Xamarin Android的DownloadProvider下载提供器实现要在哪里查找?
Xamarin Android下载进度监听问题解决方案
关于DownloadProvider在Xamarin Android的引入问题
Xamarin Android确实没有直接封装原生的DownloadProvider类,但你完全不需要额外找外部包引入,你用系统自带的DownloadManager服务就可以,它本身就对外暴露了可监听的Content Uri,直接监听这个系统Uri就能拿到进度,不需要自己移植原生的DownloadProvider代码。
ContentObserver不触发的排查步骤
- 先核对监听的Uri是否正确:如果是用系统DownloadManager做下载,必须监听
content://downloads/my_downloads,如果你是自己写的下载逻辑用了自定义ContentProvider,要确保监听的是你自己声明的Uri,不要写错。 - 检查权限:Android 6.0及以上必须动态申请
READ_EXTERNAL_STORAGE权限,没有这个权限你读不到DownloadManager的下载数据,Observer自然不会有回调。 - 注册方式要对:要用ApplicationContext的ContentResolver注册,别用Activity的上下文,不然Activity销毁重建之后注册就失效了,参考注册代码:
var downloadObserver = new 自定义Observer类(你的Handler, 要监听的下载ID, 下载管理器实例); Application.Context.ContentResolver.RegisterContentObserver( Android.Provider.DownloadManager.ContentUri, true, // 这个参数要传true,才能监听到子Uri的变化 downloadObserver );
- 重写OnChange方法不要写错重载:Xamarin里要重写带
bool selfChange, Uri uri两个参数的OnChange重载,别只写只有selfChange的旧版本重载,Android 7.0之后系统只会回调双参数的这个方法,旧的不会触发。
public override void OnChange(bool selfChange, Uri uri) { base.OnChange(selfChange, uri); // 这里查询下载进度逻辑 var query = new Android.Provider.DownloadManager.Query(); query.SetFilterById(你要监听的下载ID); var cursor = downloadManager.InvokeQuery(query); if (cursor.MoveToFirst()) { int downloaded = cursor.GetInt(cursor.GetColumnIndex(Android.Provider.DownloadManager.ColumnBytesDownloadedSoFar)); int total = cursor.GetInt(cursor.GetColumnIndex(Android.Provider.DownloadManager.ColumnTotalSizeBytes)); if (total > 0) { int progress = (int)(downloaded * 100f / total); // 拿到progress之后更新UI就行,注意要切到主线程更新 } } cursor.Close(); }
- 要是你完全是自己实现的下载逻辑,没用到系统DownloadManager,那你的自定义ContentProvider每次更新下载进度的时候,必须手动调用
ContentResolver.NotifyChange(你的ContentUri, null)发通知,否则Observer收不到任何变化提醒,这个是最容易漏的点。
内容的提问来源于stack exchange,提问作者Damien Doumer
相关产品推荐
相关产品推荐

