Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parse error when parsing manifest

Tags:

android

I made an application that attempts to download an APK update to internal storage from a remote server, and then install the update on the device. I tested it on a API24 device and everything works as expected.

Now I am testing it on a API 19 device (to test the part of the code pertaining to the old way of updating apps) and I keep getting "Parse error when parsing manifest". What puzzles me is that I can install the APK manually on the device and there is no parse error, so I don't think the problem is in the actual manifest file. I checked the length of the downloaded APK file in the internal storage and it appears to be fully downloaded. The code for downloading the APK is the same for all API versions.

Code:

pathToApk = getFilesDir() + "/update.apk";
try (InputStream is = response.body().byteStream();
     BufferedInputStream input = new BufferedInputStream(is);
     OutputStream os = new FileOutputStream(pathToApk)) {
         byte[] data = new byte[1024];
         int count;
         while ((count = input.read(data)) != -1) {
             os.write(data, 0, count);
         }

}

File toInstall = new File(pathToApk);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
  Uri apkUri = Uri.fromFile(toInstall);
  Intent intent = new Intent(Intent.ACTION_VIEW);
  intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
  intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  startActivity(intent);
}

Error:

W/PackageParser: Unable to read AndroidManifest.xml of /data/data/my.package.name/files/update.apk
  java.io.FileNotFoundException: AndroidManifest.xml
    at android.content.res.AssetManager.openXmlAssetNative(Native Method)
    at android.content.res.AssetManager.openXmlBlockAsset(AssetManager.java:501)
    at android.content.res.AssetManager.openXmlResourceParser(AssetManager.java:469)
    at android.content.pm.PackageParser.parsePackage(PackageParser.java:544)
    at com.android.packageinstaller.PackageUtil.getPackageInfo(PackageUtil.java:73)
    at com.android.packageinstaller.PackageInstallerActivity.onCreate(PackageInstallerActivity.java:467)
    at android.app.Activity.performCreate(Activity.java:5350)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1088)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2320)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2417)
    at android.app.ActivityThread.access$800(ActivityThread.java:151)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1342)
    at android.os.Handler.dispatchMessage(Handler.java:110)
    at android.os.Looper.loop(Looper.java:193)
    at android.app.ActivityThread.main(ActivityThread.java:5322)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:515)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:829)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:645)
    at dalvik.system.NativeStart.main(Native Method)
11-10 10:16:24.213 4140-4140/? W/PackageInstaller: Parse error when parsing manifest. Discontinuing installation

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="my.package.name">

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

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity
        android:name=".main.activities.UpdateActivity"
        android:screenOrientation="portrait">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <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/provider_paths" />
    </provider>
</application>
</manifest>

EDIT

See my answer for solution.

like image 325
HomeIsWhereThePcIs Avatar asked Apr 26 '26 22:04

HomeIsWhereThePcIs


1 Answers

The problem was that the system could not read the APK from the private internal storage of my application on API<=23. The fix was pretty straightforward.

Changed this line:

OutputStream os = new FileOutputStream(pathToApk)

To this:

boolean old = Build.VERSION.SDK_INT < Build.VERSION_CODES.N;
OutputStream os = old ? 
    openFileOutput("update.apk", Context.MODE_WORLD_READABLE)
    : new FileOutputStream(pathToApk)
like image 53
HomeIsWhereThePcIs Avatar answered May 01 '26 02:05

HomeIsWhereThePcIs