In practical development, you may encounter other apk s packaged in your own application and installed together. Here are the steps:
First copy the test.apk to the main/assets directory and apply for read and write access to the memory card in the manifest file:
Additionally, mobile phones with 6.0 or more require dynamic permissions in the code:<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this,Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_CODE);
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { // super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == REQUEST_CODE) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) { ... } else { finish(); } return; } }
To be compatible with phones over 7.0, to use a provider, add a provider under the application node in the manifest file:
<manifest> ... <application> ... <provider android:name="android.support.v4.content.FileProvider" android:authorities="com.example.app.fileprovider" //Custom name To avoid duplication, the recommended setting is: Package name.fileprovider android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths" /> </provider> ... </application> </manifest>
Then create a new XML folder in the res directory and a new provider_paths.xml file in the XML folder (corresponding to the resource in the provider):
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <!--"."Represents all paths--> <external-path name="external_files" path="."/> <!--Fill in your package name--> <external-path path="Android/data/com.example.app/" name="share_files_path" /> <external-path path="." name="root_path" /> </paths>
Copy test.apk from the assets directory to the memory card:
/** * Copy files to SD card * @param context * @param fileName Copied file name * @param path Saved directory path * @return */ public static Uri copyAssetsFile(Context context, String fileName, String path) { try { InputStream mInputStream = context.getAssets().open(fileName); File file = new File(path); if (!file.exists()) { file.mkdir(); } File mFile = new File(path + File.separator + "test.apk"); if(!mFile.exists()) mFile.createNewFile(); LogUtil.e(TAG,"Start Copying"); FileOutputStream mFileOutputStream = new FileOutputStream(mFile); byte[] mbyte = new byte[1024]; int i = 0; while((i = mInputStream.read(mbyte)) > 0){ mFileOutputStream.write(mbyte, 0, i); } mInputStream.close(); mFileOutputStream.close(); Uri uri = null; try{ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){ //Package name.fileprovider uri = FileProvider.getUriForFile(context, "com.example.app.fileprovider", mFile); }else{ uri = Uri.fromFile(mFile); } }catch (ActivityNotFoundException anfe){ LogUtil.e(TAG,anfe.getMessage()); } MediaScannerConnection.scanFile(context, new String[]{mFile.getAbsolutePath()}, null, null); LogUtil.e(TAG,"Copy complete:" + uri); return uri; } catch (IOException e) { e.printStackTrace(); Log.e(TAG, fileName + "not exists" + "or write err"); return null; } catch (Exception e) { return null; } }
Then install test.apk,
/** * Install apk * @param uri apk Stored Path * @param context */ public static void openApk(Uri uri, Context context) { Intent intent = new Intent(); intent.setAction(Intent.ACTION_VIEW); if (Build.VERSION.SDK_INT >= 24) { intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.setDataAndType(uri, "application/vnd.android.package-archive"); } else { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); } intent.setDataAndType(uri, "application/vnd.android.package-archive"); context.startActivity(intent); }
Finally, you can check to see if test.apk is installed:
/** * App Is it installed * @param mContext * @param packageName Package Name * @return */ private boolean isAppInstall(Context mContext, String packageName){ PackageInfo mInfo; try { mInfo = mContext.getPackageManager().getPackageInfo(packageName, 0 ); } catch (Exception e) { // TODO: handle exception mInfo = null; Log.i(TAG, "Installed package name not found"); } if(mInfo == null){ return false; }else { return true; } }