最近遇到一个bug需求,将视屏文件放到手机文件管理器里面,并且在用户手动删除以后,恢复出厂设置还能在恢复之前复制进去的视屏文件。
首先得要把这几个视屏文件放入系统源码里面,我的做法和预置apk是一样的。在预置apk的路径下面放置这3个文件,我的预置路径是在source/packages/Customer/SOUNDPHONE/下面,每个项目的路径可能略有不同。在这个路径下面建一个文件夹名字为MyTselMobile放置这三个文件。然后在product.mk文件里面写入你需要编译到哪个路径下面。
product.mk
PRODUCT_COPY_FILES += \ $(LOCAL_PATH)/MyTselMobile/INNAINNdiA.mp4:system/etc/VIDEOS/INNAINNdiA.mp4 \ $(LOCAL_PATH)/MyTselMobile/Jessie.mp4:system/etc/VIDEOS/Jessie.mp4 \ $(LOCAL_PATH)/MyTselMobile/MeghanTrainor.mp4:system/etc/VIDEOS/MeghanTrainor.mp4 \在这个地方就将这三个视屏文件复制到了out下面,生成在img文件里面了。
接下来的操作就是怎么将文件从system下面复制到文件管理里面,我这里使用的是通过发送广播的方式完成的copy操作。
具体代码实现。
在android/packages/providers/MediaProvider/src/com/android/providers/media/MediaProvider.java里面发送一个广播用于执行copy操作。
/** * Ensure that default folders are created on mounted primary storage * devices. We only do this once per volume so we don't annoy the user if * deleted manually. */ private void ensureDefaultFolders(DatabaseHelper helper, SQLiteDatabase db) { final StorageVolume vol = mStorageManager.getPrimaryVolume(); final String key; if (VolumeInfo.ID_EMULATED_INTERNAL.equals(vol.getId())) { key = "created_default_folders"; } else { key = "created_default_folders_" + vol.getUuid(); } final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); if (prefs.getInt(key, 0) == 0) { for (String folderName : sDefaultFolderNames) { final File folder = new File(vol.getPathFile(), folderName); if (!folder.exists()) { folder.mkdirs(); insertDirectory(helper, db, folder.getAbsolutePath()); } //chendan Sends a video file to the file manager if(folderName.equals(Environment.DIRECTORY_AUDIO_FM_RADIO)) { if(!new File(folder.getAbsolutePath()+"/INNAINNdiA.mp4").exists()){ Log.d(TAG, "wangchong MMXDDS broadcast"); Intent firIntent = new Intent("android.intent.action.MEDIA_MOUNTED_FOR_FIRTIME"); getContext().sendStickyBroadcast(firIntent); } }//end
} SharedPreferences.Editor editor = prefs.edit(); editor.putInt(key, 1); editor.commit(); } }这个方法里面看上面的注释就知道这个地方是建默认的默认目录的地方,如果我们把默认的目录删除了,恢复出厂设置也会重新新建回来的。然后我们在这个地方判断是否有这个默认文件夹,然后判断文件夹里面是不是有这个视屏文件,虽然复制进来的文件是3个,但是这个地方只需要判断一个就好,因为他们是一起执行的复制操作,只要有一个是重复的,那么就不会在发送广播执行复制操作。
在android/packages/providers/MediaProvider/src/com/android/providers/media/路径下面新建一个类FirstCopyReceiver继承自BroadcastReceiver,用于执行copy操作的一系列代码
FirstCopyReceiver.java
/** * * Copy additional UNISCOPE files * */ package com.android.providers.media; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.util.Slog; import com.android.featureoption.FeatureOption; public class FirstCopyReceiver extends BroadcastReceiver{ /** * delete file or folder * @param folder Path String ,absolute path of file :/mnt/sdcard/test/1.png */ public static void deleteDirectory(String folderPath) { try { // delete all files deleteAllFile(folderPath); File lastFile = new File(folderPath); if (lastFile.exists()) { //delete the empty folder lastFile.delete(); } } catch (Exception e) { e.printStackTrace(); } } /** * delete file or folder * @param folder Path String ,absolute path of file :/mnt/sdcard/test/1.png */ private static void deleteAllFile(String path) { //open up a file space in memory File file = new File(path); if (!file.exists()) { return; } if (file.isFile()) { file.delete(); } else if (file.isDirectory()) { String[] tempList = file.list(); File temp = null; for (int i = 0; i < tempList.length; i++) { if (path.endsWith(File.separator)) { temp = new File(path + tempList[i]); } else { temp = new File(path + File.separator + tempList[i]); } if (temp.isFile()) { temp.delete(); } if (temp.isDirectory()) { deleteAllFile(path + "/" + tempList[i]); deleteDirectory(path + "/" + tempList[i]); } } } } public void copyFolder(String oldPath, String newPath) { try { (new File(newPath)).mkdirs(); Slog.i("FirstCopyReceiver", oldPath+"to"+newPath); File a=new File(oldPath); String[] file=a.list(); if(file == null) { Slog.i("FirstCopyReceiver", "file is NULL, error"); } File temp=null; for (int i = 0; i < file.length; i++) { if(oldPath.endsWith(File.separator)){ temp=new File(oldPath+file[i]); } else{ temp=new File(oldPath+File.separator+file[i]); } if(temp.isFile()){ FileInputStream input = new FileInputStream(temp); FileOutputStream output = new FileOutputStream(newPath + "/" + (temp.getName()).toString()); byte[] b = new byte[1024 * 10 * 1024]; int len; while ( (len = input.read(b)) != -1) { output.write(b, 0, len); } output.flush(); output.close(); input.close(); } if(temp.isDirectory()){ copyFolder(oldPath+"/"+file[i],newPath+"/"+file[i]); } } } catch (Exception e) { Slog.i("FirstCopyReceiver", "copy failure"); e.printStackTrace(); } } @Override public void onReceive(Context context, Intent intent) { Slog.i("FirstCopyReceiver", "onReceive"); Thread t = new Thread(new Runnable(){ @Override public void run() { copyFolder("/system/etc/VIDEOS/", "/storage/emulated/0/DCIM"); Slog.i("FirstCopyReceiver", "after copy"); } }); t.start(); } }这个类里面接收到广播以后就执行copy操作。代码比较简单就不进行讲解了。
最后在AndroidMainfest.xml中配置新建的这个类。
<receiver android:name=".FirstCopyReceiver"> <intent-filter> <action android:name="android.intent.action.MEDIA_MOUNTED_FOR_FIRTIME" /> </intent-filter> </receiver>
就这样一个复制的完整过程就完成了。有什么问题欢迎大家提出来,谢谢!