久久99精品久久久久久琪琪,久久人人爽人人爽人人片亞洲,熟妇人妻无码中文字幕,亚洲精品无码久久久久久久

Ubuntu 11.10編譯Android源碼錯誤[范文大全]

時間:2019-05-13 23:25:26下載本文作者:會員上傳
簡介:寫寫幫文庫小編為你整理了多篇相關的《Ubuntu 11.10編譯Android源碼錯誤》,但愿對你工作學習有幫助,當然你在寫寫幫文庫還可以找到更多《Ubuntu 11.10編譯Android源碼錯誤》。

第一篇:Ubuntu 11.10編譯Android源碼錯誤

Ubuntu 11.10編譯Android源碼錯誤

問題1:

frameworks/base/libs/utils/RefBase.cpp: 在成員函數

‘void android::RefBase::weakref_type::trackMe(bool, bool)’中:

frameworks/base/libs/utils/RefBase.cpp:483:67: 錯誤: 將

‘constandroid::RefBase::weakref_impl’作為

‘voidandroid::RefBase::weakref_impl::trackMe(bool, bool)’的‘this’實參時丟棄了類型限定[-fpermissive]

make: *** [out/host/linux-x86/obj/STATIC_LIBRARIES/libutils_intermediates/RefBase.o] 錯誤 1 原因:Ubuntu 11.10的gcc 4.6版本太高了,android編譯需要gcc 4.4

解決辦法:更換gcc、g++版本4.6為4.4

sudo apt-get install gcc-4.4

sudo apt-get install g++-4.4

sudo rm-rf /usr/bin/gcc /usr/bin/g++

sudo ln-s /usr/bin/gcc-4.4 /usr/bin/gcc

sudo ln-s /usr/bin/g++-4.4 /usr/bin/g++

問題2:

g++: 錯誤: –fpermissive:沒有那個文件或目錄

make: *** [out/host/linux-x86/obj/STATIC_LIBRARIES/libutils_intermediates/RefBase.o] 錯誤 1 解決辦法:sudoapt-get install g++-4.4-multilib

經過此操作編譯可順利進行。

第二篇:Android源碼編譯整理總結

1.必要的軟件環境

sudo apt-get install build-essential sudo apt-get install make sudo apt-get install gcc sudo apt-get install g++ sudo apt-get install libc6-dev sudo apt-get install patch sudo apt-get install texinfo sudo apt-get install libncurses-dev sudo apt-get install git-core gnupg sudo apt-get install flex bison gperf libsdl-dev libesd0-dev libwxgtk2.6-dev build-essential zip curl sudo apt-get install ncurses-dev sudo apt-get install zlib1g-dev sudo apt-get install valgrind sudo apt-get install python2.5

筆者發現這里已經比較全來,不過還有一些應該是linux系統自帶的,如果缺少就按照提示install一下

安裝java環境,這里有必要說一下,大家裝環境的時候很多人會一起裝,不過筆者建議java和其他的分開,因為裝java很可能會失敗,從而導致其他的也fail sudo apt-get install sun-java6-jdk

這里就說到上面說很多人會安裝java失敗的問題,筆者也是從網上找的解決辦法現在一起整理出來:

ubuntu10.04 lucid 去掉了sun-java6-jre,sun-java6-jdk的源,所以如果是直接apt-get install 提示是

現在沒有可用的軟件包 sun-java6-jdk,但是它被其它的軟件包引用了。

這可能意味著這個缺失的軟件包可能已被廢棄,或者只能在其他發布源中找到

E: 軟件包 sun-java6-jdk 還沒有可供安裝的候選者

解決辦法(選擇一個即可):

1、系統->系統管理->軟件源->“其它軟件”下添加一個 deb http://archive.canonical.com/ lucid partner

之后,再執行apt-get install 如果是下載java5就添加deb http://us.archive.ubuntu.com/ubuntu/ jaunty multiverse”

2、自己從sun網站下載相應的Jre,JDK安裝即可

3、從新立德軟件管理器中search openJDK,用openJDK代替

注: 官方文檔說如果用sun-java6-jdk可出問題,得要用sun-java5-jdk。經測試發現,如果僅僅make(make不包括make sdk),用sun-java6-jdk是沒有問題的。而make sdk,就會有問題,嚴格來說是在make doc出問題,它需要的javadoc版本為1.5。

因此,我們安裝完sun-java6-jdk后最好再安裝sun-java5-jdk,或者 只安裝sun-java5-jdk。這里sun-java6-jdk和sun-java5-jdk都安裝,并只修改javadoc.1.gz和 javadoc。因為只有這兩個是make sdk用到的。這樣的話,除了javadoc工具是用1.5版本,其它均用1.6版本: sudo apt-get install sun-java5-jdk 修改javadoc的link cd /etc/alternatives sudo rm javadoc.1.gz

sudo ln-s /usr/lib/jvm/java-1.5.0-sun/man/man1/javadoc.1.gz javadoc.1.gz sudo rm javadoc sudo ln-s /usr/lib/jvm/java-1.5.0-sun/bin/javadoc javadoc

2、設置環境變量 vim ~/.bashrc 在.bashrc中新增或整合PATH變量,如下 #java 程序開發/運行的一些環境變量 JAVA_HOME=/usr/lib/jvm/java-6-sun JRE_HOME=${JAVA_HOME}/jre export ANDROID_JAVA_HOME=$JAVA_HOME export CLASSPATH=.:${JAVA_HOME}/lib:$JRE_HOME/lib:$CLASSP ATH export JAVA_PATH=${JAVA_HOME}/bin:${JRE_HOME}/bin export JAVA_HOME;export JRE_HOME;export CLASSPATH;HOME_BIN=~/bin/ export PATH=${PATH}:${JAVA_PATH}:${JRE_PATH}:${HOME_BIN};#echo $PATH;最后,同步這些變化: source ~/.bashr 3.安裝repo(用來更新android源碼)

創建~/bin目錄,用來存放repo程序,如下: $ cd ~ $ mkdir bin 并加到環境變量PATH中,在第2步中已經加入 下載repo腳本并使其可執行:

$ curl http://android.git.kernel.org/repo >~/bin/repo $ chmod a+x ~/bin/repo 4.初始化repo

repo是android對git的一個封裝,簡化了一些git的操作。創建工程目錄: $ mkdir android $ cd android repo初始化

$ repo init-u git://android.git.kernel.org/platform/manifest.git 這里包含了android最新的源碼

在此過程中需要輸入名字和email地址。初始化成功后,會顯示: repo initialized in /android 在~/android下會有一個.repo的隱藏目錄。

如果想拿某個branch而不是主線上的代碼,我們需要用-b參數制定branch名字,比如:

repo init-u git://android.git.kernel.org/platform/manifest.git-b cupcake 這 里抓下來的分支是cupcake,網上關于編譯到文章大多是針對cupcake分支,是andoird 1.5版本,但是之前我沒有輸入后面的參數,以致于下到的代碼是主線上的代碼,是android 2.1版本。兩者目錄結構有一些差別,導致當我按照網上的說明步驟來執行遇到錯誤時,不知道是版本不同的原因還是其他什么原因。因此很奇怪為什么網上的文 章都是說cupcake的,而沒有怎么講主線的源代碼編譯。5.同步源代碼 $ repo sync 這一步要很久,要看個人的網絡速度

6.編譯android源碼,并得到~/android/out目錄 $ cd ~/andoird

$ make-j2 筆者的電腦是雙核所以是-j2,以此類推8核就可以-j8 這一過程很久,主要看機器的配置

如果是cupcake,那么直接make的時候,會出現以下錯誤:

1.frameworks/policies/base/PolicyConfig.mk:22: *** No module defined for the given PRODUCT_POLICY(android.policy_phone).Stop.錯誤。

解決辦法:

在build/tools/findleaves.sh中的第89行,這一句find “${@:0:$nargs}” $findargs-type f-name “$filename”-print |

改為find “${@:1:$nargs-1}” $findargs-type f-name “$filename”-print |

2.frameworks/base/tools/aidl/AST.cpp:10: error: 'fprintf' was not declared in this scope的錯誤

解決辦法:

下載gcc-4.3和g++-4.3

apt-get install gcc-4.3 g++-4.3

因為ubuntu 9.10自帶到是gcc 4.4,因此需要重新下載gcc 4.3,最后設置gcc軟連接到gcc 4.3

進入/usr/bin cd /usr/bin

建個軟連接

ln-s gcc-4.3 gcc

ln-s g++-4.3 g++

然后進入android目錄下,執行make,就可以了。

主線代碼則沒有此問題 7.在模擬器上運行編譯好的android

編譯好android之后,emulator在~/android/out/host/linux-x86/bin 下,ramdisk.img,system.img和userdata.img則在~/android/out/target/product /generic下 $ cd ~/android/out/host/linux-x86/bin 增加環境變量 $ emacs ~/.bashrc 在.bashrc中新增環境變量,如下 #java 程序開發/運行的一些環境變量

export ANDROID_PRODUCT_OUT=~/android/out/target/product/g eneric ANDROID_PRODUCT_OUT_BIN=~/android/out/host/linux-x 86/bin export PATH=${PATH}:${ANDROID_PRODUCT_OUT_BIN}:${ANDROID_ PRODUCT_OUT};最后,同步這些變化: $ source ~/.bashrc $ cd ~/android/out/target/product/generic

$ emulator-system system.img-data userdata.img-ramdisk ramdisk.img 最后進入android桌面,就說明成功了。8.編譯模塊

android中的一個應用程序可以單獨編譯,編譯后要重新生成system.img 在源碼目錄下執行

$.build/envsetup.sh(.后面有空格)就多出一些命令:

-croot: Changes directory to the top of the tree.mm: Builds all of the modules in the current directory.cgrep: Greps on all local C/C++ files.resgrep: Greps on all local res/*.xml files.-godir: Go to the directory containing a file.可以加—help查看用法

我們可以使用mmm來編譯指定目錄的模塊,如編譯聯系人: $ mmm packages/apps/Contacts/ 編完之后生成兩個文件: out/target/product/generic/data/app/ContactsTests.apk out/target/product/generic/system/app/Contacts.apk 可以使用 $ make snod 重新生成system.img,再運行模擬器 9.編譯SDK

直接執行make是不包括make sdk的。make sdk用來生成SDK,這樣,我們就可以用與源碼同步的SDK來開發android了。

a)修改/frameworks/base/include/utils/Asset.h ?UNCOMPRESS_DATA_MAX = 1 * 1024 * 1024? 改為 ?UNCOMPRESS_DATA_MAX = 2 * 1024 * 1024?

原因是eclipse編譯工程需要大于1.3M的buffer;

這一步,筆者編譯的是主線程的,在Asset.h文件里沒找到上面的常量,所以就沒做這一步,但是也成功了。b)編譯ADT。

如果想用eclipse開發android應用程序,最好是安裝ADT,這樣就可以在eclipse下創建android的工程。

產生ADT eclipse plugins $ development/tools/eclipse/scripts/build_server.sh ~/adt/

使用前建議設定一下ECLIPSE_HOME的環境變量,不然會以為沒有裝eclipse,然后幫你download下來。

這里要非常注意,本人就曾經卡在這里,始終編譯不過。一開始會提示eclipse的什么什么jar找不到,因此fail。這主要是因為我到 ECLIPSE_HOME到環境變量設置錯誤。我之前裝的eclipse只從新力得上面抓下來的,好像找不到eclipse所在到目錄是哪個,結果就設置 了一個名為eclipse的文件夾作為環境變量。因此后來直接從eclipse的官網上下了一個,以為這樣就可以。結果杯具的是下到是一個eclipse Galileo,到頭來還是提示eclipse什么什么文件找不到。最后實在沒法,索性把eclipse刪個干凈,讓程序自己去下eclipse,發現抓 的是eclipse ganymede。在此要鄭重說明一下,自己去下的話應該下載jee的ganymade,而不能是java 的ganymade,具體原因試試就知道了。

主線代碼編譯ADT的時候方法相同,但是沒有development/tools/eclipse這個目錄,而是在/sdk/eclipse這個目錄 c)執行make sdk。

注意,這里需要的javadoc版本為1.5,所以你需要在步驟1中同時安裝sun-java5-jdk $ make sdk

編譯很慢。編譯后生成的SDK存放在out/host/linux-x86/sdk/,此目錄下有android-sdk_eng.xxx_linux-x86.zip和android-sdk_eng.xxx_linux-x86目錄。android-sdk_eng.xxx_linux-x86就是 SDK目錄

實際上,當用mmm命令編譯模塊時,一樣會把SDK的輸出文件清除,因此,最好把android-sdk_eng.xxx_linux-x86移出來

此后的應用開發,就在該SDK上進行,所以把7)對于~/.bashrc的修改注釋掉,增加如下一行:

export PATH=${PATH}:~/android/out/host/linux-x86/sdk/andr oid-sdk_eng.xxx_linux-x86/tools 注意要把xxx換成真實的路徑;

同樣筆者編譯的是主線程,所以編譯完之后,發現~/android/out/host/linux-x86/sdk/android-sdk_eng.x xx_linux-x86/目錄下有2個文件夾一個是tools一個是platform-tools,然后用eclipse指向這個目錄的時候會提示找不到ADB,這時候只要把platform-tools下的ADB拷貝到tools文件夾就OK了 d)關于環境變量、android工具的選擇 目前的android工具有:

A、我們從網上下載的SDK,如果你下載過的話(tools下有許多android工具,lib/images下有img映像)

B、我們用make sdk編譯出來的SDK(tools下也有許多android工具,lib/images下有img映像)

C、我們用make編譯出來的out目錄(tools下也有許多android工具,lib/images下有img映像)

那么我們應該用那些工具和img呢?

首先,我們一般不會用A選項的工具和img,因為一般來說它比較舊,也源碼不同步。其次,也不會用C選項的工具和img,因為這些工具和img沒有經過 SDK的歸類處理,會有工具和配置找不到的情況;事實上,make sdk產生的很多工具和img,在make編譯出來out目錄的時候,已經編譯產生了,make sdk只是做了copy而已。e)安裝、配置ADT

~/adt/android-eclipse/下的文件壓縮,然后從eclipse中install就行了,當然還有其他方法 10.編譯linux內核映像 a)準備交叉編譯工具鏈

android代碼樹中有一個prebuilt項目,包含了我們編譯內核所需的交叉編譯工具。b)設定環境變量 $ emacs ~/.bashrc 增加如下兩行:

export PATH=$PATH:~/android/prebuilt/linux-x86/toolchain/ arm-eabi-4.4.0/bin export ARCH=arm 保存后,同步變化: $ source ~/.bashrc c)獲得合適的內核源代碼 $ cd ~/android 獲得內核源代碼倉庫

$ git clone git://android.git.kernel.org/kernel/common.git kernel $ cd kernel $ git branch 顯示 * android-2.6.27

說明你現在在android-2.6.27這個分支上,也是kernel/common.git的默認主分支。顯示所有head分支: $ git branch-a 顯示 * android-2.6.27 remotes/origin/HEAD-> origin/android-2.6.27 remotes/origin/android-2.6.25 remotes/origin/android-2.6.27 remotes/origin/android-2.6.29 remotes/origin/android-goldfish-2.6.27 remotes/origin/android-goldfish-2.6.29

我們選取最新的android-goldfish-2.6.29,其中goldfish是android的模擬器模擬的CPU。

$ git checkout-b android-goldfish-2.6.29 origin/android-goldfish-2.6.29 $ git branch 顯示 android-2.6.27 * android-goldfish-2.6.29 我們已經工作在android-goldfish-2.6.29分支上了。d)設定交叉編譯參數

打開kernel目錄下的Makefile文件,把CROSS_COMPILE指向剛才下載的prebuilt中的arm-eabi編譯器

CROSS_COMPILE ?= arm-eabi-把 LDFLAGS_BUILD_ID = $(patsubst-Wl$(comma)%,%, $(call ld-option,-Wl$(comma)build-id,))

這一行注釋掉,并且添加一個空的LDFLAGS_BUILD_ID定義,如下: LDFLAGS_BUILD_ID = e)編譯內核映像 $ cd ~/android/kernel $ make goldfish_defconfig $ make f)測試生成的內核映像

$ emulator-avd myavd-kernel ~/android/kernel/arch/arm/boot/zImage

第三篇:android有關sensor的源碼總結

android有關sensor的源碼總結

雖然這篇文章寫得很差,因為趕時間,所以就匆匆忙忙地寫出來自己作一個筆記。但是我想對大家應該有一點幫助。

1、有關sensor在Java應用程序的編程(以注冊多個傳感器為例,這程序是我臨時弄出來的,可能有錯)

package com.sensors.acc;

import android.app.Activity;import android.os.Bundle;

import android.util.Log;import android.widget.TextView;import android.hardware.SensorManager;import android.hardware.Sensor;import android.hardware.SensorEvent;import android.hardware.SensorEventListener;

public class acc extends Activity { float x, y, z;SensorManager sensormanager = null;Sensor accSensor = null;Sensor lightSensor = null;Sensor proximitySensor = null;TextView accTextView = null;/** Called when the activity is first created.*/ @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState);setContentView(R.layout.main);sensormanager =(SensorManager)getSystemService(SENSOR_SERVICE);accSensor = sensormanager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);lightSensor = sensormanager.getDefaultSensor(Sensor.TYPE_LIGHT);proximitySensor = sensormanager.getDefaultSensor(Sensor.TYPE_PROXIMITY);accTextView =(TextView)findViewById(R.id.textview_name);}

SensorEventListener lsn = new SensorEventListener(){ public void onSensorChanged(SensorEvent e){ if(e.sensor == accSensor){ Log.d(“sensor”, “found acc sensor”);x = e.values[SensorManager.DATA_X];y = e.values[SensorManager.DATA_Y];z = e.values[SensorManager.DATA_Z];accTextView.setText(“x = ” + x + “, ny = ” + y + “, nz = ” + z);} else if(e.sensor == lightSensor){ Log.d(“sensor”, “found light sensor”);accTextView.setText(“data is ” + e.values[0]);} else if(e.sensor == proximitySensor){ Log.d(“sensor”, “found proximity sensor”);accTextView.setText(“distance is ” + e.values[0]);} }

public void onAccuracyChanged(Sensor s, int accuracy){ } };@Override protected void onResume(){ super.onResume();// register this class as a listener for the orientation and accelerometer sensors sensormanager.registerListener(lsn, accSensor, SensorManager.SENSOR_DELAY_NORMAL);sensormanager.registerListener(lsn, lightSensor, SensorManager.SENSOR_DELAY_NORMAL);sensormanager.registerListener(lsn, proximitySensor, SensorManager.SENSOR_DELAY_NORMAL);// sensormanager.unregisterListener(lsn);} @Override protected void onStop(){ // unregister listener sensormanager.unregisterListener(lsn, accSensor);sensormanager.unregisterListener(lsn, lightSensor);sensormanager.unregisterListener(lsn, proximitySensor);super.onStop();} }

在onCreate()函數中,調用getSystemService(SENSOR_SERVICE)初始化一個SensorManager實例,為什么要用getSystemService函數,而不直接用new SensorManager呢?我們看此函數的實現,在ApplicationContext.java中,if(SENSOR_SERVICE.equals(name)){ return getSensorManager();然后getSensorManager()的實現

private SensorManager getSensorManager(){ synchronized(mSync){ if(mSensorManager == null){ mSensorManager = new SensorManager(mMainThread.getHandler().getLooper());} } return mSensorManager;} 看到沒有?初始化SensorManager的時候需要mMainThread.getHandler().getLooper()這個參數,之個應該是用來傳遞消息用的,在SensorManager類的構造函數中會把此參數傳給類成員mMainLooper。如果用new SensorManager()就需要另外獲取mainLooper參數傳遞進去。

2、在android中跟sensor有關的一些文件有SensorManager.java,位于frameworksbasecorejavaandroidhardware目錄下,SensorService.java,位于frameworksbaseservicesjavacomandroidserver目錄下,android_hardware_SensorManager.cpp,位于frameworksbasecorejni目錄下,與SensorManager.java相對應,com_android_server_SensorService.cpp,在frameworksbaseservicesjni目錄下,與SensorService.java相對應。還有SystemServer.java文件,HardwareLibhardwareIncludeHardware目錄下的Sensor.h頭文件。另外我們需要根據Sensor.h實現自己的一個源文件,一般取名為sensors_xxx.c或者sensors_xxx.cpp。

3、SensorManager類分析 有幾個函數比較重要,必須清晰理解它們的實現,才能了解整個傳感器系統的實現。從而更好地去實現硬件抽象層的實現。幾個比較重要的函數有構造函數SensorManager(), registerListener()和unregisterListener(),其中registerListener()和unregisterListener()有多個,標志為 @Deprecated的是過時的,就不要看了。(1)構造函數SensorManager(Looper mainLooper)這個函數首先獲取得傳感器系統服務,并賦給類成員mSensorService,mSensorService = ISensorService.Stub.asInterface(ServiceManager.getService(Context.SENSOR_SERVICE));這里我要說一句,就是關于這個傳感器系統服務,很多書上都說用getSystemService()是獲得傳感器的系統服務,而它返回的是SensorManager類型,所以以為整個系統都是使用同一個SensorManager類的實例,以為我們在任何地方使用的SensorManager實例都是同一個,它們的公共成員是共享的。但是經過這兩天的分析,這種說法是錯誤的。其實每次調用getSystemService()函數時都初始化一個新的SensorManager實例,而這個SensorManager實例會在構造函數里通過取得傳感器系統服務SensorService來實現對下層傳感器的一些控制。而這個SensorService才是系統的傳感器服務,說服務,不如說它只是SensorService類的一個實例罷了。它只在系統初始化時初始化一次。Android中的系統服務機制應該跟傳感器的都差不多一個樣,都是由不同的Manager調用下層相同的Service。你可以列舉其它的Manager。那它是什么時候初始化呢?它是系統初始化在SystemServer進程里創建的,SystemServer是一個管理很多系統服務的進程,我們轉到SystemServer.的main函數里,可以看到一直到調用int2()函數,它會創建一個ServerThread,最終調用AdbSettingsObserver類的run()函數,在run()函數里有這么有一句

// Sensor Service is needed by Window Manager, so this goes first Log.i(TAG, “Sensor Service”);ServiceManager.addService(Context.SENSOR_SERVICE, new SensorService(context));這里就創建SensorService實例了。在創建這個實例時會在SensorService構造函數中調用jni函數 public SensorService(Context context){ if(localLOGV)Log.d(TAG, “SensorService startup”);_sensors_control_init();} 我們看_sensors_control_init();對應的為 static jint android_init(JNIEnv *env, jclass clazz){ sensors_module_t* module;if(hw_get_module(SENSORS_HARDWARE_MODULE_ID,(const hw_module_t**)&module)== 0){ if(sensors_control_open(&module->common, &sSensorDevice)== 0){ const struct sensor_t* list;int count = module->get_sensors_list(module, &list);return count;} } return 0;} 它主要調用了sensor.h中的sensors_control_open()static inline int sensors_control_open(const struct hw_module_t* module, struct sensors_control_device_t** device){ return module->methods->open(module, SENSORS_HARDWARE_CONTROL,(struct hw_device_t**)device);} 之后在系統任何地方使用的都是這個SensorService實例。最后run()函數調用Looper.loop();就進行消息循環等待了,這就是SystemServer進程的消息服務了。這才真正叫做系統服務嘛。

我們繼續看SensorManager類的構造函數,取得SensorService后,nativeClassInit();這是一個jni函數,SensorManager類調用的jni函數都在com_android_server_SensorService.cpp里,我們看這函數 static void nativeClassInit(JNIEnv *_env, jclass _this){ jclass sensorClass = _env->FindClass(“android/hardware/Sensor”);SensorOffsets& sensorOffsets = gSensorOffsets;sensorOffsets.name = _env->GetFieldID(sensorClass, “mName”, “Ljava/lang/String;”);sensorOffsets.vendor = _env->GetFieldID(sensorClass, “mVendor”, “Ljava/lang/String;”);sensorOffsets.version = _env->GetFieldID(sensorClass, “mVersion”, “I”);sensorOffsets.handle = _env->GetFieldID(sensorClass, “mHandle”, “I”);sensorOffsets.type = _env->GetFieldID(sensorClass, “mType”, “I”);sensorOffsets.range = _env->GetFieldID(sensorClass, “mMaxRange”, “F”);sensorOffsets.resolution = _env->GetFieldID(sensorClass, “mResolution”,“F”);sensorOffsets.power = _env->GetFieldID(sensorClass, “mPower”, “F”);} 這個函數只是獲取和設置一些信息吧,我們不關心。接著 sensors_module_init();我們看這函數 static jint sensors_module_init(JNIEnv *env, jclass clazz){ int err = 0;sensors_module_t const* module;err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,(const hw_module_t **)&module);if(err == 0)sSensorModule =(sensors_module_t*)module;return err;} 它獲取了sensor的模塊信息,并把它賦給sSensorModule全局變量,之后傳的modules參數都為這個。接著在構造函數里

final ArrayList fullList = sFullSensorsList;int i = 0;do { Sensor sensor = new Sensor();i = sensors_module_get_next_sensor(sensor, i);

if(i>=0){ Log.d(TAG, “found sensor: ” + sensor.getName()+ “, handle=” + sensor.getHandle());sensor.setLegacyType(getLegacySensorType(sensor.getType()));fullList.add(sensor);sHandleToSensor.append(sensor.getHandle(), sensor);} } while(i>0);這里主要是通過jni函數sensors_module_get_next_sensor(sensor, i);獲取傳感器列表,并把它加入自己的fullList列表中。我們看sensors_module_get_next_sensor()函數 static jint sensors_module_get_next_sensor(JNIEnv *env, jobject clazz, jobject sensor, jint next){ if(sSensorModule == NULL)return 0;

SensorOffsets& sensorOffsets = gSensorOffsets;const struct sensor_t* list;int count = sSensorModule->get_sensors_list(sSensorModule, &list);if(next >= count)return-1;

list += next;

jstring name = env->NewStringUTF(list->name);jstring vendor = env->NewStringUTF(list->vendor);env->SetObjectField(sensor, sensorOffsets.name, name);env->SetObjectField(sensor, sensorOffsets.vendor, vendor);env->SetIntField(sensor, sensorOffsets.version, list->version);env->SetIntField(sensor, sensorOffsets.handle, list->handle);env->SetIntField(sensor, sensorOffsets.type, list->type);env->SetFloatField(sensor, sensorOffsets.range, list->maxRange);env->SetFloatField(sensor, sensorOffsets.resolution, list->resolution);env->SetFloatField(sensor, sensorOffsets.power, list->power);next++;return next } 它主要是調用HAL層的get_sensors_list()函數取得傳感器列表信息。接著在sensorManger構造函數最后

sSensorThread = new SensorThread();創建一個SensorThread()線程。但并未運行,但在SensorThread類的構造函數里會執行jni函數 sensors_data_init();我們看此函數static jint sensors_data_init(JNIEnv *env, jclass clazz){ if(sSensorModule == NULL)return-1;int err = sensors_data_open(&sSensorModule->common, &sSensorDevice);return err;} 它調用了HAL層的sensors_data_open函數,而這個函數位于sensor.h中,它調用的是 static inline int sensors_data_open(const struct hw_module_t* module, struct sensors_data_device_t** device){ return module->methods->open(module, SENSORS_HARDWARE_DATA,(struct hw_device_t**)device);} Modules->methods->open函數。而在SensorThread類的析構函數finalize()里會調用 sensors_data_uninit();static jint sensors_data_uninit(JNIEnv *env, jclass clazz){ int err = 0;if(sSensorDevice){ err = sensors_data_close(sSensorDevice);if(err == 0)sSensorDevice = 0;} return err;} 在sensor.h里

static inline int sensors_data_close(struct sensors_data_device_t* device){ return device->common.close(&device->common);} 那什么時候sSensorThread線程會運行呢?我們在下面看registerListener()函數。

(2)public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate){ return registerListener(listener, sensor, rate, null);} 它調用的是 public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate, Handler handler)在這函數中,先驗證rate,然后檢測注冊的listener在不在本類的sListeners列表中。for(ListenerDelegate i : sListeners){ if(i.getListener()== listener){ l = i;break;} } 如果不在就申請一個listener,并把它加入全局列表sListener中,并調用mSensorService的enableSensor()函數使能傳感器,這個enableSensor()函數最終會調用HAL層的active函數和set_delay()函數,使用后然后判斷sListener列表是否為空,當然,第一次為空時加入一個新的listener就不為空了,此時就執行sSensorThread的startLocked運行sSensorThread線程了

l = new ListenerDelegate(listener, sensor, handler);result = mSensorService.enableSensor(l, name, handle, delay);if(result){ sListeners.add(l);sListeners.notify();} if(!sListeners.isEmpty()){ sSensorThread.startLocked(mSensorService);} 另一方面,如果注冊的listener在sListeners列表中,則先調用mSensorService的enableSensor()函數使能傳感器,然后把注冊的傳感器加入到已存在的listener中。result = mSensorService.enableSensor(l, name, handle, delay);if(result){ l.addSensor(sensor);} 接下來我們看看startLocked函數,它在SensorThread中,void startLocked(ISensorService service){ try { if(mThread == null){ Bundle dataChannel = service.getDataChannel();mThread = new Thread(new SensorThreadRunnable(dataChannel), SensorThread.class.getName());mThread.start();} } catch(RemoteException e){ Log.e(TAG, “RemoteException in startLocked: ”, e);} } 第一次mThread為null,然后它調用了service.getDataChannel()函數,此函數在SensorService類中,主要調用了jni函數_sensors_control_open(),public Bundle getDataChannel()throws RemoteException { // synchronize so we do not require sensor HAL to be thread-safe.synchronized(mListeners){ return _sensors_control_open();} } SensorService類中調用的jni函數主要都在com_android_server_SensorService.cpp文件 中,我們看一下這個函數 static jobject android_open(JNIEnv *env, jclass clazz){ native_handle_t* handle = sSensorDevice->open_data_source(sSensorDevice);if(!handle){ return NULL;}

// new Bundle()jobject bundle = env->NewObject(gBundleOffsets.mClass, gBundleOffsets.mConstructor);

if(handle->numFds > 0){ jobjectArray fdArray = env->NewObjectArray(handle->numFds, gParcelFileDescriptorOffsets.mClass, NULL);for(int i = 0;i < handle->numFds;i++){ // new FileDescriptor()jobject fd = env->NewObject(gFileDescriptorOffsets.mClass, gFileDescriptorOffsets.mConstructor);env->SetIntField(fd, gFileDescriptorOffsets.mDescriptor, handle->data[i]);// new ParcelFileDescriptor()jobject pfd = env->NewObject(gParcelFileDescriptorOffsets.mClass, gParcelFileDescriptorOffsets.mConstructor, fd);env->SetObjectArrayElement(fdArray, i, pfd);} // bundle.putParcelableArray(“fds”, fdArray);env->CallVoidMethod(bundle, gBundleOffsets.mPutParcelableArray, env->NewStringUTF(“fds”), fdArray);}

if(handle->numInts > 0){ jintArray intArray = env->NewIntArray(handle->numInts);env->SetIntArrayRegion(intArray, 0, handle->numInts, &handle->data[handle->numInts]);// bundle.putIntArray(“ints”, intArray);env->CallVoidMethod(bundle, gBundleOffsets.mPutIntArray, env->NewStringUTF(“ints”), intArray);}

// delete the file handle, but don't close any file descriptors native_handle_delete(handle);return bundle;} 它主要調用了HAL層的open_data_source()函數。取得一些文件描述符等信息。接下來SensorThread創建一個線程,調用start()就進入SensorThreadRunnable類的run()函數了,所以我們接著去看run()函數,它首先調用open()函數 if(!open()){ return;} 在open()函數中調用了 jni函數sensors_data_open(fds, ints);static jint sensors_data_open(JNIEnv *env, jclass clazz, jobjectArray fdArray, jintArray intArray){ jclass FileDescriptor = env->FindClass(“java/io/FileDescriptor”);jfieldID fieldOffset = env->GetFieldID(FileDescriptor, “descriptor”, “I”);int numFds =(fdArray ? env->GetArrayLength(fdArray): 0);int numInts =(intArray ? env->GetArrayLength(intArray): 0);native_handle_t* handle = native_handle_create(numFds, numInts);int offset = 0;

for(int i = 0;i < numFds;i++){ jobject fdo = env->GetObjectArrayElement(fdArray, i);if(fdo){ handle->data[offset++] = env->GetIntField(fdo, fieldOffset);} else { handle->data[offset++] =-1;} } if(numInts > 0){ jint* ints = env->GetIntArrayElements(intArray, 0);for(int i = 0;i < numInts;i++){ handle->data[offset++] = ints[i];} env->ReleaseIntArrayElements(intArray, ints, 0);}

// doesn't take ownership of the native handle return sSensorDevice->data_open(sSensorDevice, handle);} 這函數最終調用了HAL層的data_open(),之后run()函數就進入一個while循環了。while(true){ // wait for an event final int sensor = sensors_data_poll(values, status, timestamp);

int accuracy = status[0];synchronized(sListeners){ if(sensor ==-1 || sListeners.isEmpty()){ if(sensor ==-1){ // we lost the connection to the event stream.this happens // when the last listener is removed.Log.d(TAG, “_sensors_data_poll()failed, we bail out.”);}

// we have no more listeners or polling failed, terminate the thread sensors_data_close();mThread = null;break;} final Sensor sensorObject = sHandleToSensor.get(sensor);if(sensorObject!= null){ // report the sensor event to all listeners that // care about it.final int size = sListeners.size();for(int i=0;i ListenerDelegate listener = sListeners.get(i);if(listener.hasSensor(sensorObject)){ // this is asynchronous(okay to call // with sListeners lock held).listener.onSensorChangedLocked(sensorObject, values, timestamp, accuracy);} } } } 它調用了jni函數sensors_data_poll()一直讀數據。static jint sensors_data_poll(JNIEnv *env, jclass clazz, jfloatArray values, jintArray status, jlongArray timestamp){ sensors_data_t data;int res = sSensorDevice->poll(sSensorDevice, &data);if(res >= 0){ jint accuracy = data.vector.status;env->SetFloatArrayRegion(values, 0, 3, data.vector.v);env->SetIntArrayRegion(status, 0, 1, &accuracy);env->SetLongArrayRegion(timestamp, 0, 1, &data.time);}

return res;} 把傳感器得到的值都放在value數組中,根據返回的傳感器標志sensor,把它分派給在sListener列表中所有的listener,如果listener中有監聽這個sensor,就把它分派給這個listener,此時就會引起onSensorChange()了。

好了,獲取傳感器數據主要是這樣一個途徑。最后我們去分析一下unregisterListener()函數。

private void unregisterListener(Object listener){ if(listener == null){ return;} try { synchronized(sListeners){ final int size = sListeners.size();for(int i=0;i ListenerDelegate l = sListeners.get(i);if(l.getListener()== listener){ // disable all sensors for this listener for(Sensor sensor : l.getSensors()){ String name = sensor.getName();int handle = sensor.getHandle();mSensorService.enableSensor(l, name, handle, SENSOR_DISABLE);} sListeners.remove(i);break;} } } } catch(RemoteException e){ Log.e(TAG, “RemoteException in unregisterListener: ”, e);} } 不用想這個函數會做一些與registerListener相反的事情,至少差不多。它先在sListeners列表中找到這個listener,然后先調用enableSensor()函數禁止這個傳感器。我們跟蹤一下這函數,在SensorService類中。synchronized(mListeners){ if(enable!=SENSOR_DISABLE &&!_sensors_control_activate(sensor, true)){ Log.w(TAG, “could not enable sensor ” + sensor);return false;}

Listener l = null;int minDelay = enable;for(Listener listener : mListeners){ if(binder == listener.mToken){ l = listener;} if(minDelay > listener.mDelay)minDelay = listener.mDelay;}

if(l == null && enable!=SENSOR_DISABLE){ l = new Listener(binder);binder.linkToDeath(l, 0);mListeners.add(l);mListeners.notify();}

if(l == null){ // by construction, this means we're disabling a listener we // don't know about...Log.w(TAG, “listener with binder ” + binder + “, doesn't exist(sensor=” + name + “, id=” + sensor + “)”);return false;}

if(minDelay >= 0){ _sensors_control_set_delay(minDelay);}

if(enable!= SENSOR_DISABLE){ l.addSensor(sensor, enable);} else { l.removeSensor(sensor);deactivateIfUnusedLocked(sensor);if(l.mSensors == 0){ mListeners.remove(l);binder.unlinkToDeath(l, 0);mListeners.notify();} }

if(mListeners.size()== 0){ _sensors_control_wake();_sensors_control_close();} } return true;你們看到它的實現了吧。如果enable是true的話,就調用_sensors_control_activate(),如果是false的話,就調用deactivateIfUnusedLocked(),它們最終都會調用 HAL層的active()函數。最后,如果是禁止傳感器的話,如果mListeners為空了,它就會調用 _sensors_control_wake();_sensors_control_close();這兩個jni函數,最終會調用HAL層的wake()和close_data_source()函數。當調用wake()函數時,會使SensorManager類線程的run()函數中的sensor_data_poll()函數立即返回,此時在run()函數中調用sensors_data_close();最終會調用HAL層的data_close()函數。至此,一個傳感器從初始到結束的流程就分析完了。

所以在java使用一個傳感器在HAL層具體調用的函數流程為: 首先,sensors_control_open(),只在系統初始化時調用一次。用來初始化control_device結構體。

以下的是每次使用傳感器一般經過的流程,注意,是一般而已,有些并不執行(1)sensors_data_open(2)get_sensors_list(3)activate(4)set_delay(5)open_data_source(6)data_open(7)poll 一直讀數據。。。。。。退出時(8)activate(9)sensors_control_close(10)data_close

當然其它的細節你們可以繼續去研究。也可以在我博客里提出來大家交流和討論一下!發表于 @ 2010年04月15日 09:25:00 | 評論(15 AddFeedbackCountStack(“5487476”))| 編輯| 舉報| 收藏

var CurrentEntryId = '5487476';var CurArticleTitle = '閱讀android有關sensor的源碼總結';var AllowComment = 'True';var AllowAnonymousComment = /^true$/i.test('False');匿名用戶 發表于Saturday, April 24, 2010 4:10:24 PM IP:舉報回復刪除挺好的,可是我有一點疑問呢?匿名用戶 發表于Wednesday, May 05, 2010 10:44:44 AM IP:舉報回復刪除代碼中怎么沒有看到hal stub的東西啊?我想知道open等操作的具體實現(非kenne層)匿名用戶 發表于Thursday, May 06, 2010 11:42:40 PM IP:舉報回復刪除回復 匿名用戶: check sensors_device_open()in sensor.c 匿名用戶 發表于Friday, May 07, 2010 12:12:08 AM IP:舉報回復刪除我看了詳細代碼,講得很好。流程大概就是這樣了。估計你沒有hal層代碼,因為那是芯片廠商提供或者自己寫的。很難寫。匿名用戶 發表于Saturday, May 08, 2010 12:04:55 AM IP:舉報回復刪除Hal usually has folling functions: 1.Sampling Device manager notifies sensor drivers via ioctl to refresh sensor data.Sensor drivers usually utialize i2c bus API functions(i.e.i2c_transfer())to fetch data.2.Reporting After sampling, sensor device drivers report sensor data through input device via input device API functions(i.e.input_report_xxx()and input_sync())3.in sensor_xxx.c or sensor_xxx.cpp, dev->device.poll = sensors_data_poll;sensors_data_poll()is a static function to pick sensor, poll and read sensor data.In Platform: 1.in android_hardware_SensorManager.cpp jni function sensors_data_poll()is provided for SensorManager.java to poll sensor data.sensors_data_poll()actually calls sensors_data_poll()in sensor_xxx.c /sensor_xxx.cpp.2.In SensorManager.java.registerListener()would call sSensorThread.startLocked().sSensorThread.startLocked()would create a new thread based on SensorThreadRunnable()that calls sensors_data_poll().3.In SensorThreadRunnable()listener.onSensorChangedLocked()is called to notify the Sensor event listener after polling sensor data.tigerhily 發表于Thursday, June 03, 2010 10:08:06 PM IP:舉報回復刪除jerry: 講得真好!頂一個。請問你有HAL的具體實現嗎?我想參考一下。或者講講sensors_data_open(3)activate(4)set_delay(5)open_data_source(6)data_open(7)poll 這些接口的具體實現!謝謝匿名用戶 發表于Saturday, June 05, 2010 12:15:03 AM IP:舉報回復刪除Tigerhily: 1.poll()is usually via input_event.Please get poll()reference from EventHup.cpp is you do not have sensor_xxx.c or sensor_xxx.cpp.input_event is device independent abstraction layer provided by the kernel.2.set_delay()starts from SensorManager.java, it calls native delay function in snesor_xxx.c or sensor_xxx.cpp.sensor_xxx.c or sensor_xxx.cpp calls ioctl to set delay value to sendor device driver.sensor device driver usually creates a miscdevice to accept ioctl command.3.Sensor device driver utilizes delay to adjust sampling rate and retrieves data via i2c bus and saves the data via input_event to let application pull sensor data.tigerhily 發表于Sunday, June 06, 2010 8:48:21 PM IP:舉報回復刪除回復 匿名用戶:hi jerry:Thanks for your help.Actually I don't have sensro_xxx.c and i am going to implement it.I will try and consult if needed.Thanks.lz_fine 發表于Tuesday, August 03, 2010 2:08:17 PM IP:舉報回復刪除你好,我現在也在做這塊,但是我遇到一個問題,我在HAL層的sensor.c中control__activate()函數中打開設備文件/dev /sensor成功,并且能執行ioctl操作,但是到了data__poll()函數中再執行ioctl就失敗了,報告的錯誤是Bad file number,errno是EBADF,看起來好像是這個fd被關閉了,這個怎么也想不通,因為看起來SensorThread還在跑,而且在 sensor.c中也沒有執行close操作,這種情況有沒有遇到過啊,能解釋一下嗎,感激不盡lz_fine 發表于Wednesday, August 04, 2010 3:55:43 PM IP:舉報回復刪除找到ioctl失敗的原因了,是在SensorManager.java中關閉fd的,不過正常情況下sensor.c中應該先復制一個fd,因此加上一句復制fd的語句就可以了,終于搞定了,內牛滿面啊iceskyang 發表于Thursday, August 05, 2010 11:02:16 AM IP:舉報回復刪除問一下,如果加入后臺進程用來輔助計算加速度磁場的值,那么這個進程為什么會在一開機后就運行的。我在int.rc中明明設置了disabled。

第四篇:Android4.0編譯錯誤記錄

1.make: ***

[out/host/linux-x86/obj/STATIC_LIBRARIES/libMesa_intermediates/src/glsl/linker.o] Error 1 解決方法: vim external/mesa3d/src/glsl/linker.cpp

添加:

#include

2.make: ***

[out/host/linux-x86/obj/EXECUTABLES/test-librsloader_intermediates/test-librsloader] Error 1 解決辦法:

vim external/llvm/llvm-host-build.mk

添加:

LOCAL_LDLIBS :=-lpthread-ldl

3.make: ***

[out/host/linux-x86/obj/STATIC_LIBRARIES/libgtest_host_intermediates/gtest-all.o] Error 1 解決方法:

vim external/gtest/include/gtest/internal/gtest-param-util.h

添加:

#include

4.

第五篇:32位Ubuntu 11.10下android2.3.7源碼下載與編譯小結

32位Ubuntu 11.10下android2.3.7源碼下載與編譯小結

1、我是在vmware下安裝ubuntu 11.10的,這個網上資料很多,不多說了。我給ubuntu分了25g硬盤和1g內存。

2、請參照http://source.android.com/source。初始化編譯環境 檢查一下包是否安裝: Python 2.4-2.7 Git 1.5.4 或更高版本

沒有話可以sudo apt-get install..安裝一下

JDK 6 因為是編譯android2.3以上,如果編譯2.2以下需要JDK5 安裝JDK6:

$ sudo add-apt-repository“deb http://archive.canonical.com/ lucid partner” $ sudo apt-get update $ sudo apt-get install sun-java6-jdk 如果下載速度不行,可以先把ubuntu的更新源改成網易的源,可參考:http://bolg.malu.me/html/2010/279.html。其他需要安裝的包:

我安裝了如下包:官網上那是64位需要安裝的包,我是32位的有些不一樣。

$ sudo apt-get install git-core gnupg flex bison gperf libsdl1.2-dev libesd0-dev libwxgtk2.6-dev build-essential zip curl libncurses5-dev zlib1g-dev x11proto-core-dev libx11-dev libgl1-mesa-dev g++-multilib mingw32 tofrodos python-markdown libxml2-utils

3、下面開始下載源碼

首先安裝repo(是一個便于git管理的工具)$ mkdir~/bin $ PATH=~/bin:$PATH $ curl https://dl-ssl.google.com/dl/googlesource/git-repo/repo > ~/bin/repo $ chmod a+x~/bin/repo 初始化repo client $ mkdir android2.3.7 $ cd android2.3.7 初始化repo,我是使用的下面的地址,使用官網地址時出現了網絡錯誤

$ repo init-u http://android.googlesource.com/platform/manifest.git-b android-2.3.7_r1

按照提示輸入用戶名和郵箱。接著 $ repo sync 開始同步源碼,根據你的網速,我的持續了50分鐘左右。

還有一步驗證git tags可參照官網。下完后就可以在剛才創建的android2.3.7文件夾下看見已下載的源碼。

4、開始編譯 初始化:

$ source build/envsetup.sh $ lunch full-eng 上面代表編譯的一個target,full是針對emulator編譯全部包括app、輸入法等,eng是指針對開發者編譯,有最高權限。具體可參見官網。

接著就可以編譯了,在源碼目錄下直接make就行,需要一段時間。編譯過程中有幾個問題需要指出一下: 問題1:

由于我們是32位系統,所以有些文件需要修改一下:將./external/clearsilver/cgi/Android.mk./external/clearsilver/java-jni/Android.mk./external/clearsilver/util/Android.mk./external/clearsilver/cs/Android.mk 四個文件中的

LOCAL_CFLAGS+=-m64 LOCAL_LDFLAGS+=-m64

注釋掉,或者將“64”換成“32”

LOCAL_CFLAGS+=-m32 LOCAL_LDFLAGS+=-m32

然后,將./build/core/main.mk 中的

ifneq(64,$(findstring64,$(build_arch)))

改為:

ifneq(i686,$(findstring i686,$(build_arch)))

問題2:

frameworks/base/libs/utils/RefBase.cpp:483:67: android::RefBase::weakref_impl?

as

?this?

error:

passing

of

?const ?void

argument android::RefBase::weakref_impl::trackMe(bool, bool)? discards qualifiers [-fpermissive] make: *** [out/host/linux-x86/obj/STATIC_LIBRARIES/libutils_intermediates/RefBase.o] error 1 如下解決:

$ gedit frameworks/base/libs/utils/Android.mk 將下面一行

LOCAL_CFLAGS+=-DLIBUTILS_NATIVE=1 $(TOOL_CFLAGS)改成

LOCAL_CFLAGS+=-DLIBUTILS_NATIVE=1 $(TOOL_CFLAGS)–fpermissive 問題3:

:0:0: warning: “_FORTIFY_SOURCE” redefined [enabled by default]

:0:0: note: this is the location of the previous definition cc1plus: all warnings being treated as errors make: *** [out/host/linux-x86/obj/EXECUTABLES/obbtool_intermediates/Main.o] Error 1 這是由于11.10的gcc

版本過高造成的,可參考這篇文章修改:http://hi.baidu.com/designhouse/blog/item/fec5cdbf8d6a231618d81fc1.html。至此編譯完畢。

make編譯的并不是所有內容,不包含內核和SDK。映像生成在out/target/product/generic

下:android

源碼編譯后得到system.img,ramdisk.img,userdata.img映像文件。其中,ramdisk.img是一個分區映像文件,在kernel啟動時,ramdisk被用來調用init,以及把真正的root file system mount起來。system.img包括了主要系統,系統app等,會被掛載到/下,可對應查看./system該目錄,可以發現在其下app/下有一些系統自帶的應用程序。userdata.img包括了一些用戶數據,被掛載到/data下,對應可查看./data/目錄,emulator加載這3個映像文件。

5、編譯SDK 編譯SDK可以得到與源碼同步的SDK,還會生成一些tools,在源碼根目錄下:

$ sudo make PRODUCT-sdk-sdk 編譯生成的SDK在out/host/linux-x86/SDK下。之后如果在ubuntu下使用eclipse進行開發,可以使用你編譯的SDK。

下面就在模擬器中運行鏡像,建議切到root用戶下,首先配置幾個環境變量,將自己編譯的SDK設為優先級最高,在源碼根目錄下執行:

$sudo update-alternatives

--install/usr/bin/AndroidSDK

AndroidSDK

/home/zhaolin/AndroidSource_GB/out/host/linux-x86/sdk/android-sdk_eng.root_linux-x86255 這樣會在/etc/alternatives下生成一個指向該SDK目錄的軟連接AndroidSDK,這個目錄主要存放一些系統默認打開的程序的信息和配置。那么/usr/bin/AndroidSDK就指向這個軟連接。接著執行:

gedit~/.bashrc 在文件末尾添加:

export ANDROID_SDK_HOME=/usr/bin/AndroidSDK export PATH=$ANDROID_SDK_HOME/tools:$PATH export ANDROID_PRODUCT_OUT=~/android2.3.7/out/target/product/generic 接著就可以執行:

$ emulator 運行的就是你編譯的映像。執行emulator 命令時,如果不帶任何參數,則Linux Kernel鏡像默認使用~/Android/prebuilt/android-arm/kernel目錄下的kernel-qemu文件,而

Android鏡像文件則默認使用ANDROID_PRODUCT_OUT目錄下的system.img、userdata.img和ramdisk.img。模擬器運行需要這四個文件,如果你編譯了內核則可以使用自己的Kernel鏡像,可用于android移植等。

6、單獨編譯模塊

如果你不想編譯整個系統,就想編譯某一個應用程序,可以使用mmm命令,使用之前,在源碼目錄下先要執行:

$ build/envsetup.sh

這樣會生成一些命令,有m即make、mm編譯當前目錄下所有模塊、mmm編譯指定目錄下所有模塊。你可以把packages/apps/Music應用的application name改成MyMusic(AndroidManifest.xml中),然后執行:

$ mmm packages/apps/Music 在out/target/product/generic/system/app中就可以看見Music.apk,然后執行:

$ make snod 重新生成system.img。

下載Ubuntu 11.10編譯Android源碼錯誤[范文大全]word格式文檔
下載Ubuntu 11.10編譯Android源碼錯誤[范文大全].doc
將本文檔下載到自己電腦,方便修改和收藏,請勿使用迅雷等下載。
點此處下載文檔

文檔為doc格式


聲明:本文內容由互聯網用戶自發貢獻自行上傳,本網站不擁有所有權,未作人工編輯處理,也不承擔相關法律責任。如果您發現有涉嫌版權的內容,歡迎發送郵件至:645879355@qq.com 進行舉報,并提供相關證據,工作人員會在5個工作日內聯系你,一經查實,本站將立刻刪除涉嫌侵權內容。

相關范文推薦

主站蜘蛛池模板: 少妇被黑人到高潮喷出白浆| 天堂√最新版中文在线地址| 亚洲欧美国产日产综合不卡| 无码专区—va亚洲v专区| 一本久久综合亚洲鲁鲁五月天| 免费国产在线精品一区二区三区| 亚洲人成人伊人成综合网无码| 精品含羞草免费视频观看| 亚洲动漫精品无码av天堂| 无码日韩av一区二区三区| 久久国产精品久久精品国产| 老妇高潮潮喷到猛进猛出| 熟女人妻aⅴ一区二区三区电影| 免费国产乱理伦片在线观看| 国产明星精品无码av换脸| 精品无人区卡卡二卡三乱码| 男女性高爱潮免费网站| 久久精品99国产精品日本| 口爆吞精一区二区久久| 亚洲伊人色综合www962| 大ji巴好深好爽又大又粗视频| 亚洲精品黑牛一区二区三区| 日本做受高潮好舒服视频| 亚洲av永久无码精品漫画| 亚洲欧美自拍偷一区二区| 国产亚洲欧美日韩夜色凹凸成人| 国产超碰人人做人人爽av动图| 麻豆乱码国产一区二区三区| 国产成人a亚洲精v品无码| 亚洲午夜久久久影院| 51被公侵犯玩弄漂亮人妻| 成人无码精品1区2区3区免费看| 国产成人亚洲综合图区| 亚洲欧美成人综合久久久| 未发育成型小奶头毛片av| 秋霞成人午夜鲁丝一区二区三区| 人妻精品久久久久中文字幕69| gv天堂gv无码男同在线观看| 欧美性大战xxxxx久久久√| 一二区成人影院电影网| 极品少妇被猛得白浆直流草莓视频|