FileProvider: Installing APK. There was an error p

2019-06-14 08:31发布

问题:

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>

回答1:

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>