androidinstallationapkandroid-fileprovider

FileProvider: Installing APK. There was an error parsing the package.


I have an APK-File in /storage/emulated/0/Download/app-debug.apk. I want to install this file by FileProvider because I am using Android N.

When I try to launch the intent logcat doesn't show any error but I receive following message on my phone:

There was a problem parsing the package.

What am I doing wrong?

MainActivity

public class MainActivity extends AppCompatActivity {

Button btnStartIntent;
String strRootPathInternalStorage = Environment.getExternalStorageDirectory().toString();       //-> /storage/emulated/0     //-> /storage/emulated/0/Download/
String strApkToInstall = "app-debug.apk";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

/*
        --> Booooh bad way! <--
        StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
        StrictMode.setVmPolicy(builder.build());
*/

    btnStartIntent = (Button)findViewById(R.id.btnStartIntent);
    btnStartIntent.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            installApk(MainActivity.this, strRootPathInternalStorage+"/Download/"+strApkToInstall);
        }
    });
}

public static void installApk(Context context, String apkPath) {
    if (context == null || TextUtils.isEmpty(apkPath)) {
        return;
    }


    File file = new File(apkPath);
    Intent intent = new Intent(Intent.ACTION_VIEW);

    if (Build.VERSION.SDK_INT >= 24) {
        //provider authorities
        Uri apkUri = FileProvider.getUriForFile(context, "com.spicysoftware.test.provider", file);
        //Granting Temporary Permissions to a URI
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
    } else {
        intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
    }

    context.startActivity(intent);
}

}

Manifest

<?xml version="1.0" encoding="utf-8"?>

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">


    <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="com.spicysoftware.test.provider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_paths"/>
    </provider>

    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

provider_paths.xml

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

Solution

  • For anyone who has the same problem. I had to specify the exactly folder with getExternalFilesDir();

    MainActivity

    public class MainActivity extends AppCompatActivity {
    
        Button btnStartIntentFileProvider;
        String strRootPathInternalStorage = Environment.getExternalStorageDirectory().toString();         
        String strApkToInstall = "app-debug.apk";
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            btnStartIntentFileProvider = (Button)findViewById(R.id.btnFileProvider);
            btnStartIntentFileProvider.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
    
                    File fileApkToInstall = new File(getExternalFilesDir("Download"), strApkToInstall);  
    
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                        Uri apkUri = FileProvider.getUriForFile(MainActivity.this, BuildConfig.APPLICATION_ID + ".provider", fileApkToInstall);
                        Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
                        intent.setData(apkUri);
                        intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                        MainActivity.this.startActivity(intent);
                    } else {
                        Uri apkUri = Uri.fromFile(fileApkToInstall);
                        Intent intent = new Intent(Intent.ACTION_VIEW);
                        intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        MainActivity.this.startActivity(intent);
                    }
                }
            });
        }
    }
    

    Manifest

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.spicysoftware.test">
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
            <provider
                android:name="android.support.v4.content.FileProvider"
                android:authorities="com.spicysoftware.test.provider"
                android:exported="false"
                android:grantUriPermissions="true">
                <meta-data
                    android:name="android.support.FILE_PROVIDER_PATHS"
                    android:resource="@xml/provider_paths"/>
            </provider>
    
            <activity android:name=".MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    </manifest>
    

    provider_paths (in XML Folder)

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