In APK development, it is not difficult to open the system installation program through Java code to install the APK. Generally, Android systems have this function to open.
- However, with the iteration of the Android system version, its control over permissions becomes increasingly strict, or it is becoming more and more concerned about security. This leads to the functions that could be implemented in the past with a few simple lines of code, which are now much more complicated.
- The watershed of the limitation of opening the system installer through code is Android 7.0, that is, Android N. Usually one method is used on systems above Android N, and another method is used below.
- Traditional way to install APK through code
File apk = new File(...); Uri uri = (apk); Intent intent = new Intent(); ("", ""); (uri); (Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent);
This method is simple, crude and practical. Just know the location of the APK to be installed and have access rights.
But now the mainstream Android mobile phone system versions on the market are already higher than 7.0, and this method is almost useless
How to install APK through code on higher version systems
File apk = new File(...); Intent intent = new Intent(Intent.ACTION_VIEW); (Intent.FLAG_ACTIVITY_NEW_TASK); (Intent.FLAG_GRANT_READ_URI_PERMISSION); Uri uri = (this, "", apk); (uri, "application/-archive"); startActivity(intent);
Speaking of permission issues, with the continuous improvement of Android version, the system's security is getting higher and higher. Many permissions are not just registered in the manifest file. The read and write permissions of the memory card are dangerous permissions, and we need to use the code to dynamically add them. Here I use the RxPermiision framework. The method of obtaining permissions when encountering a system of 9.0 or higher may be different.
private void rxPermission() { RxPermissions rxPermissions = new RxPermissions(this); (.WRITE_EXTERNAL_STORAGE).subscribe(new Consumer<Boolean>() { @Override public void accept(Boolean granted) throws Exception { if (granted) { //Permissions allowed //You can add your own operations here } else { // Permission denied } } }); }
For more permissions on Android, you need to query:/p/24f79a70025b
The above code installation code does not seem to be much different from the traditional method, right?
It's true, but the real difference is not reflected in Java code.
In higher version systems, APKs can no longer directly access private data of other APKs.
What is private data for APK?
The exclusive directory created by APK in the data directory during installation is naturally its private data. In addition, as long as it is a File object encapsulated in the application, regardless of whether the file itself is created by the program or not, the file belongs to the program's "private data". For example, suppose we connect our phone to the computer and push an APK file into the sdcard directory through adb push. Then we wrote a piece of code ourselves and passed the installation package in the sdcard to the system PackageInstaller for installation. They would report a security error, because this file located in the sdcard directory is "private data" for our code and is not allowed to be directly exposed to the PackageInstaller.
Let’s take a look at the methods of exposing “private data” to other programs in higher version systems.。
In higher versions, Android 7.0 and above, the only way to open (expose) private data is through ContentProvider.
The specific steps are roughly as follows:
- ContentProvider information in configuration;
- Configure paths information to be opened;
- Encapsulate file information through FileProvider in Java code.
1. Configuration
As mentioned earlier, in a higher version of the system, it is actually to turn the previous direct opening into indirect opening through ContentProvider. Therefore, we need to add a provider tag to it, the example is as follows:
<provider android:name="" android:authorities="" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name=".FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
- The android:name property fills in the full name of the FileProvider class. This class can fill in two values, one is located under the support (.) package and the other is located under the androidx() package. Both of these can be filled in, and there is no difference in essence. However, you have to decide which one to use according to the actual situation, that is, whether your project is introducing an Androidx support package or a support package. This article will not repeat the relationship between support and androidx.
- The android:authorities property is the uri tag header used to access file resources like the ordinary ContentProvider. The value content can be filled in according to actual needs.
- Android:exported This property indicates whether other apps can access this provider
- android:grantUriPermissions This property is used to authorize the data subset of the content provider
- If the grantUriPermissions property of the content provider is set to true, then permissions can be granted to any data within the scope of the content provider. However, if the grantUriPermission property is set to false, then permissions can only grant subsets of data specified by this element. A content provider can contain any number of elements. Each can only specify one path (one of three possible properties).
- What needs to be paid attention to in the content in the meta-data tag is the content in the android:resource attribute. The value of this property leads to a self-configured xml file. This xml file records the path information in the device. It simply understands that what directory file resources you want to open for third parties to use. For the configuration of this xml, please refer to the records in step 2.
2. Paths configuration
- The usual practice is to create a new xml directory in the project res directory and create a new xml file in the xml directory. The name of the file must be consistent with the configuration in the @xml/ attribute value in step 1.
- According to the sample code in step 1, we need to create a new file_paths.xml file. Here, my apk is reserved in the program's file file and the content of the file is as follows:
<?xml version="1.0" encoding="utf-8"?> <paths> <files-path path="apk/" name="apk" /> </paths>
For other path configuration methods, please refer to:/md?articleId=106670247
Simply put, select the type of path you want to open out, and then fill in the relative path under that type.
Let's talk about it in detail with examples:
<?xml version="1.0" encoding="utf-8"?> <paths> <files-path path="apk/" name="apk" /> </paths>
This means that we want to open the files directory in the program memory, and then the subpath in the files directory is /apk, and the absolute path is /data//files/apk. As for the name tag, it is used for ContentProvider tags. Generally speaking, it is enough to set it to different values as needed. I have a subdirectory here.
3. Java code configuration
There is nothing special about the Java code configuration, just use the code in the first part of the chapter. The key code actually has only one line:
Uri uri = (context, authority, file);
The three parameters here are:
- context: This means that a context needs to be passed over
- Authority: You can get it in the code
- file: It is the installation file you need
String authority = new StringBuilder(packageName).append(".provider").toString(); //The path + name of the strFile file here; for example: /data/file/apk/File f=new File(strFile); Uri uri = (context, authority, file);
Usually we will take into account both the high and low versions of Android, so we will use the "hybrid" code shown below:
public void install(){ try{//There are read and write files here, and you need to deal with exceptions Intent intent = new Intent(Intent.ACTION_VIEW); (Intent.FLAG_ACTIVITY_NEW_TASK); (Intent.FLAG_GRANT_READ_URI_PERMISSION); if (.SDK_INT >= Build.VERSION_CODES.N){ //If SDK version >=24, that is: .SDK_INT >=24 String packageName = ().getPackageName(); String authority = new StringBuilder(packageName).append(".provider").toString(); uri = (context, authority, file); (uri, "application/-archive"); } else{ uri = (file); (uri, "application/-archive"); } (intent); }catch (Exception e) { (); } }
Summarize
This is the end of this article about how to install APK through Android through code. For more related android code installation content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!