androidapkparsing-error

Parsing error while updating app programmatically


My goal is to host an app update to remote server & check for update via API. App will check the defined url for checking the update, if response version code is greater than current code, it'll download the updated apk from server & install it by code. I hosted a PHP file for checking the version & the apk file to a server. App is downloading the apk without any problem. But after download, while installing the file, it is showing "Parse Error : There is a problem parsing the package."

I searched stackoverflow & google to get rid of the problem, but can't find any proper solution to fix this issue & install the update. All required permission have been provided. File Provider is working properly. Downloaded file is also installed manually & has been run without any issue. But the only issue arises when installing it programmatically.

This is gradle.bulid file config for lower version:

    minSdkVersion 21
    targetSdkVersion 28
    versionCode 1
    versionName "1.0"

and gradle.bulid file config for updated version:

    minSdkVersion 21
    targetSdkVersion 28
    versionCode 2
    versionName "1.1"

Following are in Manifest:

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

Declared file provider inside manifest:

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

Provider file contains:

    <paths xmlns:android="http://schemas.android.com/apk/res/android">
        <external-path path="Android/data/${applicationId}/" name="files_root" />
        <root-path name="root" path="/" />
    </paths>`

Now the coding part

to download the file I wrote

    DownloadManager.Request request = new DownloadManager.Request(Uri.parse(updateURL));
    request.setMimeType("application/vnd.android.package-archive");
    request.setTitle("Downloading " + updateURL.substring(updateURL.lastIndexOf("/") + 1));
    request.allowScanningByMediaScanner();
    //request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
    String dir = Environment.DIRECTORY_DOWNLOADS;
    String file = updateURL.substring(updateURL.lastIndexOf("/") + 1);
    request.setDestinationInExternalPublicDir(dir, file);

    downloadPathFile += "/" + file;

    Log.e("Path", downloadPathFile);

    DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
    manager.enqueue(request);
    registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));

The logcat shows the path

    E/Path: /storage/emulated/0/Download/app-debug.apk

(File is there in the Download folder & there is no issue on installing manually)

After download completing intent broadcasted by download manager, app catches that via this receiver & tries to install the updated apk.

BroadcastReceiver onComplete = new BroadcastReceiver() {
    public void onReceive(Context context, Intent intent1) {
        Toast.makeText(context, "Download Completed...", Toast.LENGTH_SHORT).show();
        Intent intent = new Intent(Intent.ACTION_VIEW);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            Uri contentUri = FileProvider.getUriForFile(MainActivity.this, context.getApplicationContext().getPackageName() + ".provider", new File(downloadPathFile));
            intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
        } else {
            intent.setDataAndType(Uri.fromFile(new File(downloadPathFile)), "application/vnd.android.package-archive");
        }
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);

        unregisterReceiver(onComplete);
    }
};

According to the tutorials & Q&A found in Google & stackoverflow, this code is correct but still it is throwing the parse error while installing programmatically.

Looking forward to get help from the community to overcome the issue. I'm always ready to share any related file or snippets of the project.

Thanks in advance.

EDIT 1: Testing device is Samsung Galaxy J8 Infinity with Android 8.0.0 (API 26)


Solution

  • I had same problem. There is an option to check canRequestPackageInstalls () in Android 8.0.0 (API 26).

    This might be the solution of your problem. Find more here