編輯:關於Android編程
客戶提了一個需求,內置22張客戶提供的壁紙到launcher的壁紙中,並且要在圖庫中顯示這22張壁紙
初步看,覺得這應該是一個非常簡單的需求,只要在luncher中對應以前的壁紙中添加22張客戶的壁紙就可以了
理想非常豐滿,現實是非常骨感!
我大公司研發部門實行開發平台化大戰略,各個開發實行模塊化戰術,各個模塊,各個應用實行釋放apk,不提供源碼的策略。
好政策啊!
領導英明啊!
我按照launcher apk提供配制壁紙的方法,將客戶提供的22張壁紙成功內置到launcher中,在launcher中可以看到壁紙中有內置的客戶22張壁紙,但是圖庫中不能顯示。
我就去向launcher模塊的負責人咨詢相關的解決方法。launcher告知我這要去找圖庫模塊。
好吧,去找圖庫的負責人,圖庫負責查看了我的圖片內置的位置:
system/etc/iamgeswallpapers/
告知我說圖片內置到system中,圖片不能識別。要我去找以前做項目的人。
我提出疑問:圖庫應該提供一個內置圖片到圖庫的方法。
圖庫的負責人直接回復:對於這種需求,我們不負責,這和圖庫沒有關系。
好吧,是我錯了,哥,對不起,麻煩你們了。
我再找以前做項目的人,問了一下此需求。他們告知我解決方案:
(1)先將圖片復制到system目錄下
(2)再內置一個apk,就可以了
(注,為什麼這位告訴我這麼詳細,因為是熟人!)
我按照上面的方法來實現:
第一:內置圖片到目錄(system/media/bootupResource)下:
先將圖片放到picture目錄下,然後在mk文件中配置,復制圖片到(system/media/bootupResource):
配制方法:
PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/picture/hd_0.jpg:system/media/bootupResource/hd_0.jpg \
$(LOCAL_PATH)/picture/hd_1.jpg:system/media/bootupResource/hd_1.jpg \
$(LOCAL_PATH)/picture/hd_2.jpg:system/media/bootupResource/hd_2.jpg \
$(LOCAL_PATH)/picture/hd_3.jpg:system/media/bootupResource/hd_3.jpg \
$(LOCAL_PATH)/picture/hd_4.jpg:system/media/bootupResource/hd_4.jpg \
$(LOCAL_PATH)/picture/hd_5.jpg:system/media/bootupResource/hd_5.jpg \
$(LOCAL_PATH)/picture/hd_6.jpg:system/media/bootupResource/hd_6.jpg \
$(LOCAL_PATH)/picture/hd_7.jpg:system/media/bootupResource/hd_7.jpg \
.................
第二:內置app應用BootupImage
此應用BootupImage主要的作用是二個,一是將(system/media/bootupResource)目錄下的圖片復制到我們定義的手機內存中,二是通知手機立刻掃描到新復制的圖片,以在圖庫中顯示。
坑人的是,我內置此apk,圖庫中就是沒有顯示圖片,我debug了半天,才發現原來是高通和MTK的讀取內置路徑的方法不同,我再移植對應的高通項目的此應用,功能是實現了。
看了一下BootupImage應用,代碼面向具體實現,代碼的可讀性一般,沒有什麼規范性,沒有什麼擴展性和可移植性。
我決定重寫:
關鍵方法說明:
boolean copyFile(String src,String des) ---復制文件功能:把路徑為src的文件復制到路徑為des的位置 成功返回true,失敗為false
public static boolean copyFile(String src,String des){
boolean result = true;
FileInputStream fis = null;
FileOutputStream fos = null;
try {
//定義輸入和輸出的文件
File fin = new File(src);
File fout = new File(des);
//定義輸入流和輸出流的對象
fis = new FileInputStream(fin);
fos = new FileOutputStream(fout);
//3.執行復制操作
byte[] b = new byte[1024];
int len;
while ((len = fis.read(b)) != -1) {
fos.write(b, 0, len);
}
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
result = false;
}finally{
//4.關閉對應的流,先關輸出流,後關輸入流
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
result = false;
}
}
if(fis != null){
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
result = false;
}
}
}
return result;
}
public static boolean copyDirectory(String sourceDir, String destDir) ---復制文件夾功能:把路徑為src的文件夾復制到路徑為des的位置 成功返回true,失敗為false
public static boolean copyDirectory(String sourceDir, String destDir){
boolean result = true;
File sourceFile = new File(sourceDir);
File destFile = new File(destDir);
if(!sourceFile.exists()){
android.util.Log.i(TAG, "sourceFile do not exist");
return false;
}
if(!destFile.exists()){
if(!destFile.mkdirs()){
android.util.Log.i(TAG, "destFile mkdirs fail");
return false;
}
}
if(!destFile.canRead()){
android.util.Log.i(TAG, "destFile can not Read");
return false;
}
File[] file = sourceFile.listFiles();
for(int i=0;ipublic static final void scanFile(final Context context,final String path)
---掃描文件,讓手機可以實時識別變動的文件
public static final void scanFile(final Context context,final String path){
android.util.Log.i(TAG, "scanFile--:"+path);
Intent scanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
scanIntent.setData(Uri.fromFile(new File(path)));
context.sendBroadcast(scanIntent);
}
public static final void scanDir(final Context context,final String path)
---掃描文件夾,讓手機可以實時識別變動的文件夾
public static final void scanDir(final Context context,final String path){
android.util.Log.i(TAG, "scanDir");
android.util.Log.i(TAG, "scanDir---path:"+path);
File file = new File(path);
File[] fileItemFiles = file.listFiles();
for (int i = 0; i < fileItemFiles.length; i++) {
String pathItem = fileItemFiles[i].getParent()+File.separator+fileItemFiles[i].getName();
if(fileItemFiles[i].isFile()){
scanFile(context,pathItem);
}
if(fileItemFiles[i].isDirectory()){
scanDir(context,pathItem);
}
}
}
定義幾個關鍵的變量:
public static final String TAG = "Util";
//public static final String sourceDir = "/system/media/bootupResource";
public static final String sourceDir = "/system/media";
public static final String destDir_Without_SDCARD = Environment.getExternalStorageDirectory().getAbsolutePath() +File.separator+ "Pictures_01";
public static final String destDir_With_SDCARD = "/storage/sdcard1/Pictures";
調用方法
啟動線程,以Util.copyDirectory實現復制文件夾,並且以Util.scanDir掃描最新復制的文件夾,以方便手機識別變動的文件,以讓圖片可以在圖庫中顯示:
runnable = new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
//復制文件夾到對應的位置
boolean result = Util.copyDirectory(Util.sourceDir,Util.destDir_Without_SDCARD);
android.util.Log.i(TAG, "onClickDo:"+result);
android.util.Log.i(TAG, "onClickDo:---scanDir");
//掃描最新復制的文件夾,以識別變動的文件
Util.scanDir(getApplicationContext(), Util.destDir_Without_SDCARD);
}
};
runnable.run();
Android.mk
配置app的android.mk文件
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := TinnoCopyResourceToStorage
LOCAL_CERTIFICATE := platform
include $(BUILD_PACKAGE)
AndroidManifest.xml
定義權限:
以上其實已經實現了內置圖片到圖庫中,並且實時讓手機識別,以在圖庫中顯示。
擴展
那麼,如果客戶提出內置其它資源到特定的目錄路徑(比如鈴聲,音樂,視頻,apk,zip等等),並且讓手機實現識別到復制過來的資源,以讓手機實時識別和顯示。
啊噢,哈哈。
告訴你一個好消息吧,以上方法,你只需要修改src和des的路徑,就可以實現所有此類的需求。並且已驗證!!
Android Content Providers基礎
Content Provider介紹內容提供程序管理對結構化數據集的訪問。它們封裝數據,並提供用於定義數據安全性的機制。 內容提供程序是連接一個進程中的數據與另一個進程中
android網絡框架OkHttp之get請求(源碼初識)
概括OkHttp現在很火呀。於是上個星期就一直在學習OkHttp框架,雖然說起來已經有點晚上手了,貌似是2013年就推出了。但是現在它版本更加穩定了呀。這不,說著說著,O
Unity3D —— protobuf網絡框架
前言:protobuf是google的一個開源項目,主要的用途是:1.數據存儲(序列化和反序列化),這個功能類似xml和json等;2.制作網絡通信協議;一、資源下載:1
Android特效專輯(十)——點擊水波紋效果實現,邏輯清晰實現簡單
Android特效專輯(十)——點擊水波紋效果實現,邏輯清晰實現簡單 這次做的東西呢,和上篇有點類似,就是用比較簡單的邏輯思路去實現一些比較好玩的