首页 >> 大全

预置文件到sdcard目录

2023-11-25 大全 22 作者:考证青年

了解为什么不可以直接预置

因为是挂载之后出现的,没法在编译的时候直接添加内容

无法直接预置,那么用什么替代

找一个已知会在编译的时候,可以预置文件的位置,这里用的是文件夹

路径:

\device\mediatek\common\mid\common\system

原理是什么?

开启一个复制的服务,让加载的时候,复制目录下的文件到需要的位置

方法 1.将需要的文件放到目录下,可以有多级目录,这里在定义位置的时候做出选择

我这里放置来3张图片到extra目录下

2.这里建立一个,做类似预置应用的操作

这里取个名叫,可以随便取名,注意在加包的时候做对应的修改

看目录可以知道有3个大文件,最上面那个就是我们的项目的代码。类似写安卓项目,目录层级是一样的,jni就是java和c#的互相调用,mk文件是编译的关键,据说12变成了bp文件,这里是11.

mk文件可以理解为说明书,具体可以看

直接上的代码

目录存放设备文件__目录文件所存放的信息是什么

.xml


<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.mid.copymedia"android:versionCode="1"android:versionName="1.0"android:sharedUserId="android.uid.system" ><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/><applicationandroid:icon="@drawable/ic_launcher"android:label="@string/app_name" ><service android:name=".CopyService"android:directBootAware="true"><intent-filter ><action android:name="mid.intent.action.COPYMEDIA"/><category android:name="android.intent.category.DEFAULT"/>intent-filter>service><receiver android:name=".CopyReceiver"android:directBootAware="true">  <intent-filter>  <action android:name="android.intent.action.BOOT_COMPLETED" />  intent-filter>  receiver>application>manifest>

可以看到这里面没有,只有一个服务和一个广播接收者,说明什么,没有界面。

.java

package com.mid.copymedia;import java.io.File;import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Environment;
import android.os.SystemProperties;public class CopyReceiver extends BroadcastReceiver {private String BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED";private static final String SRC_S = "/system/extra";private static final String SRC_D = "/data/extra";private static final String DST_STR = "persist.sys.sd.defaultpath";private static final String DST = "sdcard";@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();boolean copyOk = SystemProperties.get("persist.sys.mid.cpok","fail").equals("ok");//CopyJni.isCopyDown();CopyUtil.debug("onReceive action " + action);if(action.equals(BOOT_COMPLETED)){if(!copyOk){Intent copyIntent = new Intent(context, CopyService.class);context.startService(copyIntent);}}}public void doCopyStuff(final Context mContext){CopyJni.startProcess(mContext, SystemProperties.get("ro.preinstall.canreset", "yes").equals("yes") ?SRC_S:SRC_D, DST);}}

这个类,做了啥,定义了一堆的常量,还拿到了一个系统值,先通过来筛选服务,这里没有直接调用方法,而是通过开启一个服务,让服务去调用这个方法,为什么?很显然,这种操作只有可能是耗时,不方便在这里调用,为什么服务可以?这个需要去看对服务的定义了,不展开描述

.java

package com.mid.copymedia;import android.app.Service;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Environment;
import android.os.IBinder;public class CopyService extends Service {	private CopyReceiver mCopyReceiver = new CopyReceiver();public static void debug(String msg){android.util.Log.d("xxczy","mid=>"+msg);}@Overridepublic IBinder onBind(Intent arg0) {// TODO Auto-generated method stubreturn null;}@Overridepublic void onCreate() {// TODO Auto-generated method stubsuper.onCreate();debug("CopyService onCreate");mCopyReceiver.doCopyStuff(this);}@Overridepublic void onStart(Intent intent, int startId) {// TODO Auto-generated method stubsuper.onStart(intent, startId);}@Overridepublic void onDestroy() {debug("CopyService onDestroy");super.onDestroy();}}

回过头去看.(),这里好像啥都没做,但不可能,不在src文件中具体实现,那么就是在jni了,直接打开,可以看到

JNIEXPORT void JNICALL Java_com_mid_copymedia_CopyJni_startProcess(JNIEnv *env, jclass cls, jobject ctx, jstring src, jstring dst)
{/**jclass FindClass(JNIEnv *env, const char *name);*/jclass  CopyUtilClz = env->FindClass("com/mid/copymedia/CopyUtil");if(CopyUtilClz == NULL){LOGD("CopyJni_startProcess can't find CopyUtilClz \n");return;}/*	jmethodID GetStaticMethodID(JNIEnv *env, jclass clazz,const char *name, const char *sig);*/jmethodID doCopyMthdId = env->GetStaticMethodID(CopyUtilClz, "doCopy","(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)V");/**jstring NewStringUTF(JNIEnv *env, const char *bytes);*/// jstring src = env->NewStringUTF("/system/vendor_prebuilt");// jstring dst = env->NewStringUTF("/storage/sdcard0/vendor_media");/*NativeType CallStaticMethod(JNIEnv *env, jclass clazz,jmethodID methodID, ...);*/env->CallStaticVoidMethod(cls,doCopyMthdId,ctx,src,dst);
}

这一看,就有点懵,反手查资料,可以知道

该函数用于加载本地定义的类。它将搜索由 环境变量为具有指定名称的类所指定的目录和 zip文件

调用静态方法

资料链接:

嗯,可以看到又回去了,直接的意思就是把.java的静态方法全部调用了

.java

package com.mid.copymedia;import java.io.File;
import java.io.IOException;import android.content.Context;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Environment;
import android.os.SystemProperties;public class CopyUtil {public static void debug(String msg){android.util.Log.d("xxczy","mid=>"+msg);}public static String getRealPath(File file){try {debug("getRealPath getCanonicalPath="+file.getCanonicalPath()+" absPath="+file.getAbsolutePath());if(!file.getCanonicalPath().equals(file.getAbsolutePath())){return getRealPath(new File(file.getCanonicalPath()));}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}return file.getAbsolutePath();}public static void doCopy(final Context ctx , final String SRC, final String DST){boolean copyOk = SystemProperties.get("persist.sys.mid.cpok","fail").equals("ok");//CopyJni.isCopyDown();debug("doCopyStuff copy "+ copyOk);if(!copyOk){new Thread(){public void run() {File src = new File(SRC);File dst =  new File(DST);String dstPath = dst.getAbsolutePath();String dstCanoinacal = dstPath;debug("dstPath="+dstPath);dstCanoinacal = getRealPath(dst);debug("dstCanoinacal="+dstCanoinacal);dst = new File(dstCanoinacal);boolean ret = true;if(!dst.exists()){ret = dst.mkdirs();}if(!ret){debug("mkdir error return now "+dstCanoinacal);return;}CopyJni.doSomething(src, dst);CopyJni.copyDown(ctx, dstPath);};}.start();}}public static void updateMedia(Context context, String filename){  MediaScannerConnection.scanFile(context,  new String[] { filename }, null,  new MediaScannerConnection.OnScanCompletedListener() {  public void onScanCompleted(String path, Uri uri) {  debug("Scanned " + path + ":");  debug("-> uri=" + uri);  }  });  } }

很显然这里做了3件事:

1.拿具体路径

2.复制文件

3.跟新数据

直接看复制文件

嗯,前面一看就知道,就是对路径的是否存在的判断,没有就创建对应的文件夹,后面又调用了**.(src, dst);和.(ctx, );**方法

/** Class:     com_mid_copymedia_CopyJni* Method:    doSomething* Signature: (Ljava/io/File;Ljava/io/File;)V*/
JNIEXPORT void JNICALL Java_com_mid_copymedia_CopyJni_doSomething(JNIEnv *env, jclass cls, jobject srcFile, jobject dstFile)
{jclass FileUtilClz = env->FindClass("com/mid/copymedia/FileUtil");if(FileUtilClz == NULL){LOGD("CopyJni_doSomethind can't find FileUtilClz \n");return;}jmethodID copyFolderId = env->GetStaticMethodID(FileUtilClz, "copyFolder","(Ljava/io/File;Ljava/io/File;)V");env->CallStaticVoidMethod(cls,copyFolderId,srcFile,dstFile);}


/** Class:     com_mid_copymedia_CopyJni* Method:    copyDown* Signature: (Landroid/content/Context;Ljava/lang/String;)V*/
JNIEXPORT void JNICALL Java_com_mid_copymedia_CopyJni_copyDown(JNIEnv *, jclass, jobject, jstring);

嗯,感觉是吃太饱了,直接看.java的代码

.java

package com.mid.copymedia;import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import android.util.Log;public class FileUtil {private static void debug(String msg) {android.util.Log.d("xxczy", "mid=>" + msg);}public static void copyFolder(File src, File dst) {debug("copyFolder " + src.getAbsolutePath() + " to "+ dst.getAbsolutePath());long startTime = System.currentTimeMillis();debug("src.isDir " + src.isDirectory() + " dst.isDir "+ dst.isDirectory());if (src.isDirectory() && dst.isDirectory()) {File[] srcFiles = src.listFiles();debug("srcFiles.len " + srcFiles.length);if (srcFiles != null) {File toFile = null;for (int i = 0; i < srcFiles.length; i++) {toFile = new File(dst, new String(srcFiles[i].getName().getBytes()));if (srcFiles[i].isDirectory()) {if (!toFile.exists()) {if (!toFile.mkdirs()) {debug("mkdirs failed "+ toFile.getAbsolutePath());continue;}}copyFolder(srcFiles[i], toFile);} else {copyfile(srcFiles[i], toFile, true);}}}}long endTime = System.currentTimeMillis();long totalMs = (endTime - startTime) / 1000;debug("totalTime = " + totalMs / 1000 + "s " + totalMs % 1000 + " ms");}public static void copyfile(File fromFile, File toFile, Boolean rewrite) {debug("start copy " + new String(fromFile.getAbsolutePath().getBytes())+ " to " + toFile.getAbsolutePath());long startTime = System.currentTimeMillis();if (!fromFile.exists()) {return;}if (!fromFile.isFile()) {return;}if (!fromFile.canRead()) {return;}if (!toFile.getParentFile().exists()) {toFile.getParentFile().mkdirs();}if (toFile.exists() && rewrite) {toFile.delete();}debug("check permission ok !");try {FileInputStream fosfrom = new FileInputStream(fromFile);FileOutputStream fosto = new FileOutputStream(toFile);byte[] bt = new byte[1024 * 128];int c;while ((c = fosfrom.read(bt)) > 0) {fosto.write(bt, 0, c);}fosfrom.close();fosto.close();} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}long endTime = System.currentTimeMillis();long totalMs = (endTime - startTime) / 1000;debug("end copy file time = " + totalMs / 1000 + "s " + totalMs % 1000+ " ms");}public static void delete(File file) {if (file.isFile()) {file.delete();return;}if (file.isDirectory()) {File[] childFiles = file.listFiles();if (childFiles == null || childFiles.length == 0) {file.delete();return;}for (int i = 0; i < childFiles.length; i++) {delete(childFiles[i]);}file.delete();}}}

这里才是关键,用流去读取和写入文件

看过全部代码就知道了,有很多是多余的,就是个人对安卓系统开发的了解还较为浅,没有做实际修改

具体文件:

最后别忘了在\\\\\.mk中添加这个包名

PRODUCT_PACKAGES += CopyMedia

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了