我们正在使用内置DownloadManager
从我们的服务器获取文件。如果我们发现该文件有更新,我们将删除本地版本并从DownloadManager
. 这仅在您完全终止并重新启动应用程序时运行(及时更新文件不是优先事项,只是我们拥有所有文件并且只要我们注意到它们就会更新)。该系统在我所有的个人测试设备上都能完美运行,但是,在 api 19 模拟器或我同事的 HTC One 上进行测试时,文件将下载然后消失(不再位于应用程序的外部数据文件夹中)。我发现两者都是 android 的 4.4.2 版本(我的设备是 4.4.4 或 4.0.4)。这很奇怪,因为它们会停留一段时间,但随后随机文件会消失。
这是一些代码:
AssetManager 设置(输出文件夹的设置)
private AssetManager(Context activity){
if(singleton != null&&IOUtils.hasExternalStorage() != IOUtils.ExtStorageState_OK){
return;
}
context = activity;
external = ContextCompat.getExternalFilesDirs(context, "")[0];
external.mkdirs();
imageFolder = new File(external,imagePath);
imageFolder.mkdirs();
singleton = this;
}
下载代码
private static class DownloadObject {
public String ServerID;
public String updated_at;
public Uri image;
public DownloadObject() {
super();
}
public DownloadObject(String ServerID,String updated_at){
super();
this.ServerID = ServerID;
this.updated_at = updated_at;
}
public DownloadObject(Cursor cursor){
super();
this.ServerID = cursor.getString(cursor.getColumnIndex(ObjectDao.Properties.ServerID.columnName));
this.updated_at = cursor.getString(cursor.getColumnIndex(ObjectDao.Properties.UpdatedAt.columnName));
String imageFile = cursor.getString(cursor.getColumnIndex(ObjectDao.Properties.Image.columnName));
this.image = Uri.parse(AssetManager.getSingleton().getImageFolder().getPath()).buildUpon().appendPath(imageFile).scheme("file").build();
}
}
//downloadObjectVector is the fresh list of all objects from the server
//existingObjects is the Cursor from the db that lists all existing object locally
private void SpinOffDownloads(final Vector<DownloadObject> downloadObjectVector,final Cursor existingObjects){
new Thread(new Runnable() {
@Override
public void run() {
int count = 0;
if(existingObjects != null){
count = existingObjects.getCount();
}
if (count>0){
existingObjects.moveToFirst();
do{
final DownloadObject obj = new DownloadObject(existingObjects);
DownloadObject notNeededObject = ArrayUtils.findFirst(downloadObjectVector,new ArrayUtils.Predicate<DownloadObject>() {
@Override
public boolean evaluate(DownloadObject downloadObject) {
return downloadObject.ServerID.equals(obj.ServerID)&&downloadObject.updated_at.compareTo(obj.updated_at) <= 0;
}
});
if (notNeededObject != null){
File imageTest = null;
if(notNeededObject.image != null) {
Uri out = Uri.parse(AssetManager.getSingleton().getImageFolder().getPath()).buildUpon().appendPath(notNeededObject.image.getLastPathSegment()).scheme("file").build();
imageTest = new File(out.getPath());
}else{
Log.v(CLASS_NAME,"object with null image:"+notNeededObject.ServerID);
}
if (imageTest == null||imageTest.exists()) {
downloadObjectVector.remove(notNeededObject);
}else{
if (imageTest != null&&imageTest.exists()&&SHOULD_REPLACE_FILE){
Log.v(CLASS_NAME,"DELETING FILE(missing image):"+imageTest.getAbsolutePath());
imageTest.delete();
}
}
}else{
File imageTest = null;
if(obj.image != null) {
imageTest = new File(obj.image.getPath());
if (imageTest != null&&imageTest.exists()&&SHOULD_REPLACE_FILE){
Log.v(CLASS_NAME,"DELETING FILE(image):"+imageTest.getAbsolutePath());
imageTest.delete();
}
}else{
Log.v(CLASS_NAME,"object with null image:"+obj.ServerID);
}
}
}while(existingObjects.moveToNext());
}
if (existingObjects!= null){
try{
existingObjects.close();
}catch (Exception e){
}
}
DownloadManager dm = (DownloadManager)getSystemService(DOWNLOAD_SERVICE);
for (int i = 0; i < downloadObjectVector.size(); i++) {
try {
DownloadObject dlObj = downloadObjectVector.get(i);
Uri in = dlObj.image;
Uri out = Uri.parse(AssetManager.getSingleton().getImageFolder().getPath()).buildUpon().appendPath(in.getLastPathSegment()).scheme("file").build();
dm.enqueue(new DownloadManager.Request(in).setDestinationUri(out).setTitle(in.getLastPathSegment()));
}catch (Exception e){
Log.w(CLASS_NAME,"Error with Download queued:",e);
}
}
}
}).start();
}
如果您需要任何其他信息或代码,请告诉我!
编辑1
所以我决定通过我的测试来详细说明这个问题,以及这个问题是如何表现出来的,希望它能让画面更加清晰!
我首先通过 Android Studio 加载应用程序并让它运行足够长的时间以知道所有下载都已完成,然后我查看应用程序以查看哪些图像存在,哪些图像丢失。大多数图像正常存在。接下来我退出应用程序并使用 android 任务管理器完全杀死它。然后我通过 Android Studio 重新启动该应用程序。然后我等待确保下载完成并观察 LogCat 以查看哪些文件被手动删除(通常最多几个)。然后我通过应用程序查看哪些图像仍然存在/哪些已添加。似乎每次出现新图像并且新图像消失时......通常那些被标记为手动删除的图像实际上通过正确下载被替换(即没有“消失”)。
如果您想让我做任何测试,请告诉我!
文件观察员测试
首先,这是我第一次使用 aFileObserver
所以如果我做了一些愚蠢的事情,请指出。这是我的观察者代码:
external = ContextCompat.getExternalFilesDirs(context, null)[0];
external.mkdirs();
fileObserver = new FileObserver(external.getPath(),FileObserver.ALL_EVENTS) {
@Override
public void onEvent(final int event, final String relPath) {
String msg = "???";
switch (event){
case FileObserver.DELETE:
msg = "FILEOB DELETE relPath:"+relPath;
break;
case FileObserver.DELETE_SELF:
msg = "FILEOB DELETE_SELF relPath:"+relPath;
break;
case FileObserver.MODIFY:
msg = "FILEOB MODIFY relPath:"+relPath;
break;
case FileObserver.MOVE_SELF:
msg = "FILEOB MOVE_SELF relPath:"+relPath;
break;
case FileObserver.MOVED_TO:
msg = "FILEOB MOVED_TO relPath:"+relPath;
break;
case FileObserver.MOVED_FROM:
msg = "FILEOB MOVED_FROM relPath:"+relPath;
break;
case FileObserver.ATTRIB:
msg = "FILEOB ATTRIB relPath:"+relPath;
break;
case FileObserver.CREATE:
msg = "FILEOB CREATE relPath:"+relPath;
break;
default:
msg = "Unknown event:"+event+" at relPath:"+relPath;
}
fileObserverHandler.publish(new LogRecord(Level.INFO,msg));
fileObserverHandler.flush();
}
@Override
public void startWatching() {
super.startWatching();
fileObserverHandler.publish(new LogRecord(Level.INFO,"START WATCHING!!!!"));
fileObserverHandler.flush();
Log.v("FileObserver","START WATCHING!!!");
}
};
fileObserver.startWatching();
我正在使用处理程序,因为起初我没有startWatching()
覆盖并且根本没有得到任何日志记录,并且文档说 onEvent 发生在它自己的线程上,因此您应该使用处理程序。课堂上就是这样:
public static Handler fileObserverHandler = new ConsoleHandler();
我从中得到的唯一输出是“开始观看!!!”。所以我猜我一定做错了什么,因为我看到它正在下载/删除东西……至少它说的是。