0

I am trying to implement a feature on an Android app that it can auto detect new app updates, then install and restart the app without any user actions required. The platform is Android 10 and the compile sdk version is 28,

The android device is used as the UI for an unattended vending machine, therefore I am trying to eliminate the user actions for updating the app.

I came up with the following code with the help from Android: install .apk programmatically [duplicate] but I encountered two issues:

  1. The check existence of file works but file.delete(); never worked.
  2. The intent to run the apk file startActivity(intent); can be started, but the OS pops up an error: There was a problem while parsing the package. I followed this post but it didn't work.

Below is the code:

  1. Code to check the updates:
    new AppUpdaterUtils(this)
                    .setUpdateFrom(UpdateFrom.GITHUB)
                    .setGitHubUserAndRepo(user, repo)
                    .withListener(new AppUpdaterUtils.UpdateListener() {
                        @Override
                        public void onSuccess(Update update, Boolean isUpdateAvailable) {
                            if(isUpdateAvailable){
                                URL u = update.getUrlToDownload();
                                String url = "https://github.com/"+gitUser+"/"+repo+"/releases/download/v"+update.getLatestVersion()+"/"+appName;
                                update(url, appName);
                            }
                        }
    
                        @Override
                        public void onFailed(AppUpdaterError error) {
                            Log.e("UPDATE", "Failed");
                        }
                    })
                    .start();
  1. Code for download, install and restart:
    public void update(String url, String fileName){
        //get destination to update file and set Uri
        String destination = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString();// + File.separator;
        final Uri destUri = Uri.parse("file://" + destination +File.separator+ fileName);
        Log.d("UPDATE", "destUri = " + destUri.toString());

        //Delete update file if exists
        File file = new File(destination + File.separator+fileName);

        if (file.exists()){
            boolean deleteSuccess = file.delete();
            Log.d("UPDATE", "file exists! Delete = " + deleteSuccess);
        }


        //set downloadmanager
        DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
        request.setDescription("add description here");
        request.setTitle("update");

        //set destination
        request.setDestinationUri(destUri);

        // get download service and enqueue file
        final DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
        final long downloadId = manager.enqueue(request);
        file.setReadable(true, false);

        //set BroadcastReceiver to install app when .apk is downloaded
        BroadcastReceiver onComplete = new BroadcastReceiver() {
            public void onReceive(Context ctxt, Intent intent) {

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    Uri apkUri = FileProvider.getUriForFile(getApplicationContext(), BuildConfig.APPLICATION_ID + ".provider", file);
                    intent = new Intent(Intent.ACTION_VIEW);
                    intent.setDataAndType(apkUri,"application/vnd.android.package-archive");
                    intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                } else {
                    Uri apkUri = Uri.fromFile(file);
                    intent = new Intent(Intent.ACTION_VIEW);
                    intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                }
                startActivity(intent);
                finish();
            }
        };
        
        //register receiver for when .apk download is compete
        registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
    }
  1. Added res/xml/provider_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_download" path="Download"/>
</paths>
  1. Added provider to AndroidManifest.xml
<provider
  android:name="androidx.core.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>
  1. Added permissions WRITE_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE, INTERNET and REQUEST_INSTALL_PACKAGES

0 Answers0