Programmatically install an apk in Android 7 / api24

后端 未结 8 1775
夕颜
夕颜 2020-12-31 07:39

I am trying to get my app to automatically install an apk. This works fine for api<24. But for 24, it is failing. Android has implemented extra security:

相关标签:
8条回答
  • 2020-12-31 08:11

    Intall Apk automatically

    Intent intent1 = new Intent(Intent.ACTION_INSTALL_PACKAGE);
                intent1.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                intent1.setDataAndType(Uri.fromFile(new File(Environment.getExternalStorageDirectory() + "/download/" +filename)), "application/vnd.android.package-archive");
                intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    
    0 讨论(0)
  • 2020-12-31 08:11

    In my case on android 8.0 problem was in

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    More detailed how to get this permission Exception 'open failed: EACCES (Permission denied)' on Android

    0 讨论(0)
  • 2020-12-31 08:15

    simply do the following steps:

    1- add the following permission to manifest:

     <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
    

    2- Add provider to manifest (as child as application tag):

     <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="tatcomputer.ir.libraryapp.provider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/paths"/>
        </provider>
    

    3- Add paths.xml to xml directory:

    <?xml version="1.0" encoding="utf-8"?>
    <paths xmlns:android="http://schemas.android.com/apk/res/android">
    <files-path name="files" path="." />
    <external-files-path name="external_files" path="." />
    <external-path name="external_files" path="." />
    <cache-path name="cached_files" path="." />
    <external-cache-path name="cached_files" path="." />
    </paths>
    

    4- show install apk page using following code (note that in my case apk is in root of my phone named tmp.apk:

           String root = Environment.getExternalStorageDirectory().toString();
    
            Uri fileUri24 = FileProvider.getUriForFile(App.applicationContext, BuildConfig.APPLICATION_ID + ".provider", new File(root + "/tmp.apk"));
            Uri fileUri = Uri.fromFile(new File(root + "/tmp.apk"));
    
            Intent intent = new Intent(Intent.ACTION_VIEW);
            if (Build.VERSION.SDK_INT >= 24)
                intent.setDataAndType(fileUri24, "application/vnd.android.package-archive");
            else intent.setDataAndType(fileUri, "application/vnd.android.package-archive");
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            App.applicationContext.startActivity(intent);
    
    0 讨论(0)
  • 2020-12-31 08:21

    Here is the solution I have found

    val newFile = File(dirPath, "$fileNameWithoutExtn.apk")
                            var fileUri = Uri.fromFile(newFile)
                            //use the fileProvider to get the downloaded from sdcard
                            if (Build.VERSION.SDK_INT >= 24) {
                                fileUri = FileProvider.getUriForFile(this@SettingAcitivity, applicationContext.packageName + ".provider", newFile)
                             val intent=Intent(Intent.ACTION_VIEW)
                                intent.setDataAndType(fileUri, "application/vnd.android.package-archive")
                                intent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
                                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
                                startActivity(intent)
                            }else{
                                newFile.setReadable(true, false)
                                val intent = Intent(Intent.ACTION_VIEW)
                                intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK
                                intent.setDataAndType(fileUri, "application/vnd.android.package-archive")
                                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
                                startActivity(intent)
                            }
    

    and write in manifest

    <provider
                android:name="android.support.v4.content.FileProvider"
                android:authorities="${applicationId}.provider"
                android:exported="false"
                android:grantUriPermissions="true">
                <meta-data
                    android:name="android.support.FILE_PROVIDER_PATHS"
                    android:resource="@xml/paths"/>
    

    and also set the permission

    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
    

    and in xml folder paths will be

    <paths>
        <external-path
            name="external_files"
            path="." />
    </paths>
    
    0 讨论(0)
  • 2020-12-31 08:29

    Are there any ways to allow an app to progammatically install an apk with api24?

    Add addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) to your promptInstall setup, to grant read access to the content.

    I have export=true in my manifest.

    Not on your FileProvider, as that would cause your app to crash.

    The problem seems to be that packageinstaller cannot use a content:// uri.

    No, the problem is that you did not grant permission to the package installer to read from that Uri. Had the package installer been unable to use a content scheme, you would have gotten an ActivityNotFoundException.

    Note, though, that it is only with Android 7.0 that the package installer starts supporting content. Earlier versions of Android have to use file.

    0 讨论(0)
  • 2020-12-31 08:31

    Add file in res/xml -> provider_paths.xml

    <?xml version="1.0" encoding="utf-8"?>
    <paths xmlns:android="http://schemas.android.com/apk/res/android">
        <external-path name="external_files" path="."/>
    </paths>
    

    Add this code in AndroidManifest.xml

         <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.example.provider" <-- change this with your package name
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths"/>
        </provider>
    

    run this code for install your app or open

        public void installApk(String file) {
            Uri uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider",new File(file));
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(uri, "application/vnd.android.package-archive");
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            context.startActivity(intent);
        }
    
    0 讨论(0)
提交回复
热议问题