android - 使用 DownloadManager 下载 HTTP 资源在 android9 上不起作用
问题描述
我有一个在原生 android9 上运行的 react-native 应用程序,现在我想使用 DownloadManager 下载文件,它是一个http资源。开始下载时,没有立即显示通知,也没有下载进度,等了几分钟就显示下载失败。DownloadManager.COLUMN_REASON是 1004,根据文档,它意味着 ERROR_HTTP_DATA_ERROR。我在AndroidManifest.xml中设置了 networkSecurityConfig。如果我将文件更改为https资源,它可以正常工作,但仍然存在一个问题,即在下载完成之前它也不会在通知栏中显示下载进度。我已将NotificationVisibility设置为VISIBILITY_VISIBLE_NOTIFY_COMPLETED。正常的 http 请求,例如 get、post 效果很好。AndroidManifest.xml
...
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
<application
android:name=".MainApplication"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:allowBackup="false"
android:networkSecurityConfig="@xml/network_security_config"
android:theme="@style/AppTheme">
<uses-library
android:name="org.apache.http.legacy"
android:required="false" />
<activity
android:name=".MainActivity"
...>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
<receiver android:name="com.cityvoice.cubebrain.MyBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.DOWNLOAD_COMPLETE"/>
</intent-filter>
</receiver>
</application>
... file_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<paths>
<external-files-path path="" name="Download" />
</paths>
</resources>
network_security_config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true"/>
</network-security-config>
AndroidDownloadManager.java
public class AndroidDownloadManager {
...
public AndroidDownloadManager(Context context, String url, String name) {
this.context = context;
this.url = url;
this.name = name;
}
public AndroidDownloadManager setListener(AndroidDownloadManagerListener listener) {
this.listener = listener;
return this;
}
public void download() {
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setAllowedOverRoaming(false);
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setTitle(name);
request.setDescription("downloading......");
request.setVisibleInDownloadsUi(true);
File file = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), name);
request.setDestinationUri(Uri.fromFile(file));
path = file.getAbsolutePath();
if (downloadManager == null) {
downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
}
if (downloadManager != null) {
if (listener != null) {
listener.onPrepare();
}
downloadId = downloadManager.enqueue(request);
}
context.registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}
private MyBroadcastReceiver receiver = new MyBroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
DownloadManager.Query query = new DownloadManager.Query();
Log.d(TAG, "onReceive >>>>" + url);
query.setFilterById(downloadId);
Cursor cursor = downloadManager.query(query);
if (cursor.moveToFirst()) {
int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
switch (status) {
case DownloadManager.STATUS_PAUSED:
break;
case DownloadManager.STATUS_PENDING:
break;
case DownloadManager.STATUS_RUNNING:
break;
case DownloadManager.STATUS_SUCCESSFUL:
if (listener != null) {
listener.onSuccess(path);
}
cursor.close();
context.unregisterReceiver(receiver);
break;
case DownloadManager.STATUS_FAILED:
if (listener != null) {
listener.onFailed(new Exception("failed"));
}
cursor.close();
context.unregisterReceiver(receiver);
break;
}
}
}
};
}
解决方案
推荐阅读
- python - 如何使用 docker 运行 python cron 应用程序?
- python - InterfaceError:执行操作失败;Python 类型 numpy.int64 无法转换
- python - 如何使用 python 在 firebase 上模拟测试(单元测试)?
- python - 删除 ")" 和字符串之间
- c# - 如何在itextsharp中居中对齐长文本?
- html - 如何仅使用 HTML 和 CSS 创建子选项卡
- java - 具有多个微服务实例的存储和转发设计模式
- javascript - 如何修复“Uncaught TypeError: Cannot read property 'classList' of null”(不是由元素顺序引起的)
- reactjs - 如何将 mxgraph 与 reactjs 集成?
- php - 有没有办法用正则表达式替换所有不需要的数字和字符?