在自定义应用程序中以编程方式安装 apk 时解析包时出错
error in parsing the package while installing apk programatically within the custom app
我正在构建一个应用程序,其中我使用下载管理器从 firebase 下载 apk,并希望在完成下载后在应用程序中自动安装 apk。
问题:完成下载 apk 后,安装过程无法运行,它会抛出错误“解析包时出错”,但手动运行(当我在后台点击下载通知时,安装过程有效但不在应用程序内)
我通过搜索同样的错误尝试了很多关于 Whosebug 的解决方案,但我没有弄清楚我在哪里做错了..
这是我的下载 apk 代码:
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();
}
这是我的 installapk 代码:
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();
}
}
希望这会起作用我刚刚将它从 kotlin 转换为 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));
}
我正在构建一个应用程序,其中我使用下载管理器从 firebase 下载 apk,并希望在完成下载后在应用程序中自动安装 apk。
问题:完成下载 apk 后,安装过程无法运行,它会抛出错误“解析包时出错”,但手动运行(当我在后台点击下载通知时,安装过程有效但不在应用程序内)
我通过搜索同样的错误尝试了很多关于 Whosebug 的解决方案,但我没有弄清楚我在哪里做错了..
这是我的下载 apk 代码:
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();
}
这是我的 installapk 代码:
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();
}
}
希望这会起作用我刚刚将它从 kotlin 转换为 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));
}