Emre Can Serteli Emre Can Serteli - 5 months ago 72
Android Question

Trying to update my apk programmatically results in parse error

I need to update my application without Google Play. So I uploaded my apk to my server to be downloaded when needed.

It's downloaded fine by the following code, but when the installation intent is started it's throwing: "Parse Error: There is a problem parsing the package"

If I try to run the downloaded apk manually, it still gives the same error.

BUT, if I transfer the apk by USB and then run it, it installs smoothly. So this problem is not about the apk itself.

Here is my Task class:

class Update implements Runnable {
@Override
public void run() {
FTPClient ftpClient = new FTPClient();
try {
ftpClient.connect(InetAddress.getByName("mysite.com"));
ftpClient.login("mysite.com", "123456"));
ftpClient.enterLocalPassiveMode();
String remoteFile1 = "/httpdocs/program/app-release.apk";
String downPath = getExternalStoragePublicDirectory(DIRECTORY_DOWNLOADS).getAbsolutePath();
File myapk = new File(downPath + "/app-release.apk");
OutputStream outputStream1 = new BufferedOutputStream(new FileOutputStream(myapk));
boolean success = ftpClient.retrieveFile(remoteFile1, outputStream1);
outputStream1.close();
myapk.setReadable(true, false);
if (!success) {
ftpClient.logout();
ftpClient.disconnect();
return;
} else {
Intent promptInstall = new Intent(Intent.ACTION_VIEW)
.setDataAndType(Uri.fromFile(myapk), "application/vnd.android.package-archive")
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(promptInstall);
}
}
catch (Exception ex) {
//catch exception
}
}
}

Answer

Alright, it was my own mistake. Sorry for anyone scanned up and frustrated about my perfectly fine working code.

The reason was me, trying to update the app I ran directly from Android Studio over USB. Despite it's been running on "Release" mode, it throws the parse error on the newly downloaded apk file (I'm still not sure why).

So, I just generated a signed apk with proper (lower) versioning; copy it into the phone and then install. Only then, the app can properly download and run the newer versioned apk file. Updating itself as expected.

Let this be an example case for anyone did the same thing as me. Use generated apk when testing for a manual update function.

Lastly, I want to share my code. I changed it from FTP to direct download via HttpURLConnection. Both versions work fine (the code in the question and this). So feel free to choose the one suits your job.

class Update implements Runnable {
    @Override
    public void run() {
        try {
            URL url = new URL("mysite.com/app-release.apk");
            HttpURLConnection c = (HttpURLConnection) url.openConnection();
            c.setRequestMethod("GET");
            c.setDoOutput(true);
            c.connect();
            String PATH = getExternalStoragePublicDirectory(DIRECTORY_DOWNLOADS).getAbsolutePath();
            File file = new File(PATH);
            File outputFile = new File(file, "app-release.apk");
            FileOutputStream fos = new FileOutputStream(outputFile);
            InputStream is = c.getInputStream();
            byte[] buffer = new byte[1024];
            int len1 = 0;
            while ((len1 = is.read(buffer)) != -1) {
                fos.write(buffer, 0, len1);
            }
            fos.close();
            is.close();
            Intent promptInstall = new Intent(Intent.ACTION_VIEW)
                    .setDataAndType(Uri.fromFile(outputFile), "application/vnd.android.package-archive")
                    .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(promptInstall);
        } catch (Exception ex) {
            //catch exception
        }
    }
}
Comments