Ⅰ 如何用adroid studio 如何閱讀android源碼
在android源碼中有一個目錄idegen,是生成ide的project文件,主要是生成intellij的project文件,用source insight閱讀Android源碼,效果非常好。
過程:
效果圖;
導入到android studio,打開Android studio,點擊File > Open,選擇剛剛生成的android.ipr就好了;
備註:
可以結合android studio,界面,智能提示都比source insight要好。
Ⅱ 如何高效閱讀android反編譯後的源碼
一、工具准備:apktool , dex2jar , jd-gui
二、使用dex2jar + jd-gui 得到apk的java源碼
1.用解壓工具從 apk包中取出 classes.dex 文件
用命令(dex2jar.bat classes.dex)得到一個 jar文件
2.用jd-gui反編譯工具將得到.jar文件反編譯成.java文件
三、使用apktool得到apk的xml文件
用命令(apktool d xxx.apk xxx_xml)反編譯xxx.apk包2.從 xxx_xml 文件夾得到xml文件四、第二步 得到的程序源代碼 和 第三步 得到的xml文件組合下,即可得到完整的apk源碼。
五、應用: 漢化/去廣告,加 values-zh-rCN, values-zh-rTW, values-de, values-fr
1.在步驟三的文件夾xxx_xml/res/ 下, 建文件夾: values-zh-rCN,values-zh-rTW
2.1復制valuesstrings.xml 到 values-zh-rCN 並翻譯.
2.2 去廣告見;
3.重建APK,用命令(apktool b xxx) ,輸出到ABC/dist/out.apk
或命令( apktool b xxx out.apk)
詳細代碼
Ⅲ 如何閱讀android framework源碼
首先看MediaRecorder.java內的setVideoEncoder方法:
/**
* Sets the video encoder to be used for recording. If this method is not
* called, the output file will not contain an video track. Call this after
* setOutputFormat() and before prepare().
*
* @param video_encoder the video encoder to use.
* @throws IllegalStateException if it is called before
* setOutputFormat() or after prepare()
* @see android.media.MediaRecorder.VideoEncoder
*/
public native void setVideoEncoder(int video_encoder)
throws IllegalStateException;123456789101112
這是一個native方法,根據JNI的規則,我們應該去android_media_MediaRecorder.cpp里看這個方法的實現:
static void
android_media_MediaRecorder_setVideoEncoder(JNIEnv *env, jobject thiz, jint ve)
{
ALOGV("setVideoEncoder(%d)", ve);
if (ve < VIDEO_ENCODER_DEFAULT || ve >= VIDEO_ENCODER_LIST_END) {
jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid video encoder");
return;
}
sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
process_media_recorder_call(env, mr->setVideoEncoder(ve), "java/lang/RuntimeException", "setVideoEncoder failed.");
}1234567891011
關鍵是最後的兩句,sp是Android 里的一個指針,就當沒看見~ 所以最後兩句的意思是調用Native層的MediaRecorder的setVideoEncoder方法。
繼續去MediaRecorder.cpp里看setVideoEncoder方法:
status_t MediaRecorder::setVideoEncoder(int ve)
{
ALOGV("setVideoEncoder(%d)", ve);
if (mMediaRecorder == NULL) {
ALOGE("media recorder is not initialized yet");
return INVALID_OPERATION;
}
if (!mIsVideoSourceSet) {
ALOGE("try to set the video encoder without setting the video source first");
return INVALID_OPERATION;
}
if (mIsVideoEncoderSet) {
ALOGE("video encoder has already been set");
return INVALID_OPERATION;
}
if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
ALOGE("setVideoEncoder called in an invalid state(%d)", mCurrentState);
return INVALID_OPERATION;
}
status_t ret = mMediaRecorder->setVideoEncoder(ve);
if (OK != ret) {
ALOGV("setVideoEncoder failed: %d", ret);
mCurrentState = MEDIA_RECORDER_ERROR;
return ret;
}
mIsVideoEncoderSet = true;
return ret;
}
這里的mMediaReocorder定義在MediaRecorder.h里:
sp<IMediaRecorder> mMediaRecorder;1
可見其是一個IMediaRecorder類型的變數,這是一個介面類型,看一下其介面定義,在IMediaRecorder.h中:
class IMediaRecorder: public IInterface
{
public:
DECLARE_META_INTERFACE(MediaRecorder);
virtual status_t setCamera(const sp<hardware::ICamera>& camera,
const sp<ICameraRecordingProxy>& proxy) = 0;
virtual status_t setPreviewSurface(const sp<IGraphicBufferProcer>& surface) = 0;
virtual status_t setVideoSource(int vs) = 0;
virtual status_t setAudioSource(int as) = 0;
virtual status_t setOutputFormat(int of) = 0;
virtual status_t setVideoEncoder(int ve) = 0;
virtual status_t setAudioEncoder(int ae) = 0;
virtual status_t setOutputFile(int fd, int64_t offset, int64_t length) = 0;
virtual status_t setVideoSize(int width, int height) = 0;
virtual status_t setVideoFrameRate(int frames_per_second) = 0;
virtual status_t setParameters(const String8& params) = 0;
virtual status_t setListener(const sp<IMediaRecorderClient>& listener) = 0;
virtual status_t setClientName(const String16& clientName) = 0;
virtual status_t prepare() = 0;
virtual status_t getMaxAmplitude(int* max) = 0;
virtual status_t start() = 0;
virtual status_t stop() = 0;
virtual status_t reset() = 0;
virtual status_t pause() = 0;
virtual status_t resume() = 0;
virtual status_t init() = 0;
virtual status_t close() = 0;
virtual status_t release() = 0;
virtual status_t setInputSurface(const sp<IGraphicBufferConsumer>& surface) = 0;
virtual sp<IGraphicBufferProcer> querySurfaceMediaSource() = 0;
};
// ----------------------------------------------------------------------------
class BnMediaRecorder: public BnInterface<IMediaRecorder>
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};3031323334353637383940414243
吶~關鍵的步驟來了,在以前我基本就追到這,就算完蛋了,不知道怎麼繼續往下追了,後來看Binder相關的內容,知道了BnInterface的作用,這是Binder中關鍵的一環,我們這就不展開講了,只要記得,接下來我們要追的是BnMediaRecorder這個類。
全局搜索一下「: public BnMediaRecorder」,也就是去找它的實現類,發現在MediaRecorderClient.h當中有如下的定義:
class MediaRecorderClient : public BnMediaRecorder
{
class ServiceDeathNotifier: public IBinder::DeathRecipient
{
public:
ServiceDeathNotifier(
const sp<IBinder>& service,
const sp<IMediaRecorderClient>& listener,
int which);
virtual ~ServiceDeathNotifier();
virtual void binderDied(const wp<IBinder>& who);
private:
int mWhich;
sp<IBinder> mService;
wp<IMediaRecorderClient> mListener;
};
public:
virtual status_t setCamera(const sp<hardware::ICamera>& camera,
const sp<ICameraRecordingProxy>& proxy);
virtual status_t setPreviewSurface(const sp<IGraphicBufferProcer>& surface);
virtual status_t setVideoSource(int vs);
virtual status_t setAudioSource(int as);
virtual status_t setOutputFormat(int of);
virtual status_t setVideoEncoder(int ve);
virtual status_t setAudioEncoder(int ae);
virtual status_t setOutputFile(int fd, int64_t offset,
int64_t length);
virtual status_t setVideoSize(int width, int height);
virtual status_t setVideoFrameRate(int frames_per_second);
virtual status_t setParameters(const String8& params);
virtual status_t setListener(
const sp<IMediaRecorderClient>& listener);
virtual status_t setClientName(const String16& clientName);
virtual status_t prepare();
virtual status_t getMaxAmplitude(int* max);
virtual status_t start();
virtual status_t stop();
virtual status_t reset();
virtual status_t pause();
virtual status_t resume();
virtual status_t init();
virtual status_t close();
virtual status_t release();
virtual status_t mp(int fd, const Vector<String16>& args);
virtual status_t setInputSurface(const sp<IGraphicBufferConsumer>& surface);
virtual sp<IGraphicBufferProcer> querySurfaceMediaSource();
private:
friend class MediaPlayerService; // for accessing private constructor
MediaRecorderClient(
const sp<MediaPlayerService>& service,
pid_t pid,
const String16& opPackageName);
virtual ~MediaRecorderClient();
sp<IBinder::DeathRecipient> mCameraDeathListener;
sp<IBinder::DeathRecipient> mCodecDeathListener;
pid_t mPid;
Mutex mLock;
MediaRecorderBase *mRecorder;
sp<MediaPlayerService> mMediaPlayerService;
};303132333435363738394
那麼我們去MediaRecorderClient.cpp里看看:
status_t MediaRecorderClient::setVideoEncoder(int ve)
{
ALOGV("setVideoEncoder(%d)", ve);
Mutex::Autolock lock(mLock);
if (mRecorder == NULL) {
ALOGE("recorder is not initialized");
return NO_INIT;
}
return mRecorder->setVideoEncoder((video_encoder)ve);
}12345678910
這里的mRecorder 定義在MediaRecorderClient.h當中:
MediaRecorderBase *mRecorder;1
來,我們繼續搜索「: public MediaRecorderBase」,在StagefrightRecorder.h中找到了,那麼我們去StagefrightRecorder.cpp當中看看~
status_t StagefrightRecorder::setVideoEncoder(video_encoder ve) {
ALOGV("setVideoEncoder: %d", ve);
if (ve < VIDEO_ENCODER_DEFAULT ||
ve >= VIDEO_ENCODER_LIST_END) {
ALOGE("Invalid video encoder: %d", ve);
return BAD_VALUE;
}
mVideoEncoder = ve;
return OK;
}123456789101112
吶,這就算完了~最後我們會發現MediaRecorder中的介面實現基本到最後都會落在這個StagefrightRecorder.cpp當中。
Ⅳ 大牛們是怎麼閱讀 Android 系統源碼的
如果只是想看看一些常用類的實現, 在Android包管理器里把源碼下載下來, 隨便一個IDE配好Source Code的path看就行.
但如果想深入的了解Android系統, 那麼可以看下我的一些簡單的總結.
知識
Java
Java是AOSP的主要語言之一. 沒得說, 必需熟練掌握.
熟練的Android App開發
Linux
Android基於Linux的, 並且AOSP的推薦編譯環境是Ubuntu 12.04. 所以熟練的使用並了解Linux這個系統是必不可少的. 如果你想了解偏底層的代碼, 那麼必需了解基本的Linux環境下的程序開發. 如果再深入到驅動層, 那麼Kernel相關的知識也要具備.
Make
AOSP使用Make系統進行編譯. 了解基本的Makefile編寫會讓你更清晰了解AOSP這個龐大的項目是如何構建起來的.
Git
AOSP使用git+repo進行源碼管理. 這應該是程序員必備技能吧.
C++
Android系統的一些性能敏感模塊及第三方庫是用C++實現的, 比如: Input系統, Chromium項目(WebView的底層實現).
硬體
流暢的國際網路
AOSP代碼下載需要你擁有一個流暢的國際網路. 如果在下載代碼這一步就失去耐心的話, 那你肯定沒有耐心去看那亂糟糟的AOSP代碼. 另外, 好程序員應該都會需要一個流暢的Google.
一台運行Ubuntu 12.04的PC.
如果只是閱讀源碼而不做太多修改的話, 其實不需要太高的配置.
一台Nexus設備
AOSP項目默認只支持Nexus系列設備. 沒有也沒關系, 你依然可以讀代碼. 但如果你想在大牛之路走的更遠, 還是改改代碼, 然後刷機調試看看吧.
高品質USB線
要刷機時線壞了, 沒有更窩心的事兒了.
軟體
Ubuntu 12.04
官方推薦, 沒得選.
Oracle Java 1.6
注意不要用OpenJDK. 這是個坑, 官方文檔雖然有寫, 但還是單獨提一下.
安裝:
sudo apt-get install python-software-properties
sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update
sudo apt-get install oracle-java6-installer
sudo apt-get install oracle-java6-set-default
Eclipse
估計會有不少人吐槽, 為什麼要用這個老古董. 其實原因很簡單, 合適. 剛開始搞AOSP時, 為了找到效率最優的工具, 我嘗試過Eclipse, IntelliJ IDEA, Vim+Ctags, Sublime Text+Ctags. 最終結果還是Eclipse. 主要優點有:
有語法分析 (快速准確的類, 方法跳轉).
支持C++ (IntelliJ的C++支持做的太慢了).
嵌入了DDMS, View Hierarchy等調試工具.
為了提高效率, 花5分鍾背下常用快捷鍵非常非常值得.
調整好你的classpath, 不要導入無用的代碼. 因為AOSP項目代碼實在是太多了. 當你還不需要看C++代碼時, 不要為項目添加C++支持, 建索引過程會讓你崩潰.
Intellij IDEA
開發App必備. 當你要調試系統的某個功能是, 常常需要迅速寫出一個調試用App, 這個時候老舊的Eclipse就不好用了. Itellij IDEA的xml自動補全非常給力.
巨人的肩膀
這個一定要先讀. 項目介紹, 代碼下載, 環境搭建, 刷機方法, Eclipse配置都在這里. 這是一切的基礎.
這個其實是給App開發者看的. 但是裡面也有不少關於系統機制的介紹, 值得細讀.
此老羅非彼老羅. 羅升陽老師的博客非常有營養, 基本可以作為指引你開始閱讀AOSP源碼的教程. 你可以按照博客的時間順序一篇篇挑需要的看.但這個系列的博客有些問題:
早期的博客是基於舊版本的Android;
大量的代碼流程追蹤. 讀文章時你一定要清楚你在看的東西在整個系統處於什麼樣的位置.
鄧凡平老師也是為Android大牛, 博客同樣很有營養. 但是不像羅升陽老師的那麼系統. 更多的是一些技術點的深入探討.
Android官方Issue列表. 我在開發過程中發現過一些奇怪的bug, 最後發現這里基本都有記錄. 當然你可以提一些新的, 有沒有人改就是另外一回事了.
一定要能流暢的使用這個工具. 大量的相關知識是沒有人系統的總結的, 你需要自己搞定.
其它
代碼組織
AOSP的編譯單元不是和git項目一一對應的, 而是和Android.mk文件一一對應的. 善用mmm命令進行模塊編譯將節省你大量的時間.
Binder
這是Android最基礎的進程間通訊. 在Application和System services之間大量使用. 你不僅要知道AIDL如何使用, 也要知道如何手寫Binder介面. 這對你理解Android的Application和System services如何交互有非常重要的作用. Binder如何實現的倒不必著急看.
HAL
除非你對硬體特別感興趣或者想去方案公司上班, 否則別花太多時間在這一層.
CyanogenMod
這是一個基於AOSP的第三方Rom. 從這個項目的wiki里你能學到很多AOSP官方沒有告訴你的東西. 比如如何支持Nexus以外的設備.
DIA
這是一個Linux下畫UML的工具, 能夠幫你梳理看過的代碼.
XDA
Ⅳ 如何閱讀Android系統源碼
Android源碼兩個部分看得最多,一個是packages,就是各個系統應用的實現,另外就是framework,框架層的實現。 具體看什麼就看你想了解什麼。 工具eclipse也很好,build一下生成class path,各種轉跳非常方便,不需要grep了。