======================= 第一节 ===========================
这里简单的介绍了Android的java环境基础,在后面一节中会结合具体的实例来理解这一节的内容。
一、Dalvik虚拟机
Dalvik是Android的程序的java虚拟机,代码在dalvik/下,
./
|-- Android.mk
|-- CleanSpec.mk
|-- MODULE_LICENSE_APACHE2
|-- NOTICE
二、Android的java框架
Android层次中第3层是java框架,第四层就是java应用程序。
Android的java类代码,主要是在frameworks/base/core/java/下,
./
|-- Android
|-- com
|-- jarjar-rules.txt
`-- overview.html
我们再看一下frameworks/base/目录
./
|-- Android.mk
|-- CleanSpec.mk
|-- MODULE_LICENSE_APACHE2
|-- NOTICE
|-- api
|-- awt
|-- build
|-- camera
|-- cmds
|-- common
|-- core
|-- data
|-- docs
|-- graphics
|-- include
|-- keystore
|-- libs
|-- location
|-- media
|-- native
|-- obex
|-- opengl
|-- packages
|-- preloaded-classes
|-- sax
|-- services
|-- telephony
|-- test-runner
|-- tests
|-- tools
|-- vpn
`-- wifi
这里也有Android的java框架代码。
三、JNI
在Android中,通过JNI,java可以调用C写的代码,主要的实现是在frameworks/base/core/jni,通过查看Android.mk,我们可以看到最后生成了libandroid_runtime.so,具体实现JNI功能需要上面我们介绍的libnativehelper.so,
四、系统服务之java
1、binder,提供Android的IPC功能
2、servicemanager,服务管理的服务器端
3、系统进程zygote,负责孵化所有的新应用
======================= 第二节 ==========================
在我平时工作中主要是进行linux网络子系统的模块开发、linux应用程序(C/C++)开发。在学习和从事驱动模块开发的过程中,如果你对linux系统本身,包括应用程序开发都不了解,那么读内核代码就如同天书,毫无意义,所以我分析框架也是从基本系统api开始的,当然也不会太多涉及到应用程序开发。
好,开始这节主要是讲一个简单的adnroid应用程序,从应用程序出发,到框架代码。
分析的应用程序我们也奉行拿来主义:froyo/development/samples/HelloActivity
./
|-- Android.mk
|-- AndroidManifest.xml
|-- res
|-- src
`-- tests
其他的就多说了,看代码
[size=1em]1 [size=1em]2 [size=1em]3 [size=1em]4 [size=1em]5 [size=1em]6 [size=1em]7 [size=1em]8 [size=1em]9 [size=1em]10 [size=1em]11 [size=1em]12 [size=1em]13 [size=1em]14 [size=1em]15 [size=1em]16 [size=1em]17 [size=1em]18 [size=1em]19 [size=1em]20 [size=1em]21 [size=1em]22 [size=1em]23 [size=1em]24 [size=1em]25 [size=1em]26 [size=1em]27 [size=1em]28 [size=1em]29 [size=1em]30 [size=1em]31 [size=1em]32 [size=1em]33 [size=1em]34 [size=1em]35 | [size=1em][size=1em]/* [size=1em] * Copyright (C) 2007 The Android Open Source Project [size=1em] * [size=1em] * Licensed under the Apache License, Version 2.0 (the "License"); [size=1em] * you may not use this file except in compliance with the License. [size=1em] * You may obtain a copy of the License at [size=1em] * [size=1em] * http://www.apache.org/licenses/LICENSE-2.0 [size=1em] * [size=1em] * Unless required by applicable law or agreed to in writing, software [size=1em] * distributed under the License is distributed on an "AS IS" BASIS, [size=1em] * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. [size=1em] * See the License for the specific language governing permissions and [size=1em] * limitations under the License. [size=1em] */ [size=1em]package com.example.Android.helloactivity; [size=1em]import Android.app.Activity; [size=1em]import Android.os.Bundle; [size=1em]/** [size=1em] * A minimal "Hello, World!" application. [size=1em] */ [size=1em]public class HelloActivity extends Activity { [size=1em] public HelloActivity() { [size=1em] } [size=1em] /** [size=1em] * Called with the activity is first created. [size=1em] */ [size=1em] @Override [size=1em] public void onCreate(Bundle savedInstanceState) { [size=1em] super.onCreate(savedInstanceState); [size=1em] // Set the layout for this activity. You can find it [size=1em] // in res/layout/hello_activity.xml [size=1em] setContentView(R.layout.hello_activity); [size=1em] } [size=1em]} |
每一个写过Android程序的人都应该是从这个代码起步的吧?那好,那么我们研究android框架也从这里启航。
首先是
[size=1em]1 [size=1em]2 | [size=1em][size=1em]import Android.app.Activity; [size=1em]import Android.os.Bundle; |
记住,我们这里不是讲JAVA,我们要讲的是Android.app.Activity,回顾上节的内容,android的JAVA框架代码放在froyo/frameworks/base/,
其中Activity的代码放在框架代码的core/java/Android/app/Activity.java,大概看一下
[size=1em][backcolor=rgb(108, 226, 108) !important][size=1em]1 [size=1em]2 [size=1em]3 [size=1em]4 [size=1em]5 [size=1em]6 [size=1em]7 [size=1em]8 [size=1em]9 [size=1em]10 [size=1em]11 [size=1em]12 | [size=1em][size=1em]public class Activity extends ContextThemeWrapper [size=1em] implements LayoutInflater.Factory, [size=1em] Window.Callback, KeyEvent.Callback, [size=1em] OnCreateContextMenuListener, ComponentCallbacks { [size=1em] private static final String TAG = "Activity"; [size=1em] /** Standard activity result: operation canceled. */ [size=1em] public static final int RESULT_CANCELED = 0; [size=1em] /** Standard activity result: operation succeeded. */ [size=1em] public static final int RESULT_OK = -1; [size=1em] /** Start of user-defined activity results. */ [size=1em] public static final int RESULT_FIRST_USER = 1; [size=1em] private static long sInstanceCount = 0; |
同样的Bundle的代码core/java/Android/os/Bundle.java
[size=1em][backcolor=rgb(108, 226, 108) !important][size=1em]1 [size=1em]2 [size=1em]3 | [size=1em][size=1em]public final class Bundle implements Parcelable, Cloneable { [size=1em] private static final String LOG_TAG = "Bundle"; [size=1em] public static final Bundle EMPTY; |
呵呵,其实写多应用程序,然后看看这些代码,会有更加豁然开朗的感觉,所以列出以上目录给大家参考,所有的java框架代码都在那个目录下,到这里今天要讨论的第一个问题就到这里了。
我所在的公司是网络设备供应商,其实和Android本身不搭边,android只是平时的爱好而已,所以很多地方如果写错了敬请原谅,当然也计划去做做android系统开发,例如驱动或者是框架开发,这是后话。
======================== 第三节 ========================
上节讲到了JAVA框架代码和应用程序的关系,那么框架代码和驱动层是怎么联系的呢?这就是这一节的内容:JNI
java使用一种叫做jni的技术来支持对C/C++代码的调用,在anroid中jni的代码放在froyo/frameworks/base/core/jni下,当然在java框架代码的目录下还有其他地方也多多少少放了jni代码,大家可以打开源码来看看。
整体关系如下图:
| java应用程序
--------------------------------------- Android系统api
| java框架
|本地接口声明
--------------------------------------
| JNI
--------------------------------------
| C/C++代码
继续拿来主义,C/C++中调试用printf,内核调试用printk,呵呵,Android调试用log,那么我们就分析log的实现。
log的java代码froyo/frameworks/base/core/java/Android/util/Log.java,
[size=1em][backcolor=rgb(108, 226, 108) !important][size=1em]1 [size=1em]2 [size=1em]3 [size=1em]4 [size=1em]5 [size=1em]6 [size=1em]7 [size=1em]8 [size=1em]9 [size=1em]10 [size=1em]11 [size=1em]12 [size=1em]13 [size=1em]14 [size=1em]15 [size=1em]16 [size=1em]17 [size=1em]18 [size=1em]19 [size=1em]20 [size=1em]21 [size=1em]22 [size=1em]23 [size=1em]24 [size=1em]25 [size=1em]26 [size=1em]27 [size=1em]28 [size=1em]29 [size=1em]30 [size=1em]31 [size=1em]32 [size=1em]33 [size=1em]34 [size=1em]35 [size=1em]36 [size=1em]37 [size=1em]38 [size=1em]39 [size=1em]40 [size=1em]41 [size=1em]42 [size=1em]43 [size=1em]44 [size=1em]45 [size=1em]46 [size=1em]47 [size=1em]48 [size=1em]49 [size=1em]50 [size=1em]51 [size=1em]52 [size=1em]53 [size=1em]54 [size=1em]55 [size=1em]56 [size=1em]57 [size=1em]58 [size=1em]59 [size=1em]60 [size=1em]61 [size=1em]62 [size=1em]63 [size=1em]64 [size=1em]65 [size=1em]66 [size=1em]67 [size=1em]68 [size=1em]69 [size=1em]70 [size=1em]71 [size=1em]72 [size=1em]73 [size=1em]74 [size=1em]75 [size=1em]76 [size=1em]77 [size=1em]78 [size=1em]79 [size=1em]80 [size=1em]81 [size=1em]82 [size=1em]83 [size=1em]84 [size=1em]85 [size=1em]86 [size=1em]87 [size=1em]88 [size=1em]89 [size=1em]90 [size=1em]91 [size=1em]92 [size=1em]93 [size=1em]94 [size=1em]95 [size=1em]96 [size=1em]97 [size=1em]98 [size=1em]99 [size=1em]100 [size=1em]101 [size=1em]102 [size=1em]103 [size=1em]104 [size=1em]105 [size=1em]106 [size=1em]107 [size=1em]108 [size=1em]109 [size=1em]110 [size=1em]111 [size=1em]112 [size=1em]113 [size=1em]114 [size=1em]115 [size=1em]116 [size=1em]117 [size=1em]118 [size=1em]119 [size=1em]120 [size=1em]121 [size=1em]122 [size=1em]123 [size=1em]124 [size=1em]125 [size=1em]126 [size=1em]127 [size=1em]128 [size=1em]129 [size=1em]130 [size=1em]131 [size=1em]132 [size=1em]133 [size=1em]134 [size=1em]135 [size=1em]136 [size=1em]137 [size=1em]138 [size=1em]139 [size=1em]140 [size=1em]141 [size=1em]142 [size=1em]143 [size=1em]144 [size=1em]145 [size=1em]146 [size=1em]147 [size=1em]148 [size=1em]149 [size=1em]150 [size=1em]151 [size=1em]152 [size=1em]153 [size=1em]154 [size=1em]155 [size=1em]156 [size=1em]157 [size=1em]158 [size=1em]159 [size=1em]160 [size=1em]161 [size=1em]162 [size=1em]163 [size=1em]164 [size=1em]165 [size=1em]166 [size=1em]167 [size=1em]168 [size=1em]169 [size=1em]170 [size=1em]171 [size=1em]172 [size=1em]173 [size=1em]174 [size=1em]175 [size=1em]176 [size=1em]177 [size=1em]178 [size=1em]179 [size=1em]180 [size=1em]181 [size=1em]182 [size=1em]183 [size=1em]184 [size=1em]185 [size=1em]186 [size=1em]187 [size=1em]188 [size=1em]189 [size=1em]190 [size=1em]191 [size=1em]192 [size=1em]193 [size=1em]194 [size=1em]195 [size=1em]196 [size=1em]197 [size=1em]198 [size=1em]199 [size=1em]200 [size=1em]201 [size=1em]202 [size=1em]203 [size=1em]204 [size=1em]205 [size=1em]206 [size=1em]207 [size=1em]208 [size=1em]209 [size=1em]210 [size=1em]211 [size=1em]212 [size=1em]213 [size=1em]214 [size=1em]215 [size=1em]216 [size=1em]217 [size=1em]218 [size=1em]219 [size=1em]220 [size=1em]221 [size=1em]222 [size=1em]223 [size=1em]224 [size=1em]225 [size=1em]226 [size=1em]227 [size=1em]228 [size=1em]229 [size=1em]230 [size=1em]231 [size=1em]232 [size=1em]233 [size=1em]234 [size=1em]235 [size=1em]236 [size=1em]237 [size=1em]238 [size=1em]239 [size=1em]240 [size=1em]241 [size=1em]242 [size=1em]243 [size=1em]244 [size=1em]245 [size=1em]246 [size=1em]247 [size=1em]248 [size=1em]249 [size=1em]250 [size=1em]251 [size=1em]252 [size=1em]253 [size=1em]254 [size=1em]255 [size=1em]256 [size=1em]257 [size=1em]258 [size=1em]259 [size=1em]260 [size=1em]261 [size=1em]262 [size=1em]263 [size=1em]264 [size=1em]265 [size=1em]266 [size=1em]267 [size=1em]268 | [size=1em][size=1em]/** [size=1em] * Copyright (C) 2006 The Android Open Source Project [size=1em] * [size=1em] * Licensed under the Apache License, Version 2.0 (the "License"); [size=1em] * you may not use this file except in compliance with the License. [size=1em] * You may obtain a copy of the License at [size=1em] * [size=1em] * http://www.apache.org/licenses/LICENSE-2.0 [size=1em] * [size=1em] * Unless required by applicable law or agreed to in writing, software [size=1em] * distributed under the License is distributed on an "AS IS" BASIS, [size=1em] * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. [size=1em] * See the License for the specific language governing permissions and [size=1em] * limitations under the License. [size=1em] */ [size=1em]package Android.util; [size=1em]import com.Android.internal.os.RuntimeInit; [size=1em]import java.io.PrintWriter; [size=1em]import java.io.StringWriter; [size=1em]/** [size=1em] * API for sending log output. [size=1em] * [size=1em] * <p>Generally, use the Log.v() Log.d() Log.i() Log.w() and Log.e() [size=1em] * methods. [size=1em] * [size=1em] * <p>The order in terms of verbosity, from least to most is [size=1em] * ERROR, WARN, INFO, DEBUG, VERBOSE. Verbose should never be compiled [size=1em] * into an application except during development. Debug logs are compiled [size=1em] * in but stripped at runtime. Error, warning and info logs are always kept. [size=1em] * [size=1em] * <p><b>Tip:</b> A good convention is to declare a <code>TAG</code> constant [size=1em] * in your class: [size=1em] * [size=1em] * <pre>private static final String TAG = "MyActivity";</pre> [size=1em] * [size=1em] * and use that in subsequent calls to the log methods. [size=1em] * </p> [size=1em] * [size=1em] * <p><b>Tip:</b> Don't forget that when you make a call like [size=1em] * <pre>Log.v(TAG, "index=" + i);</pre> [size=1em] * that when you're building the string to pass into Log.d, the compiler uses a [size=1em] * StringBuilder and at least three allocations occur: the StringBuilder [size=1em] * itself, the buffer, and the String object. Realistically, there is also [size=1em] * another buffer allocation and copy, and even more pressure on the gc. [size=1em] * That means that if your log message is filtered out, you might be doing [size=1em] * significant work and incurring significant overhead. [size=1em] */ [size=1em]public final class Log { [size=1em] /** [size=1em] * Priority constant for the println method; use Log.v. [size=1em] */ [size=1em] public static final int VERBOSE = 2; [size=1em] /** [size=1em] * Priority constant for the println method; use Log.d. [size=1em] */ [size=1em] public static final int DEBUG = 3; [size=1em] /** [size=1em] * Priority constant for the println method; use Log.i. [size=1em] */ [size=1em] public static final int INFO = 4; [size=1em] /** [size=1em] * Priority constant for the println method; use Log.w. [size=1em] */ [size=1em] public static final int WARN = 5; [size=1em] /** [size=1em] * Priority constant for the println method; use Log.e. [size=1em] */ [size=1em] public static final int ERROR = 6; [size=1em] /** [size=1em] * Priority constant for the println method. [size=1em] */ [size=1em] public static final int ASSERT = 7; [size=1em] /** [size=1em] * Exception class used to capture a stack trace in {@link #wtf()}. [size=1em] */ [size=1em] private static class TerribleFailure extends Exception { [size=1em] TerribleFailure(String msg, Throwable cause) { super(msg, cause); } [size=1em] } [size=1em] private Log() { [size=1em] } [size=1em] /** [size=1em] * Send a {@link #VERBOSE} log message. [size=1em] * @param tag Used to identify the source of a log message. It usually identifies [size=1em] * the class or activity where the log call occurs. [size=1em] * @param msg The message you would like logged. [size=1em] */ [size=1em] public static int v(String tag, String msg) { [size=1em] return println_native(LOG_ID_MAIN, VERBOSE, tag, msg); [size=1em] } [size=1em] /** [size=1em] * Send a {@link #VERBOSE} log message and log the exception. [size=1em] * @param tag Used to identify the source of a log message. It usually identifies [size=1em] * the class or activity where the log call occurs. [size=1em] * @param msg The message you would like logged. [size=1em] * @param tr An exception to log [size=1em] */ [size=1em] public static int v(String tag, String msg, Throwable tr) { [size=1em] return println_native(LOG_ID_MAIN, VERBOSE, tag, msg + '/n' + getStackTraceString(tr)); [size=1em] } [size=1em] /** [size=1em] * Send a {@link #DEBUG} log message. [size=1em] * @param tag Used to identify the source of a log message. It usually identifies [size=1em] * the class or activity where the log call occurs. [size=1em] * @param msg The message you would like logged. [size=1em] */ [size=1em] public static int d(String tag, String msg) { [size=1em] return println_native(LOG_ID_MAIN, DEBUG, tag, msg); [size=1em] } [size=1em] /** [size=1em] * Send a {@link #DEBUG} log message and log the exception. [size=1em] * @param tag Used to identify the source of a log message. It usually identifies [size=1em] * the class or activity where the log call occurs. [size=1em] * @param msg The message you would like logged. [size=1em] * @param tr An exception to log [size=1em] */ [size=1em] public static int d(String tag, String msg, Throwable tr) { [size=1em] return println_native(LOG_ID_MAIN, DEBUG, tag, msg + '/n' + getStackTraceString(tr)); [size=1em] } [size=1em] /** [size=1em] * Send an {@link #INFO} log message. [size=1em] * @param tag Used to identify the source of a log message. It usually identifies [size=1em] * the class or activity where the log call occurs. [size=1em] * @param msg The message you would like logged. [size=1em] */ [size=1em] public static int i(String tag, String msg) { [size=1em] return println_native(LOG_ID_MAIN, INFO, tag, msg); [size=1em] } [size=1em] /** [size=1em] * Send a {@link #INFO} log message and log the exception. [size=1em] * @param tag Used to identify the source of a log message. It usually identifies [size=1em] * the class or activity where the log call occurs. [size=1em] * @param msg The message you would like logged. [size=1em] * @param tr An exception to log [size=1em] */ [size=1em] public static int i(String tag, String msg, Throwable tr) { [size=1em] return println_native(LOG_ID_MAIN, INFO, tag, msg + '/n' + getStackTraceString(tr)); [size=1em] } [size=1em] /** [size=1em] * Send a {@link #WARN} log message. [size=1em] * @param tag Used to identify the source of a log message. It usually identifies [size=1em] * the class or activity where the log call occurs. [size=1em] * @param msg The message you would like logged. [size=1em] */ [size=1em] public static int w(String tag, String msg) { [size=1em] return println_native(LOG_ID_MAIN, WARN, tag, msg); [size=1em] } [size=1em] /** [size=1em] * Send a {@link #WARN} log message and log the exception. [size=1em] * @param tag Used to identify the source of a log message. It usually identifies [size=1em] * the class or activity where the log call occurs. [size=1em] * @param msg The message you would like logged. [size=1em] * @param tr An exception to log [size=1em] */ [size=1em] public static int w(String tag, String msg, Throwable tr) { [size=1em] return println_native(LOG_ID_MAIN, WARN, tag, msg + '/n' + getStackTraceString(tr)); [size=1em] } [size=1em] /** [size=1em] * Checks to see whether or not a log for the specified tag is loggable at the specified level. [size=1em] * [size=1em] * The default level of any tag is set to INFO. This means that any level above and including [size=1em] * INFO will be logged. Before you make any calls to a logging method you should check to see [size=1em] * if your tag should be logged. You can change the default level by setting a system property: [size=1em] * 'setprop log.tag.<YOUR_LOG_TAG> <LEVEL>' [size=1em] * Where level is either VERBOSE, DEBUG, INFO, WARN, ERROR, ASSERT, or SUPPRESS. SUPPRESS will [size=1em] * turn off all logging for your tag. You can also create a local.prop file that with the [size=1em] * following in it: [size=1em] * 'log.tag.<YOUR_LOG_TAG>=<LEVEL>' [size=1em] * and place that in /data/local.prop. [size=1em] * [size=1em] * @param tag The tag to check. [size=1em] * @param level The level to check. [size=1em] * @return Whether or not that this is allowed to be logged. [size=1em] * @throws IllegalArgumentException is thrown if the tag.length() > 23. [size=1em] */ [size=1em] public static native boolean isLoggable(String tag, int level); [size=1em] /** [size=1em] * Send a {@link #WARN} log message and log the exception. [size=1em] * @param tag Used to identify the source of a log message. It usually identifies [size=1em] * the class or activity where the log call occurs. [size=1em] * @param tr An exception to log [size=1em] */ [size=1em] public static int w(String tag, Throwable tr) { [size=1em] return println_native(LOG_ID_MAIN, WARN, tag, getStackTraceString(tr)); [size=1em] } [size=1em] /** [size=1em] * Send an {@link #ERROR} log message. [size=1em] * @param tag Used to identify the source of a log message. It usually identifies [size=1em] * the class or activity where the log call occurs. [size=1em] * @param msg The message you would like logged. [size=1em] */ [size=1em] public static int e(String tag, String msg) { [size=1em] return println_native(LOG_ID_MAIN, ERROR, tag, msg); [size=1em] } [size=1em] /** [size=1em] * Send a {@link #ERROR} log message and log the exception. [size=1em] * @param tag Used to identify the source of a log message. It usually identifies [size=1em] * the class or activity where the log call occurs. [size=1em] * @param msg The message you would like logged. [size=1em] * @param tr An exception to log [size=1em] */ [size=1em] public static int e(String tag, String msg, Throwable tr) { [size=1em] return println_native(LOG_ID_MAIN, ERROR, tag, msg + '/n' + getStackTraceString(tr)); [size=1em] } [size=1em] /** [size=1em] * What a Terrible Failure: Report a condition that should never happen. [size=1em] * The error will always be logged at level ASSERT with the call stack. [size=1em] * Depending on system configuration, a report may be added to the [size=1em] * {@link Android.os.DropBoxManager} and/or the process may be terminated [size=1em] * immediately with an error dialog. [size=1em] * @param tag Used to identify the source of a log message. [size=1em] * @param msg The message you would like logged. [size=1em] */ [size=1em] public static int wtf(String tag, String msg) { [size=1em] return wtf(tag, msg, null); [size=1em] } [size=1em] /** [size=1em] * What a Terrible Failure: Report an exception that should never happen. [size=1em] * Similar to {@link #wtf(String, String)}, with an exception to log. [size=1em] * @param tag Used to identify the source of a log message. [size=1em] * @param tr An exception to log. [size=1em] */ [size=1em] public static int wtf(String tag, Throwable tr) { [size=1em] return wtf(tag, tr.getMessage(), tr); [size=1em] } [size=1em] /** [size=1em] * What a Terrible Failure: Report an exception that should never happen. [size=1em] * Similar to {@link #wtf(String, Throwable)}, with a message as well. [size=1em] * @param tag Used to identify the source of a log message. [size=1em] * @param msg The message you would like logged. [size=1em] * @param tr An exception to log. May be null. [size=1em] */ [size=1em] public static int wtf(String tag, String msg, Throwable tr) { [size=1em] tr = new TerribleFailure(msg, tr); [size=1em] int bytes = println_native(LOG_ID_MAIN, ASSERT, tag, getStackTraceString(tr)); [size=1em] RuntimeInit.wtf(tag, tr); [size=1em] return bytes; [size=1em] } [size=1em] /** [size=1em] * Handy function to get a loggable stack trace from a Throwable [size=1em] * @param tr An exception to log [size=1em] */ [size=1em] public static String getStackTraceString(Throwable tr) { [size=1em] if (tr == null) { [size=1em] return ""; [size=1em] } [size=1em] StringWriter sw = new StringWriter(); [size=1em] PrintWriter pw = new PrintWriter(sw); [size=1em] tr.printStackTrace(pw); [size=1em] return sw.toString(); [size=1em] } [size=1em] /** [size=1em] * Low-level logging call. [size=1em] * @param priority The priority/type of this log message [size=1em] * @param tag Used to identify the source of a log message. It usually identifies [size=1em] * the class or activity where the log call occurs. [size=1em] * @param msg The message you would like logged. [size=1em] * @return The number of bytes written. [size=1em] */ [size=1em] public static int println(int priority, String tag, String msg) { [size=1em] return println_native(LOG_ID_MAIN, priority, tag, msg); [size=1em] } [size=1em] /** @hide */ public static final int LOG_ID_MAIN = 0; [size=1em] /** @hide */ public static final int LOG_ID_RADIO = 1; [size=1em] /** @hide */ public static final int LOG_ID_EVENTS = 2; [size=1em] /** @hide */ public static final int LOG_ID_SYSTEM = 3; [size=1em] /** @hide */ public static native int println_native(int bufID, [size=1em] int priority, String tag, String msg); [size=1em]} |
我们看到所有代码都是调用public static native int println_native(int bufID,
int priority, String tag, String msg);来实现输出的,这个函数的实现就是C++,调用的方式就是JNI
我们看一下对应的jni代码froyo/frameworks/base/core/jni/Android_util_Log.cpp,最终调用的输出函数是
[size=1em]1 [size=1em]2 [size=1em]3 [size=1em]4 [size=1em]5 [size=1em]6 [size=1em]7 [size=1em]8 [size=1em]9 [size=1em]10 [size=1em]11 [size=1em]12 [size=1em]13 [size=1em]14 [size=1em]15 [size=1em]16 [size=1em]17 [size=1em]18 [size=1em]19 [size=1em]20 [size=1em]21 [size=1em]22 [size=1em]23 [size=1em]24 [size=1em]25 [size=1em]26 [size=1em]27 [size=1em]28 [size=1em]29 [size=1em]30 [size=1em]31 [size=1em]32 | [size=1em][size=1em]/* [size=1em] * In class Android.util.Log: [size=1em] * public static native int println_native(int buffer, int priority, String tag, String msg) [size=1em] */ [size=1em]static jint Android_util_Log_println_native(JNIEnv* env, jobject clazz, [size=1em] jint bufID, jint priority, jstring tagObj, jstring msgObj) [size=1em]{ [size=1em] const char* tag = NULL; [size=1em] const char* msg = NULL; [size=1em] if (msgObj == NULL) { [size=1em] jclass npeClazz; [size=1em] npeClazz = env->FindClass("java/lang/NullPointerException"); [size=1em] assert(npeClazz != NULL); [size=1em] env->ThrowNew(npeClazz, "println needs a message"); [size=1em] return -1; [size=1em] } [size=1em] if (bufID < 0 || bufID >= LOG_ID_MAX) { [size=1em] jclass npeClazz; [size=1em] npeClazz = env->FindClass("java/lang/NullPointerException"); [size=1em] assert(npeClazz != NULL); [size=1em] env->ThrowNew(npeClazz, "bad bufID"); [size=1em] return -1; [size=1em] } [size=1em] if (tagObj != NULL) [size=1em] tag = env->GetStringUTFChars(tagObj, NULL); [size=1em] msg = env->GetStringUTFChars(msgObj, NULL); [size=1em] int res = __Android_log_buf_write(bufID, (android_LogPriority)priority, tag, msg); [size=1em] if (tag != NULL) [size=1em] env->ReleaseStringUTFChars(tagObj, tag); [size=1em] env->ReleaseStringUTFChars(msgObj, msg); [size=1em] return res; [size=1em]} |
当然我们发现最终输出是
[size=1em][backcolor=rgb(108, 226, 108) !important][size=1em]1 | [size=1em][size=1em]int res = __Android_log_buf_write(bufID, (android_LogPriority)priority, tag, msg); |
用力grep了一下代码,结果如下
[size=1em][backcolor=rgb(108, 226, 108) !important][size=1em]1 [size=1em]2 [size=1em]3 | [size=1em][size=1em]./system/core/include/cutils/log.h:int __Android_log_buf_write(int bufID, int prio, const char *tag, const char *text); [size=1em]./system/core/liblog/logd_write.c:int __Android_log_buf_write(int bufID, int prio, const char *tag, const char *msg) [size=1em]./system/core/liblog/logd_write.c: return __Android_log_buf_write(bufID, prio, tag, buf); |
这个就是和Android专用驱动进行通信的方式,这个分析下去就有点深了,后面分析。
以上三个小节分析了Android的JAVA环境,我这里都是简单的抛砖引玉,希望能给大家一点大体的指引,其他修行靠大家了,能成为是一个android程序员是多么幸福的事情,各位已经在幸福中了,我什么时候也可以幸福一把??
欢迎光临 中科因仑“3+1”工程特种兵精英论坛 (http://bbs.enlern.com/) | Powered by Discuz! X3.4 |