Android4.2中Gallery2源碼移植

最近開始做Android平臺下的相機開發,有別於驅動層和HAL層,我更多的是關注成像畫質和虛擬預覽等上層應用,整理了一點心得,感覺有必要記錄一下成長的足跡。因爲初學,不保證理解精準到位,請各位看官們堅定立場,大神請繞路走咯。害羞

一、源碼編譯

        對於自學開源軟件,我已經養成了一套自己的學習法則,那肯定是下載源碼—>查閱系統架構介紹(一定是官方網站爲主+各路民間帖)—>扣取感興趣小模塊,導入IDE裏深入分析—>再參考官網上對應部分的tutorials(好的開源軟件這個部分都很贊!就像ROS)—>從編譯helloworld開始學習編譯源代碼 —>改寫代碼,引用自己需要的三方庫—>鑑於Android移動開發,最後一步一定是要在真機上install對應的apk咯。

1)開發環境的搭建

先確保安裝好對應版本的JDK(我用jdk1.7.0_45),然後把官網上的adt-bundle-windows-x86_64-20131030下載下來,直接就可以用了!後面需要的build-tools、SDK-tools、platform-tools等軟件包,就交給eclipse下的Android SDK Manager了,能保證網絡通暢就行,真是一個簡單粗暴但有效便捷的方法啊。

2)扣Gallery2源碼

在Android-4.2.1_r1/packages/apps路徑下截取Gallery2和Camera包。從4.0版本起,google將Gallery和Camera聯繫在了一起,編譯前者的時候,後者不可獲取,這從Gallery/AndroidManifest.xml文件中多處閃現的camera字眼中可見。這裏,要提前在系統源碼編譯的/out/target/commom/obj/JAVA_LIBRARIES路徑下,挖出幾個後續Gallery2編譯過程中所需要引用的幾個靜態庫。分別將core_intermediates、framework_intermediates、mp4parser_intermediates、xmp_toolkit_intermediates四個路徑下得classes.jar 文件分別重命名爲  core_intermediates.jarframework_intermediates.jarmp4parser_intermediates.jarxmp_toolkit_intermediates.jar,放入本地一個文件夾裏,作爲後續編譯Gallery2模塊源碼靜態庫的預前準備。

3)在eclipse裏面導入源碼,編譯

a .在eclipse裏的Android Project from Existing Code裏面選Gallery2文件夾,不要test。接着在項目屬性的Java Build Path的Source選項下將gallerycommon和src_pd作爲源代碼文件夾add進入。這裏我做的一件事是,在gallerycommon文件夾下,刪除了原來自帶的以src開頭的包,新建了三個以com開頭對應名稱的包,然後就ctrl+a把對應路徑下本地文件夾下的源java文件Paste到eclipse裏對應的包名下(以防後續import時src的多餘)。同時,在Build Path裏面用Add Libraries將之前準備的幾個jar包填進去。用Order and Export排一下序,就基本完成了第一步操作了。

b.這時,src等源文件裏面還是一片紅色小叉,不用着急。打開看後,發現很多都是import時文件缺損的問題,總結有兩類,一類是R問題(對應的gen下面果然沒有自己生成對應的R.java文件,這個先放一部),另一類就是camera相關的文件找不到的問題了,這個也等下一步解決吧。

c.查看最不該有紅叉的資源文件夾,發現res/value下面的filtershow_strings.xmlphotoeditor_strings.xmlstrings.xml都有錯誤,原因是裏面有重複定義!最簡單粗暴的方法即是找到有錯的語句,將其用<!-- -->註釋掉。可以按照這種方法對values-xx開頭的文件夾都做相同的處理,但參照前人的說法,支柱是簡體中文的我們大可將values-zh-rCN之外的value-xx從項目中移除。剩下的rCN文件夾做上面同樣的註釋處理。

d.開始配置camera包了。一個導入之前不可缺少的工作是檢查camera下的res文件夾和當前gallery工程下的res文件夾下的文件有無重名。例如:兩者的values文件夾下都有atrrs.xml文件,則需要將camera的那一份重命名爲atrrs_camera.xml,否則會發生覆蓋導致出錯。此時,在Gallery工程裏右擊import-General-File System,展開下面的兩格小窗,不要選.git、test、Android.mk、CleanSpec.mk文件夾。

e.點擊Clean後,發現gen/com.android.gallery3d下已經生成了R.java,要注意的是,此時Camera工程原本自身的com.android.camera.R(指向其對應的資源)也都整合到com.android.gallery3d.R文件中了。因此凡是有import com.android.camera.R的地方都該換成import com.android.gallery3d.R來替換。同時,之前引用了R導致報錯的地方也應該import  com.android.gallery3d.R。

f.等兩秒,發現紅叉不見了,clean編譯時會報錯:ImageFilterSharpen.java函數裏找不到forEach_root()函數。在源代碼編譯的輸出文件路徑/out/target/common/obj/APPS/GALLERY2_intermediates/src/com/android/Gallery3d/filtershow/filters文件夾下找到ScriptC_convolve3x3.java一共可以找到3份同名的文件,將有forEach_root(Allocation, Allocation)接口的文件拷貝一份出來,在com.android.gallery3d.filtershow.filters路徑下,將其名字改爲MyScriptC_convolve3x3.java,區別開gen路徑下的ScriptC_convolve3x3.java。並在引用其構造實例的地方更改名字,如ImageFilterSharpen.java中,將ScriptC_convolve3x3 mScript改爲MyScriptC_convolve3x3 mScript,並在相應地方同步更改類名MyScriptC_convolve3x3.java代碼如下:


  1. /* 
  2.  * Copyright (C) 2011-2012 The Android Open Source Project 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  *      http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  */  
  16.    
  17. package com.android.gallery3d.filtershow.filters;  
  18.   
  19. import android.renderscript.*;  
  20. import android.content.res.Resources;  
  21.   
  22. /** 
  23.  * @hide 
  24.  */  
  25. public class MyScriptC_convolve3x3 extends ScriptC {  
  26.     private static final String __rs_resource_name = "convolve3x3";  
  27.     // Constructor  
  28.     public  MyScriptC_convolve3x3(RenderScript rs) {  
  29.         this(rs,  
  30.              rs.getApplicationContext().getResources(),  
  31.              rs.getApplicationContext().getResources().getIdentifier(  
  32.                  __rs_resource_name, "raw",  
  33.                  rs.getApplicationContext().getPackageName()));  
  34.     }  
  35.   
  36.     public  MyScriptC_convolve3x3(RenderScript rs, Resources resources, int id) {  
  37.         super(rs, resources, id);  
  38.         __I32 = Element.I32(rs);  
  39.         __ALLOCATION = Element.ALLOCATION(rs);  
  40.         __F32 = Element.F32(rs);  
  41.         __U8_4 = Element.U8_4(rs);  
  42.     }  
  43.   
  44.     private Element __ALLOCATION;  
  45.     private Element __F32;  
  46.     private Element __I32;  
  47.     private Element __U8_4;  
  48.     private FieldPacker __rs_fp_ALLOCATION;  
  49.     private FieldPacker __rs_fp_F32;  
  50.     private FieldPacker __rs_fp_I32;  
  51.     private final static int mExportVarIdx_gWidth = 0;  
  52.     private int mExportVar_gWidth;  
  53.     public synchronized void set_gWidth(int v) {  
  54.         setVar(mExportVarIdx_gWidth, v);  
  55.         mExportVar_gWidth = v;  
  56.     }  
  57.   
  58.     public int get_gWidth() {  
  59.         return mExportVar_gWidth;  
  60.     }  
  61.   
  62.     public Script.FieldID getFieldID_gWidth() {  
  63.         return createFieldID(mExportVarIdx_gWidth, null);  
  64.     }  
  65.   
  66.     private final static int mExportVarIdx_gHeight = 1;  
  67.     private int mExportVar_gHeight;  
  68.     public synchronized void set_gHeight(int v) {  
  69.         setVar(mExportVarIdx_gHeight, v);  
  70.         mExportVar_gHeight = v;  
  71.     }  
  72.   
  73.     public int get_gHeight() {  
  74.         return mExportVar_gHeight;  
  75.     }  
  76.   
  77.     public Script.FieldID getFieldID_gHeight() {  
  78.         return createFieldID(mExportVarIdx_gHeight, null);  
  79.     }  
  80.   
  81.     private final static int mExportVarIdx_gPixels = 2;  
  82.     private Allocation mExportVar_gPixels;  
  83.     public void bind_gPixels(Allocation v) {  
  84.         mExportVar_gPixels = v;  
  85.         if (v == null) bindAllocation(null, mExportVarIdx_gPixels);  
  86.         else bindAllocation(v, mExportVarIdx_gPixels);  
  87.     }  
  88.   
  89.     public Allocation get_gPixels() {  
  90.         return mExportVar_gPixels;  
  91.     }  
  92.   
  93.     private final static int mExportVarIdx_gIn = 3;  
  94.     private Allocation mExportVar_gIn;  
  95.     public synchronized void set_gIn(Allocation v) {  
  96.         setVar(mExportVarIdx_gIn, v);  
  97.         mExportVar_gIn = v;  
  98.     }  
  99.   
  100.     public Allocation get_gIn() {  
  101.         return mExportVar_gIn;  
  102.     }  
  103.   
  104.     public Script.FieldID getFieldID_gIn() {  
  105.         return createFieldID(mExportVarIdx_gIn, null);  
  106.     }  
  107.   
  108.     private final static int mExportVarIdx_gCoeffs = 4;  
  109.     private float[] mExportVar_gCoeffs;  
  110.     public synchronized void set_gCoeffs(float[] v) {  
  111.         mExportVar_gCoeffs = v;  
  112.         FieldPacker fp = new FieldPacker(36);  
  113.         for (int ct1 = 0; ct1 < 9; ct1++) {  
  114.             fp.addF32(v[ct1]);  
  115.         }  
  116.   
  117.         int []__dimArr = new int[1];  
  118.         __dimArr[0] = 9;  
  119.         setVar(mExportVarIdx_gCoeffs, fp, __F32, __dimArr);  
  120.     }  
  121.   
  122.     public float[] get_gCoeffs() {  
  123.         return mExportVar_gCoeffs;  
  124.     }  
  125.   
  126.     public Script.FieldID getFieldID_gCoeffs() {  
  127.         return createFieldID(mExportVarIdx_gCoeffs, null);  
  128.     }  
  129.   
  130.     private final static int mExportForEachIdx_root = 0;  
  131.     public Script.KernelID getKernelID_root() {  
  132.         return createKernelID(mExportForEachIdx_root, 3nullnull);  
  133.     }  
  134.   
  135.     public void forEach_root(Allocation ain, Allocation aout) {  
  136.         // check ain  
  137.         if (!ain.getType().getElement().isCompatible(__U8_4)) {  
  138.             throw new RSRuntimeException("Type mismatch with U8_4!");  
  139.         }  
  140.         // check aout  
  141.         if (!aout.getType().getElement().isCompatible(__U8_4)) {  
  142.             throw new RSRuntimeException("Type mismatch with U8_4!");  
  143.         }  
  144.         // Verify dimensions  
  145.         Type tIn = ain.getType();  
  146.         Type tOut = aout.getType();  
  147.         if ((tIn.getCount() != tOut.getCount()) ||  
  148.             (tIn.getX() != tOut.getX()) ||  
  149.             (tIn.getY() != tOut.getY()) ||  
  150.             (tIn.getZ() != tOut.getZ()) ||  
  151.             (tIn.hasFaces() != tOut.hasFaces()) ||  
  152.             (tIn.hasMipmaps() != tOut.hasMipmaps())) {  
  153.             throw new RSRuntimeException("Dimension mismatch between input and output parameters!");  
  154.         }  
  155.         forEach(mExportForEachIdx_root, ain, aout, null);  
  156.     }  
  157.   
  158. }  

經過上述步驟,基於Android4.2源碼的Gallery2Camera模塊在eclipse裏面已能正常編譯,生成對應的apk,貼一張“劫後照”:



二、apk安裝

在Run As Android Application時, 接入真機後Console上會報錯:Re-installation failed due to different application signatures。You must perform a full uninstall of the application. WARNING: This will remove the application data! Please execute 'adb uninstall com.android.gallery3d' in a shell.接着就退出了。但用模擬器運行則不會有錯。從上面的錯誤信息中容易知道,這是因爲現在的Android手機中很多已有了gallery3d系列應用,安裝同名(我對應的版本號在AndroidManifest.xml下顯示是1.1.40001)包會報衝突——有人就更改了包名,後面一路安裝順暢,最後在手機上出現了兩個圖庫和相機應用。我沒有這樣做,選擇的是刪掉舊的應用包(系統默認包),安裝新應用包。

       查閱了一些文檔,發現此方法簡單有效——手機接入電腦,在windows下打開cmd,在adb.exe安裝路徑下使用adb shell進入手機真是系統級目錄(區別於用戶級目錄),可以在/system/app下面看到Gallery.apk,使用rm命令刪除之。再次回到eclipse裏run項目的時候,依然會報Installation error: INSTALL_FAILED_UPDATE_INCOMPATIBLE錯誤。google一下,有人說是前一步刪除舊的應用包時刪的不太乾淨,因爲/data/system/package.xml文件中或許還包含了該應用的相關信息,建議使用界面操作setting—>applications—>manage applications—>應用—> application Info —>uninstall進行優雅卸載。果然在我的手機setting下還能看到對應應用,於是我“強行停用”,並選擇“清除數據”,“清除緩存”,重啓了以後,再次clean,run,success!歪歪扭扭的圖庫+相機應用出現在了桌面上。(PS:剛開始相機有不明原因的卡頓,重啓了兩次手機後,ok了——目前不知曉原理,也許與系統launch之間需要一點點磨合?!)



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章