[英]Android - Download Unsuccessful and Parsing Error while trying to download and install .apk from server
目标是在不使用 Google Play 商店的情况下更新我的应用程序。 我正在尝试从服务器下载 .apk 文件,然后以编程方式安装它。 我目前收到一个错误,即下载不成功并且解析包时出错。 我有运行时请求的 READ_EXTERNAL_STORAGE 和 WRITE_EXTERNAL_STORAGE 权限。 我必须进入平板电脑的设置才能授予“安装未知应用程序”的权限。 我无法在运行时请求 REQUEST_INSTALL_PACKAGES。
如果我更改文件名并更新 URL 以获取我存储在服务器上与 .apk 相同文件夹中的 .txt 并注释掉“.setMimeType()”,我可以下载并查看 .txt 文件。
这里有一些代码片段可以帮助
毕业:应用
android {
compileSdk 31
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "farrpro.project"
minSdk 28
targetSdk 30
}
AndroidManifest.xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
<uses-permission android:name="android.permission.ACTION_INSTALL_PACKAGE"/>
MainActivity.java
private void hasInstallPermission() { // runs in onCreate()
if (getApplicationContext().checkSelfPermission(Manifest.permission.REQUEST_INSTALL_PACKAGES) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.REQUEST_INSTALL_PACKAGES}, 1);
}
}
void downloadAndInstallUpdate(){ // runs when users accepts request to download update
String fileName = "update.apk";
// example of update’s string
update = “https://myserver.net/update.apk”;
//set download manager
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(update));
request.setTitle(fileName)
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
.setDescription("Downloading")
//.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE)
.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName)
.setMimeType("application/vnd.android.package-archive");
// get download service and enqueue file
final DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
final long downloadId = manager.enqueue(request);
System.out.println("Max Bytes: "+DownloadManager.getMaxBytesOverMobile(this)); //returns null
//set BroadcastReceiver to install app when .apk is downloaded
BroadcastReceiver onComplete = new BroadcastReceiver() {
public void onReceive(Context ctxt, Intent intent) {
System.out.println("Is download successful: "+ manager.getUriForDownloadedFile(downloadId)); //returns null
System.out.println("Mime: "+manager.getMimeTypeForDownloadedFile(downloadId)); //returns application/vnd.android.package-archive
Intent install = new Intent(Intent.ACTION_VIEW);
File file = new File(ctxt.getExternalFilesDir(null) + fileName);
Uri downloadedApk = FileProvider.getUriForFile(ctxt, "farrpro.project.provider", file);
install.setDataAndType(downloadedApk,
manager.getMimeTypeForDownloadedFile(downloadId));
install.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
try {
startActivity(install);
} catch (ActivityNotFoundException e) {
e.printStackTrace();
Log.e("TAG", "Error in opening the file!");// this never prints
}
unregisterReceiver(this);
finish();
}
};
//register receiver for when .apk download is complete
registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}
问题是服务器限制了下载类型。 在更改该设置后,我的代码或多或少地工作了。 我最终需要更改广播接收器中的意图,以便在下载完成后立即安装新的 .apk。 这是我为使发布的代码正常工作所做的更改。
final long downloadId = manager.enqueue(request);
BroadcastReceiver onComplete = new BroadcastReceiver() {
public void onReceive(Context ctxt, Intent intent1) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(manager.getUriForDownloadedFile(downloadId), "application/vnd.android.package-archive");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
try {
getApplicationContext().startActivity(intent);
} catch (ActivityNotFoundException e) {
e.printStackTrace();
Log.e("TAG", "Error in opening the file!");
}
unregisterReceiver(this);
finish();
}
};
如果您的应用在 Android O 或更新版本上运行,您必须允许应用的未知应用来源。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (!context.packageManager.canRequestPackageInstalls()) {
val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES).apply {
data = Uri.parse(String.format("package:%s", context.packageName))
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
context.startActivity(intent)
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.