最近我已经成功实现了exoplayer的downloading media。下面的图片说明了使用exoplayer实现下载媒体所需的类。
根据suggestion的一个开发伙伴在媒体和我引用:
为了使DownloadManager在应用程序的所有组件之间共享,可以将其初始化为自定义应用程序类。Exoplayer还建议ExoDatabaseProvider应为单例,并且下载缓存不应收回媒体。
一切都在工作的方式,他们应该.这里是我的代码在完整..
下载服务类别:
public class ExoDownloadService extends DownloadService {
private final String TAG = "serviceTAG";
public ExoDownloadService() {
super(
1,
DEFAULT_FOREGROUND_NOTIFICATION_UPDATE_INTERVAL,
"download_channel",
R.string.app_name, 0);
}
@Override
protected DownloadManager getDownloadManager() {
final DownloadManager downloadManager = downloadManager();
downloadManager.addListener(
new TerminalStateNotificationHelper(
this, getDownloadNotificationHelper(this), 2));
return downloadManager;
}
@Inject
DownCache downCache;
private DownloadManager downloadManager() {
return ((HiltApplication) getApplication()).downloadMngContainer.getDownloadManager();
}
DownloadNotificationHelper downloadNotificationHelper;
public DownloadNotificationHelper getDownloadNotificationHelper(Context context) {
if (downloadNotificationHelper == null) {
downloadNotificationHelper =
new DownloadNotificationHelper(context, "download_channel");
}
return downloadNotificationHelper;
}
@Nullable
@Override
protected Scheduler getScheduler() {
return Util.SDK_INT >= 21 ? new PlatformScheduler(this, 1) : null;
}
@Override
protected Notification getForegroundNotification(List<Download> downloads, int notMetRequirements) {
final DownloadNotificationHelper downloadNotificationHelper =
new DownloadNotificationHelper(this, "download_channel");
return downloadNotificationHelper.buildProgressNotification(
this,
R.drawable.ic_download,
null,
null,
downloads,
notMetRequirements);
}
private static final class TerminalStateNotificationHelper implements DownloadManager.Listener {
private final Context context;
private final DownloadNotificationHelper notificationHelper;
private int nextNotificationId;
public TerminalStateNotificationHelper(
Context context, DownloadNotificationHelper notificationHelper, int firstNotificationId) {
this.context = context.getApplicationContext();
this.notificationHelper = notificationHelper;
nextNotificationId = firstNotificationId;
}
@Override
public void onDownloadChanged(DownloadManager downloadManager, Download download, @Nullable Exception finalException) {
Notification notification;
if (download.state == Download.STATE_COMPLETED) {
notification =
notificationHelper.buildDownloadCompletedNotification(
context,
R.drawable.ic_download_done,
/* contentIntent= */ null,
Util.fromUtf8Bytes(download.request.data));
} else if (download.state == Download.STATE_FAILED) {
notification =
notificationHelper.buildDownloadFailedNotification(
context,
R.drawable.ic_download_done,
/* contentIntent= */ null,
Util.fromUtf8Bytes(download.request.data));
} else {
return;
}
NotificationUtil.setNotification(context, nextNotificationId++, notification);
}
}
}
应用程序中的DownloadManager ..
public class HiltApplication extends Application {
public DownloadManagerContainer downloadMngContainer;
private final String TAG = "hiltTAG";
@Override
public void onCreate() {
super.onCreate();
downloadMngContainer = new DownloadManagerContainer(getApplicationContext());
}
}
下载管理器容器类代码..
public class DownloadManagerContainer {
private final Context context;
private DataSource.Factory httpDataSourceFactory;
private DownloadManager downloadManager;
public DownloadManagerContainer(final Context context) {
this.context = context;
}
public DownloadManager getDownloadManager() {
if (downloadManager == null) {
downloadManager = new DownloadManager(
context,
getDatabaseProvider(context),
DownCache.newInstance(context),
getHttpDataSourceFactory(), //upstreamFactory
Executors.newFixedThreadPool(6));
}
return downloadManager;
}
private DatabaseProvider getDatabaseProvider(Context context) {
return new StandaloneDatabaseProvider(context);
}
public DataSource.Factory getHttpDataSourceFactory() {
if (httpDataSourceFactory == null) {
@Nullable CronetEngine cronetEngine = CronetUtil.buildCronetEngine(context);
if (cronetEngine != null) {
httpDataSourceFactory = new CronetDataSource.Factory(cronetEngine, Executors.newSingleThreadExecutor());
}
if (httpDataSourceFactory == null) {
final CookieManager cookieManager = new CookieManager();
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ORIGINAL_SERVER);
CookieHandler.setDefault(cookieManager);
httpDataSourceFactory = new DefaultHttpDataSource.Factory();
}
}
return httpDataSourceFactory;
}
}
作为单一示例的DownCache类为:
public class DownCache {
private static Cache downCache;
public static Cache newInstance(final Context context) {
if (downCache == null) {
final File downloadContentDirectory = new File(getDownloadDirectory(context), "downloads");
downCache = new SimpleCache(downloadContentDirectory, new NoOpCacheEvictor(), getDatabaseProvider(context));
}
return downCache;
}
private static File getDownloadDirectory(Context context) {
File downloadDirectory = context.getExternalFilesDir(null);
if (downloadDirectory == null) {
downloadDirectory = context.getFilesDir();
}
return downloadDirectory;
}
private static DatabaseProvider getDatabaseProvider(Context context) {
return new StandaloneDatabaseProvider(context);
}
}
问题:
当我在我的片段中触发下载时,我也会监听downloadmanager来更新UI:这是我的片段代码。
private void downloadMedia() {
final Requirements requirements = new Requirements(Requirements.DEVICE_STORAGE_NOT_LOW);
final boolean isRequired = requirements.checkRequirements(requireContext());
DownloadService.sendSetRequirements(
requireContext(),
ExoDownloadService.class,
requirements,
isForeGround
);
Log.d(TAG, "Download Requirement Status Is : " + isRequired);
if (isRequired) {
try {
final DownloadRequest request = new DownloadRequest.Builder(downloadID, Uri.parse(vidUrl)).build();
DownloadService.sendAddDownload(requireContext(), ExoDownloadService.class, request, true);
} catch (Exception e) {
Log.d(TAG, "downloadMedia Error Is : " + e.getMessage());
}
}
downloadListener();
}
private boolean isDownloading = true;
private void downloadListener() {
final DownloadManager downloadManager = ((HiltApplication) requireActivity().getApplication()).downloadMngContainer.getDownloadManager();
displayDownloadProgress(downloadManager);
downloadManager.addListener(new DownloadManager.Listener() {
@Override
public void onInitialized(DownloadManager downloadManager) {
DownloadManager.Listener.super.onInitialized(downloadManager);
Log.d(TAG, "This Is onInitialized()");
}
@Override
public void onDownloadsPausedChanged(DownloadManager downloadManager, boolean downloadsPaused) {
DownloadManager.Listener.super.onDownloadsPausedChanged(downloadManager, downloadsPaused);
Log.d(TAG, "This Is onDownloadsPausedChanged()");
}
@Override
public void onDownloadChanged(DownloadManager downloadManager, Download download, @Nullable Exception finalException) {
DownloadManager.Listener.super.onDownloadChanged(downloadManager, download, finalException);
Log.d(TAG, "This Is onDownloadChanged()");
}
@Override
public void onDownloadRemoved(DownloadManager downloadManager, Download download) {
DownloadManager.Listener.super.onDownloadRemoved(downloadManager, download);
Log.d(TAG, "This Is onDownloadRemoved()");
}
@Override
public void onIdle(DownloadManager downloadManager) {
DownloadManager.Listener.super.onIdle(downloadManager);
Log.d(TAG, "This Is onIdle()");
isDownloading = false;
}
@Override
public void onRequirementsStateChanged(DownloadManager downloadManager, Requirements requirements, int notMetRequirements) {
DownloadManager.Listener.super.onRequirementsStateChanged(downloadManager, requirements, notMetRequirements);
Log.d(TAG, "This Is onRequirementsStateChanged()");
}
@Override
public void onWaitingForRequirementsChanged(DownloadManager downloadManager, boolean waitingForRequirements) {
DownloadManager.Listener.super.onWaitingForRequirementsChanged(downloadManager, waitingForRequirements);
Log.d(TAG, "This Is onWaitingForRequirementsChanged()");
}
});
}
private void displayDownloadProgress(DownloadManager downloadManager) {
final ExecutorService thread = Executors.newSingleThreadExecutor();
final Handler handler = new Handler(Looper.getMainLooper());
thread.execute(() -> {
final int size = downloadManager.getCurrentDownloads().size();
Log.d(TAG, "Download List Is : " + downloadManager.getCurrentDownloads().size());
while (isDownloading) {
try {
final float percent = downloadManager.getCurrentDownloads().get(size - 1).getPercentDownloaded();
final String percentStr = Float.toString(percent);
handler.post(() -> {
binding.tvDownPercent.setText(percentStr);
Log.d(TAG, "Percentage Is : " + percentStr);
});
} catch (Exception e) {
Log.d(TAG, "displayDownloadProgress Error Is : " + e.getMessage());
}
}
});
}
我面临这个错误,它说:java.lang.IllegalStateException: Another SimpleCache instance uses the folder:* poiting to this line of code in "DownCache.class"
downCache = new SimpleCache(downloadContentDirectory, new NoOpCacheEvictor(), getDatabaseProvider(context));
Here it says我们应该使用SimpleCache
作为单例,我做了精确的指令,但面临同样的错误。我哪里做错了?
1条答案
按热度按时间pxy2qtax1#
我以前也遇到过同样的问题。
我的情况是,当我尝试第二次下载相同的音频时,在相同文件目录路径中使用的simpleCache未释放。
您提到的使用SimpleCache作为单例的答案是,**使用getCacheDir()**创建缓存文件路径,而不是指定文件位置。
如果要使用指定的文件路径,则需要释放之前使用的SimpleCache对象。