android 监听exoDownloadManager时出错:另一个SimpleCache示例使用该文件夹

ryoqjall  于 2022-12-09  发布在  Android
关注(0)|答案(1)|浏览(201)

最近我已经成功实现了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作为单例,我做了精确的指令,但面临同样的错误。我哪里做错了?

pxy2qtax

pxy2qtax1#

我以前也遇到过同样的问题。
我的情况是,当我尝试第二次下载相同的音频时,在相同文件目录路径中使用的simpleCache未释放。
您提到的使用SimpleCache作为单例的答案是,**使用getCacheDir()**创建缓存文件路径,而不是指定文件位置。
如果要使用指定的文件路径,则需要释放之前使用的SimpleCache对象。

downCache.release();

相关问题