1

I am trying to write a function to update my android app without google play from within the app. I based my code very heavily off of the answer from this stackoverflow question. I've been able to fix most of the problems that have occurred but I'm now getting "Parse Error: There is a problem parsing the package". I've looked around for answers to this problem and I feel I have eliminated the obvious responses as the cause. I know the package is not corrupted because I ran my app in an emulator then used the monitor to get the apk file from the data/data location, uploaded the apk to my website, then downloaded the apk on my phone, and installed it from the download manager and it worked. Here is the code:

MainActivity calls asynctask that checks if the current version is equivalent to the most recent version online.

public class MainActivity extends Activity {

ListView list;
//private ProgressBar pb;

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

    //pb.setVisibility(View.VISIBLE);

    int v = 0;
    try {
        v = getPackageManager().getPackageInfo(getPackageName(), 0).versionCode;
    } catch (PackageManager.NameNotFoundException e) {
        // Huh? Really?
    }
    new CheckUpdates(this).execute(v);
}
}

If there is a newer version then it calls the InstallUpdate asynctask.

private class CheckUpdates extends AsyncTask<Integer, Integer, String>{
    private Context mContext;
    private ProgressDialog pdia;

    public CheckUpdates (Context c) {
        this.mContext = c;
    }

    @Override
    protected void onPreExecute(){
        super.onPreExecute();
        pdia = new ProgressDialog(mContext);
        pdia.setMessage("Checking for update...");
        pdia.show();
    }

    @Override
    protected String doInBackground(Integer... params) {
        return postData(params[0]);
    }

    @Override
    protected void onPostExecute(final String responseString){
        pdia.dismiss();

        if (!responseString.equals("")) {
            AlertDialog dialog = new AlertDialog.Builder(mContext).create();
            dialog.setTitle("Confirmation");
            dialog.setMessage("There is an update. Download and Install?");
            dialog.setCancelable(false);
            dialog.setButton(DialogInterface.BUTTON_POSITIVE, "Yes", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int buttonId) {
                    new InstallUpdate(mContext).execute("apk url");
                }
            });
            dialog.setButton(DialogInterface.BUTTON_NEGATIVE, "No", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int buttonId) {
                }
            });
            dialog.setIcon(android.R.drawable.ic_dialog_alert);
            dialog.show();
        }
    }

    public String postData(Integer version) {
        HttpClient httpclient = new DefaultHttpClient();
        // specify the URL you want to post to
        HttpPost httppost = new HttpPost("check for update php file");
        HttpResponse response = null;
        try {
            // create a list to store HTTP variables and their values
            List nameValuePairs = new ArrayList();
            // add an HTTP variable and value pair
            nameValuePairs.add(new BasicNameValuePair("currentVersion", Integer.toString(version)));
            httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
            // send the variable and value, in other words post, to the URL
            response = httpclient.execute(httppost);
        } catch (ClientProtocolException e) {
            // process execption
        } catch (IOException e) {
            // process execption
        }

        HttpEntity entity = response.getEntity();
        String responseString = "";
        try {
            responseString = EntityUtils.toString(entity, "UTF-8");
        } catch (IOException e) {
            //really?
        }

        return responseString;
    }
}

If there is an update, InstallUpdate is called and downloads the apk and tries to install it.

public class InstallUpdate extends AsyncTask<String, Integer, String> {
    private Context mContext;
    private ProgressDialog pdia;

    public InstallUpdate (Context c) {
        this.mContext = c;
    }

    @Override
    protected void onPreExecute(){
        super.onPreExecute();
        pdia = new ProgressDialog(mContext);
        pdia.setMessage("Downloading update");
        pdia.setIndeterminate(false);
        pdia.setMax(100);
        pdia.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        pdia.setCancelable(true);
        pdia.show();
    }

    @Override
    protected String doInBackground(String... sUrl) {
        String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/plm/update.apk";

        try {
            URL url = new URL(sUrl[0]);

            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setDoOutput(true);
            connection.connect();

            int fileLength = connection.getContentLength();

            // download the file
            InputStream input = new BufferedInputStream(url.openStream());
            OutputStream output = new FileOutputStream(path);

            byte data[] = new byte[1024];
            long total = 0;
            int count;
            while ((count = input.read(data)) != -1) {
                total += count;
                publishProgress((int) (total * 100 / fileLength));
                output.write(data, 0, count);
            }

            output.flush();
            output.close();
            input.close();
        } catch (Exception e) {
            Log.e("YourApp", "Well that didn't work out so well...");
            Log.e("YourApp", e.getMessage());
        }
        return path;
    }

    @Override
    protected void onProgressUpdate(Integer... progress) {
        Log.v("progress", Integer.toString(progress[0]));
        pdia.setProgress(progress[0]);
    }

    // begin the installation by opening the resulting file
    @Override
    protected void onPostExecute(String path) {
        pdia.dismiss();

        Intent i = new Intent();
        i.setAction(Intent.ACTION_VIEW);
        i.setDataAndType(Uri.fromFile(new File(path)), "application/vnd.android.package-archive" );
        i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        Log.d("Lofting", "About to install new .apk");
        this.mContext.startActivity(i);
    }
}

I feel like the problem is with "this.mContext.startActivity(i)" in the InstallUpdate asynctask postexecute. I don't know if using the MainActivity's context is correct or if calling it from an asynctask is causing a problem. I've been trying to find a solution online for about a week and keep coming up empty. I'm learning java and android programming as I've been writing this program so I'm not 100% sure what I'm doing, but this is the first problem I haven't been able to find a solution to on my own.

Community
  • 1
  • 1

1 Answers1

0

Then your download is not successful check the apk size which has to be same as that in the server after downloading