当前位置: 首页 > 知识库问答 >
问题:

Android:下载并安装更新APK而不使用Google Play商店会导致APK解析错误

姬心思
2023-03-14

我有一个Android应用程序,因为项目需求,不能放在商店。但我希望当我修复错误或推出新功能时,有限的用户可以更新应用程序。为此,我使用AppUpdater库(https://github.com/javiersantos/AppUpdater),以检查应用程序的新版本是否可用,并且我为“Update Now”按钮创建了一个监听器,该监听器触发带有ProgressBar的DownloadManager,下载smartphone中的APK文件,然后我使用找到的一些代码尝试自动安装它。下载工作良好,但当安装代码执行时,我收到这个错误:“parse Error:There is a problem parsing The package”。我已经激活了“USB调试”模式,“未知源”,并且APK没有损坏。可能我提供了一个错误的文件路径到安装代码?如何正确找到路径?还有别的建议吗?谢谢!这是我的代码:

清单权限:

<!-- Needs internet to connect to Google Services -->
    <uses-permission android:name="android.permission.INTERNET"/>
    <!-- Permission to check internet connection state -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <!-- Keeps processor from sleeping when a message is received. -->
    <uses-permission android:name="android.permission.WAKE_LOCK"/>
    <!-- Permission to vibrate when receive a notification -->
    <uses-permission android:name="android.permission.VIBRATE"/>
    <!-- Lets app receive data messages. -->
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/>
    <!-- Permission to set alarms again when device is rebooted -->
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <!-- Permission to disable the keylock -->
    <uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>
    <!-- Permission to write to external storage -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <!-- Permission to read from external storage -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

AppUpdater库代码(我将其放在MainActivity的onResume()方法中):

 // Check for app's updates with confirmation dialog
 AppUpdater appUpdater = new AppUpdater(this);

 appUpdater.setUpdateFrom(UpdateFrom.JSON)
           .setUpdateJSON(Constants.URL_UPDATE_JSON)
           .setDisplay(Display.DIALOG)
           .setButtonDoNotShowAgain(null)
           .setTitleOnUpdateAvailable("Available update")
           .setContentOnUpdateAvailable("Do you want to update the app?")
           .setButtonUpdate("Update now")
           .setButtonUpdateClickListener(new UpdateButtonClickListener(this))
           .setButtonDismiss("Later")
           .setIcon(R.mipmap.icon_icare)
           .showAppUpdated(false);

 appUpdater.start();

UpdateButtonClickListener:

public class UpdateButtonClickListener implements DialogInterface.OnClickListener
    {
     Context context;

     ProgressDialog progressDialog;

     // Constructor
     public UpdateButtonClickListener(Context context)
        {
         this.context = context;
         this.progressDialog = new ProgressDialog(context);
        }


     @Override
     public void onClick(DialogInterface dialogInterface, int i)
        {
         progressDialog.setMessage("Downloading app");
         progressDialog.setIndeterminate(false);
         progressDialog.setMax(100);
         progressDialog.setProgressNumberFormat("");
         progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
         progressDialog.setCancelable(false);

         // Download APK file from server and install it
         DownloadFile downloadFile = new DownloadFile();
         downloadFile.execute();  
        }


     private class DownloadFile extends AsyncTask<Void, Void, Void>
        {
         @Override
         protected Void doInBackground(Void... voids)
            {
             Uri apk_uri = Uri.parse(Constants.URL_UPDATE_APK);

             DownloadManager.Request request = new DownloadManager.Request(apk_uri);

             request.setTitle("Downloading app");
             request.setDescription("Please wait while downloading the updated app");

             request.setDestinationInExternalFilesDir(context, null, Constants.APK_NAME);

             // enqueue this request
             DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
             long downloadID = downloadManager.enqueue(request);

             boolean downloading = true;

             while(downloading)
                {
                 DownloadManager.Query q = new DownloadManager.Query();
                 q.setFilterById(downloadID);

                 Cursor cursor = downloadManager.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;
                     progressDialog.dismiss();

                     // ---- IS THE PATH CORRECT? I WANT THE PATH OF THE FILE JUST DOWNLOADED
                     String localFilePath = cursor.getString(cursor.getColumnIndex("local_uri"));

                     File apkFile = new File(localFilePath);

                     // ---- THIS IS THE INSTALLATION CODE
                     Intent intent = new Intent(Intent.ACTION_VIEW);
                     intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
                     context.startActivity(intent);
                    }

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

                 progressDialog.setProgress(dl_progress);

                 //Toast.makeText(context, statusMessage(cursor), Toast.LENGTH_LONG).show();

                 cursor.close();
                }

             return null;
            }


         private String statusMessage(Cursor c)
            {
             String msg;
             switch(c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS)))
                {
                 case DownloadManager.STATUS_FAILED:
                        msg = "Download failed!";
                        break;

                 case DownloadManager.STATUS_PAUSED:
                        msg = "Download paused!";
                        break;

                 case DownloadManager.STATUS_PENDING:
                        msg = "Download pending!";
                        break;

                 case DownloadManager.STATUS_RUNNING:
                        msg = "Download in progress!";
                        break;

                 case DownloadManager.STATUS_SUCCESSFUL:
                        msg = "Download complete!";
                        break;

                 default:
                        msg = "Download is nowhere in sight";
                        break;
                }

             return msg;
            }


         @Override
         protected void onPreExecute()
            {
             super.onPreExecute();
             progressDialog.show();
            }


         @Override
         protected void onPostExecute(Void aVoid)
            {    
             super.onPostExecute(aVoid);
            }
        }
    }

编辑:

我快到了!正如我所想的,错误是到APK文件的路径不正确。我替换了这行代码:

File apkFile = new File(context.getExternalFilesDir(null), Constants.APK_NAME);

共有1个答案

胡星汉
2023-03-14

这里是这样的,因为写入外部存储在危险许可权列表中,即使您在清单中声明了它,并且如果用户拒绝了它,您就不能执行需要此许可权的操作。请通过这些链接

危险权限https://developer.android.com/guide/topics/permissions/requesting.html#正常-危险

如何在Marshmallow中处理权限

https://developer.android.com/guide/topics/permissions/requesting.html

https://developer.android.com/training/permissions/requesting.html

intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 
 类似资料:
  • 首先,当你的手机上有应用程序,并且这个应用程序在play store上有更新时,google只返回更新的部分代码而不是整个包(例如3毫克而不是8毫克,这是整个包的大小)。我研究并发现,在android端,google play提取本地应用程序并合并从play store下载的更新文件,生成新的apk,然后安装新的apk和更新。假设play store没有apk keystore来签署新的apk,但

  • 我正在慢慢尝试在中执行一些简单的任务。以下应用程序安装在模拟器上,没有任何错误。但是当我尝试将其安装在真实设备Redmi 3S上时,出现了此错误: 我在这里遇到过类似的问题,但在这些情况下,错误是由于未启用调试或未访问应用程序安装而导致的。然而,我允许调试,我还尝试在Studio中安装其他一些应用程序,并且运行良好。 所以问题可能是,代码出了什么问题。 主要活动.java xml代码是: acti

  • 我创建了一个基本的Android应用程序作为实习。创建了它的APK并尝试通过USB电缆将其连接到笔记本电脑并用作模拟器在我的手机上运行,它运行良好。我的Android操作系统版本是Oreo,我尝试在Lollypop上做同样的事情,但它仍然在执行。 当我通过电子邮件发送APK并尝试直接安装在设备上时,问题就来了,它给了我这个错误 解析包时出现问题 我不知道发生了什么,因为它是从Android Stu

  • 我已经上传了两个APK文件到Google Play商店。一个是较新的版本,一个是较旧的版本。较新的版本是活动的版本,因为它有较高的版本名和代码。现在我在较新的版本中发现了一些bug,我想把它从Play Store中删除,并激活较旧的版本。Google Play不会让我停用较新的一个,再激活较旧的一个,因为它有一个较低的版本名和代码。问题是,我不是开发者,也没有构建应用程序。开发商在另一个国家,很难

  • 下面是file_paths XML:

  • 本文向大家介绍Android安装apk文件并适配Android 7.0详解,包括了Android安装apk文件并适配Android 7.0详解的使用技巧和注意事项,需要的朋友参考一下 Android安装apk文件并适配Android 7.0详解 首先在AndroidManifest.xml文件,activity同级节点注册provider: 将apk文件下载到此路径: 在res目录xml文件夹下创