1 、通过内置Sys APPS 实现资源预置
1 、通过内置Sys APPS 实现资源预置
简介:
设计之初idea来自于的资源copy demo。在此基础上完成了自己的一点想法。请大家评审、讨论,给予宝贵的改进意见。
一、文件 tree :
二、流程图 与 相关点
Adroid 的 init & vold 过程, encrypt 过程、 mnt 分区挂载过程。
注意:
1、boot_complete 和 media_mount 广播对顺序;
2、cts 检查权限,pm (packageName)等;
3、apk disable 之后,settings中是否还存在包;
三,主要功能代码:
1、修改配置文件 :/xxx/config/sdm660_64/xxx/shipping/xxx.mk
添加:
PRODUCT_PACKAGES += MediaFilePreset
2、设置Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, src)
$(warning $(LOCAL_SRC_FILES))
LOCAL_JAVA_LIBRARIES += telephony-common
LOCAL_PACKAGE_NAME := MediaFilePreset
LOCAL_CERTIFICATE := platform
LOCAL_MANIFEST_FILE := AndroidManifest.xml
LOCAL_PRIVILEGED_MODULE := true
include $(BUILD_PACKAGE)
include $(call all-makefiles-under,$(LOCAL_PATH))
3、写AndroidManifest.xml
<!--
/*
* Code by author at 2018.08.02.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.demo.mediafilepreset"
android:sharedUserId="android.uid.system" >
<uses-sdk
android:minSdkVersion="9"
android:targetSdkVersion="23" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme"
>
<receiver android:name="com.demo.mediafilepreset.MediaFilePresetReceiver">
<intent-filter >
<action android:name="android.intent.action.MEDIA_MOUNTED"/>
<data android:scheme="file">
</data>
</intent-filter>
</receiver>
</application>
</manifest>
4、定义theme
packages/MediaFilePreset/res/values-v11/styles.xml
<style name="AppBaseTheme" parent="android:Theme.Holo.Light">
<!-- API 11 theme customizations can go here. -->
</style>
packages/MediaFilePreset/res/values-v14/styles.xml
<style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
<!-- API 14 theme customizations can go here. -->
</style>
packages/MediaFilePreset/res/values/styles.xml
<style name="AppBaseTheme" parent="android:Theme.Light">
<!--
Theme customizations available in newer API levels can go in
res/values-vXX/styles.xml, while customizations related to
backward-compatibility can go here.
-->
</style>
<!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
</style>
5. 功能代码
./custorm/packages/MediaFIlePreset/src/com/android/mediafilepreset/MediaFilePresetReceiver.java
package com.hq.mediafilepreset;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.content.Intent;
import android.media.MediaScanner;
import android.net.Uri;
import android.os.Environment;
import android.util.Log;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipEntry;
public class MediaFilePresetReceiver extends BroadcastReceiver {
private static final String TAG = "MediaFilePresetReceiver";
private static final String ACTIVITIES[] = {
"com.hq.mediafilepreset.MediaFilePresetReceiver",
};
private static final String DCIM_ZIP = "DCIM.zip";
private static final String MUSIC_ZIP = "Music.zip";
//private static final String MOVIES_ZIP = "Movies.zip";
private static final String DCIM_PATH = "/mnt/sdcard/DCIM/";
private static final String MUSIC_PATH = "/mnt/sdcard/Music/";
//private static final String MOVIES_PATH = "/mnt/sdcard/Movies/";
@Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG,"onReceive:"+ intent.getAction());
boolean copied = false;
boolean sdCardExist = Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);
if (sdCardExist) {
try {
copied = compressZip(context,DCIM_ZIP,DCIM_PATH)
&& compressZip(context,MUSIC_ZIP,MUSIC_PATH)
/*&& compressZip(context,MOVIES_ZIP,MOVIES_PATH)*/;
} catch (IOException ioe){
ioe.printStackTrace();
}
}else {
Log.w(TAG,"sdcard mount failed");
}
if (copied) {
Log.i(TAG, "disable activities");
for (int i = 0; i < ACTIVITIES.length; i++) {
disableComponent(context, ACTIVITIES[i]);
}
disableComponent(context, "com.hq.mediafilepreset.MediaFilePresetReceiver");
}
}
/**
* Uncompress assets zip files.
* @param context
* @param fileName
* @param outputDirectory
* @throws IOException
*/
private boolean compressZip(Context context, String fileName, String outputDirectory) throws IOException {
File file = new File(outputDirectory);
if (!file.exists()) {
Log.d(TAG,"creat the folder");
file.mkdirs();
}
InputStream inputStream = context.getAssets().open(fileName);
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
ZipEntry zipEntry = zipInputStream.getNextEntry();
byte[] buffer = new byte[1024 * 100];
int count = 0;
while (zipEntry != null) {
if (zipEntry.isDirectory()) {
file = new File(outputDirectory + File.separator + zipEntry.getName());
if (!file.exists()) {
Log.d(TAG,"creat the subfolder");
file.mkdir();
}
} else {
file = new File(outputDirectory + File.separator + zipEntry.getName());
if (file.exists() && file.length() < zipEntry.getSize()) {
file.delete();
file.createNewFile();
FileOutputStream fileOutputStream = new FileOutputStream(file);
while ((count = zipInputStream.read(buffer)) > 0) {
fileOutputStream.write(buffer, 0, count);
}
fileOutputStream.close();
} else {
file.createNewFile();
FileOutputStream fileOutputStream = new FileOutputStream(file);
while ((count = zipInputStream.read(buffer)) > 0) {
fileOutputStream.write(buffer, 0, count);
}
fileOutputStream.close();
}
//touchMediaScan(context, file.getPath());
}
zipEntry = zipInputStream.getNextEntry();
}
zipInputStream.close();
touchMediaScan(context, outputDirectory);
return true;
}
private void disableComponent(Context context, String klass) {
Log.i(TAG,"disableComponent");
ComponentName name = new ComponentName(context, klass);
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(name,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
}
private void touchMediaScan(Context context, String dir) {
Log.i(TAG,"Touch Media Scanner");
//Intent scanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
//scanIntent.setData(Uri.fromFile(new File(path)));
//context.sendBroadcast(scanIntent);
MediaScanner mMediaScanner = new MediaScanner(context, "external");
String[] directories = null;
if (dir == DCIM_PATH) {
directories = new String[] {"/storage/emulated/0/DCIM/"};
} else if (dir == MUSIC_PATH) {
directories = new String[] {"/storage/emulated/0/Music/"};
} else {
directories = new String[] {dir};
}
if (directories != null) {
mMediaScanner.scanDirectories(directories);
}
}
}