Search code examples
javaandroidfirebaseapkparse-error

error in parsing the package while installing apk programatically within the custom app


Im building an application in which im downloading an apk from firebase using download manager and want to automatically install apk within the app after completing download.

problem: after complete downloading of apk the installation process does not working it throw an error "There was an error while parsing the package" but manually it is working (when i click over the notification of download in the background , installation process works but not within the app)

I have tried many solution over stackoverflow by searching this same error but i didnt got where im doing mistake..

here is my download apk code:

 private void Download() {

        //installtion permission

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            if (!getPackageManager().canRequestPackageInstalls()) {
                startActivityForResult(new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES).setData(Uri.parse(String.format("package:%s", getPackageName()))), 1234);
            } else {
            }
        }

        //Storage Permission

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
        }

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
        }

        final ProgressDialog progressBarDialog= new ProgressDialog(this);
        progressBarDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        progressBarDialog.setTitle("Downloading...");
        progressBarDialog.setProgress(0);

        Uri uri=Uri.parse(Common.Url);
        DownloadManager.Request r = new DownloadManager.Request(uri);
        r.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, Common.Apkname+".apk");
        r.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
        DownloadManager dm = (DownloadManager)getApplicationContext().getSystemService(Context.DOWNLOAD_SERVICE);
        final long downloadId =dm.enqueue(r);

           new Thread(new Runnable() {

            @Override
            public void run() {


                boolean downloading = true;


                while (downloading) {

                    DownloadManager.Query q = new DownloadManager.Query();
                    q.setFilterById(downloadId);

                    Cursor cursor = dm.query(q);
                    cursor.moveToFirst();
                    int bytes_downloaded = cursor.getInt(cursor
                            .getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
                    int bytes_total = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));

                    if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {
                        downloading = false;
                    }

                    final double dl_progress = (int) ((bytes_downloaded * 100l) / bytes_total);


                    runOnUiThread(new Runnable() {

                        @Override
                        public void run() {

                            progressBarDialog.setProgress((int) dl_progress);
                            progressBarDialog.setCanceledOnTouchOutside(false);

                        }
                    });
                    cursor.close();
                }

                progressBarDialog.dismiss();
                installAPK();
            }
        }).start();
        progressBarDialog.show();


    }

here is my installapk code:

void installAPK(){

        Context mContext = getApplicationContext();
        try {
            String PATH = Objects.requireNonNull(getApplicationContext().getExternalFilesDir(null)).getAbsolutePath();
            File file = new File(PATH + "/my_apk.apk");
            Intent intent = new Intent(Intent.ACTION_VIEW);
            if (Build.VERSION.SDK_INT >= 24) {
                Uri downloaded_apk = FileProvider.getUriForFile(mContext, mContext.getApplicationContext().getPackageName() + ".provider", file);
                intent.setDataAndType(downloaded_apk, "application/vnd.android.package-archive");
                List<ResolveInfo> resInfoList = mContext.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
                for (ResolveInfo resolveInfo : resInfoList) {
                    mContext.grantUriPermission(mContext.getApplicationContext().getPackageName() + ".provider", downloaded_apk, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
                }
                intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
                startActivity(intent);
            } else {
                intent.setAction(Intent.ACTION_VIEW);
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                intent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true);
                intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            }
            startActivity(intent);
        } catch (Exception e) {
            e.printStackTrace();
        }
   }


Solution

  • Hope this will work I just converted it from kotlin to java

    private final String APP_INSTALL_PATH = "\"application/vnd.android.package-archive\"";
    
        
    public void installAPK(String destination, Uri uri, Context context) {
        
                BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
                    @Override
                    public void onReceive(Context context, Intent intent) {
        
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
        
                            Uri fileProvider = FileProvider.getUriForFile(
                                    context,
                                    BuildConfig.APPLICATION_ID + ".provider",
                                    new File(destination));
        
                            Intent install = new Intent(Intent.ACTION_VIEW);
                            install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                            install.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                            install.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true);
                            install.setData(fileProvider) ;
                            context.startActivity(install);
                            context.unregisterReceiver(this);
        
                        } else {
        
                            Intent install = new Intent(Intent.ACTION_VIEW);
                            install.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                            install.setDataAndType(
                                    uri,
                                    APP_INSTALL_PATH
                            );
                            context.startActivity(install);
                            context.unregisterReceiver(this);
        
        
                        }
        
        
                    }
        
        
                };
        
                context.registerReceiver(broadcastReceiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
        
        
        
            }