1. Download our Official Android App: Forums for Android!

Download And Install App Programmatically

Discussion in 'Android Development' started by Cruzeberry, Sep 13, 2017.

  1. Cruzeberry

    Cruzeberry Lurker
    Thread Starter
    Rank:
    None
    Points:
    5
    Posts:
    3
    Joined:
    Sep 13, 2017

    Sep 13, 2017
    3
    0
    5
    Male
    Hello,

    I'm currently working on an application that has been built so that it can manage upgrading and downgrading of versions away from the Play Store using my company's web servers. This worked fine until we tried compiling against Nougat.

    The following is our code to download and install the new apk file:

    // New file
    File newAPKFile = new File(context.getExternalFilesDir(null), newfileName);
    FileOutputStream fos = new FileOutputStream(newAPKFile);
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    fos = context.openFileOutput(newAPKFile.getName(), context.MODE_PRIVATE);
    } else {
    fos = context.openFileOutput(newAPKFile.getName(), context.MODE_WORLD_READABLE| context.MODE_WORLD_WRITEABLE);
    }
    // Download the new APK file
    InputStream is = httpConn.getInputStream();
    byte[] buffer = new byte[1024];
    int len1 = 0;
    while ((len1 = is.read(buffer)) != -1) {
    fos.write(buffer, 0, len1);
    }
    fos.flush();
    fos.close();
    is.close();
    // Start the standard installation window
    File fileLocation = new File(context.getExternalFilesDir(null), newfileName);
    Intent downloadIntent;
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    Uri apkUri = FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".fileProvider", fileLocation);
    downloadIntent = new Intent(Intent.ACTION_VIEW);
    downloadIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    downloadIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    downloadIntent.setDataAndType(apkUri, "application/vnd.android.package-archive");
    } else {
    downloadIntent = new Intent(Intent.ACTION_VIEW);
    downloadIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    downloadIntent.setDataAndType(Uri.fromFile(fileLocation), "application/vnd.android.package-archive");
    }
    context.startActivity(downloadIntent);​


    This is what I'm getting in logcat:

    Process: com.google.android.packageinstaller, PID: 3807
    java.lang.RuntimeException: An error occurred while executing doInBackground()
    at android.os.AsyncTask$3.done(AsyncTask.java:318)
    at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
    at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
    at java.util.concurrent.FutureTask.run(FutureTask.java:242)
    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
    at java.lang.Thread.run(Thread.java:761)
    Caused by: java.lang.SecurityException: Permission Denial: opening provider android.support.v4.content.FileProvider from ProcessRecord{d42d519 3807:com.google.android.packageinstaller/u0a17} (pid=3807, uid=10017) that is not exported from uid 10085
    at android.os.Parcel.readException(Parcel.java:1683)
    at android.os.Parcel.readException(Parcel.java:1636)
    at android.app.ActivityManagerProxy.getContentProvider(ActivityManagerNative.java:4169)
    at android.app.ActivityThread.acquireProvider(ActivityThread.java:5434)
    at android.app.ContextImpl$ApplicationContentResolver.acquireUnstableProvider(ContextImpl.java:2267)
    at android.content.ContentResolver.acquireUnstableProvider(ContentResolver.java:1515)
    at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1129)
    at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:982)
    at android.content.ContentResolver.openInputStream(ContentResolver.java:702)
    at com.android.packageinstaller.PackageInstallerActivity$StagingAsyncTask.doInBackground(PackageInstallerActivity.java:732)
    at com.android.packageinstaller.PackageInstallerActivity$StagingAsyncTask.doInBackground(PackageInstallerActivity.java:723)
    at android.os.AsyncTask$2.call(AsyncTask.java:304)


    Anybody got any ideas on this?
     

    Advertisement

  2. LV426

    LV426 Illegitimi non carborundum
    Moderator
    Rank:
     #21
    Points:
    1,238
    Posts:
    4,816
    Joined:
    Oct 16, 2015

    Oct 16, 2015
    4,816
    6,278
    1,238
    Male
    Software developer
    South West of England
  3. Cruzeberry

    Cruzeberry Lurker
    Thread Starter
    Rank:
    None
    Points:
    5
    Posts:
    3
    Joined:
    Sep 13, 2017

    Sep 13, 2017
    3
    0
    5
    Male
    I have tried a few things on that page, got me a little further...

    I'm now getting "There was a problem parsing the package", with this in logcat:

    W/zipro: Error opening archive /data/user_de/0/com.google.android.packageinstaller/cache/package158645152.apk: Invalid file
    Is this to do with where I am storing the file? No idea what that .apk file name is, must be autogenerated by the process?
     
  4. LV426

    LV426 Illegitimi non carborundum
    Moderator
    Rank:
     #21
    Points:
    1,238
    Posts:
    4,816
    Joined:
    Oct 16, 2015

    Oct 16, 2015
    4,816
    6,278
    1,238
    Male
    Software developer
    South West of England
    We need to see the full stack trace, and also the part of your code which is attempting to unpack the APK.
     
  5. LV426

    LV426 Illegitimi non carborundum
    Moderator
    Rank:
     #21
    Points:
    1,238
    Posts:
    4,816
    Joined:
    Oct 16, 2015

    Oct 16, 2015
    4,816
    6,278
    1,238
    Male
    Software developer
    South West of England
    Oh ok, as your application hasn't crashed, there won't be a stack trace. But I would like to see the code which is unpacking and installing the APK.
     
  6. Cruzeberry

    Cruzeberry Lurker
    Thread Starter
    Rank:
    None
    Points:
    5
    Posts:
    3
    Joined:
    Sep 13, 2017

    Sep 13, 2017
    3
    0
    5
    Male
    Hi, the code I'm using is as follows: (I have just been through and added some more debug lines and the size of the file in the location I'm downloading to appears to be 0, so it could be that I'm not saving the file correctly?)

    // The following sets the connection for downloading the new apk
    URL url = new URL("https://ourserver.com/ourApplication.apk");
    URLConnection conn = url.openConnection();
    HttpURLConnection httpConn = (HttpURLConnection) conn;
    httpConn.setAllowUserInteraction(false);
    httpConn.setInstanceFollowRedirects(true);
    httpConn.setRequestMethod("GET");
    httpConn.connect();
    int checkConn = httpConn.getResponseCode();

    // The following sets up the filename for saving the apk to the device
    // Also create a file output stream to write to the file
    File newAPKFile = new File(context.getExternalFilesDir(null), newfileName);
    FileOutputStream fos = new FileOutputStream(newAPKFile);
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    fos = context.openFileOutput(newAPKFile.getName(), context.MODE_PRIVATE);
    } else {
    fos = context.openFileOutput(newAPKFile.getName(), context.MODE_WORLD_READABLE| context.MODE_WORLD_WRITEABLE);
    }

    // Download the new APK file
    InputStream is = httpConn.getInputStream();
    byte[] buffer = new byte[1024];
    int len1 = 0;
    while ((len1 = is.read(buffer)) != -1) {
    fos.write(buffer, 0, len1);
    }
    fos.flush();
    fos.close();
    is.close();

    // Start the standard installation window
    File fileLocation = new File(context.getExternalFilesDir(null), newfileName);
    Intent downloadIntent;
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    Uri apkUri = FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".fileProvider", fileLocation);
    downloadIntent = new Intent(Intent.ACTION_VIEW);
    downloadIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    downloadIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    downloadIntent.setDataAndType(apkUri, "application/vnd.android.package-archive");
    List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(downloadIntent, PackageManager.MATCH_DEFAULT_ONLY);
    for (ResolveInfo resolveInfo : resInfoList) {
    String packageName = resolveInfo.activityInfo.packageName;
    context.grantUriPermission(packageName, apkUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
    }
    } else {
    downloadIntent = new Intent(Intent.ACTION_VIEW);
    downloadIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    downloadIntent.setDataAndType(Uri.fromFile(fileLocation), "application/vnd.android.package-archive");
    }
    context.startActivity(downloadIntent);
     

Share This Page

Loading...