編輯:關於Android編程
在開發Android應用程序時,少不了使用Log來監控和調試程序的執行。在上一篇文章Android日志系統驅動程序Logger源代碼分析中,我們分析了驅動程序Logger的源代碼,在前面的文章淺談Android系統開發中Log的使用一文,我們也簡單介紹在應用程序中使Log的方法,在這篇文章中,我們將詳細介紹Android應用程序框架層和系統運行庫存層日志系統的源代碼,使得我們可以更好地理解Android的日志系統的實現。
我們在Android應用程序,一般是調用應用程序框架層的Java接口(android.util.Log)來使用日志系統,這個Java接口通過JNI方法和系統運行庫最終調用內核驅動程序Logger把Log寫到內核空間中。按照這個調用過程,我們一步步介紹Android應用程序框架層日志系統的源代碼。學習完這個過程之後,我們可以很好地理解Android系統的架構,即應用程序層(Application)的接口是如何一步一步地調用到內核空間的。
一. 應用程序框架層日志系統Java接口的實現。
在淺談Android系統開發中Log的使用一文中,我們曾經介紹過Android應用程序框架層日志系統的源代碼接口。這裡,為了描述方便和文章的完整性,我們重新貼一下這部份的代碼,在frameworks/base/core/java/android/util/Log.java文件中,實現日志系統的Java接口:
[color=amily:Consolas,'Courier]
[java] view plaincopy
................................................
public final class Log {
................................................
/**
* Priority constant for the println method; use Log.v.
*/
public static final int VERBOSE = 2;
/**
* Priority constant for the println method; use Log.d.
*/
public static final int DEBUG = 3;
/**
* Priority constant for the println method; use Log.i.
*/
public static final int INFO = 4;
/**
* Priority constant for the println method; use Log.w.
*/
public static final int WARN = 5;
/**
* Priority constant for the println method; use Log.e.
*/
public static final int ERROR = 6;
/**
* Priority constant for the println method.
*/
public static final int ASSERT = 7;
.....................................................
public static int v(String tag, String msg) {
return println_native(LOG_ID_MAIN, VERBOSE, tag, msg);
}
public static int v(String tag, String msg, Throwable tr) {
return println_native(LOG_ID_MAIN, VERBOSE, tag, msg + '\n' + getStackTraceString(tr));
}
public static int d(String tag, String msg) {
return println_native(LOG_ID_MAIN, DEBUG, tag, msg);
}
public static int d(String tag, String msg, Throwable tr) {
return println_native(LOG_ID_MAIN, DEBUG, tag, msg + '\n' + getStackTraceString(tr));
}
public static int i(String tag, String msg) {
return println_native(LOG_ID_MAIN, INFO, tag, msg);
}
public static int i(String tag, String msg, Throwable tr) {
return println_native(LOG_ID_MAIN, INFO, tag, msg + '\n' + getStackTraceString(tr));
}
public static int w(String tag, String msg) {
return println_native(LOG_ID_MAIN, WARN, tag, msg);
}
public static int w(String tag, String msg, Throwable tr) {
return println_native(LOG_ID_MAIN, WARN, tag, msg + '\n' + getStackTraceString(tr));
}
public static int w(String tag, Throwable tr) {
return println_native(LOG_ID_MAIN, WARN, tag, getStackTraceString(tr));
}
public static int e(String tag, String msg) {
return println_native(LOG_ID_MAIN, ERROR, tag, msg);
}
public static int e(String tag, String msg, Throwable tr) {
return println_native(LOG_ID_MAIN, ERROR, tag, msg + '\n' + getStackTraceString(tr));
}
..................................................................
/** @hide */ public static native int LOG_ID_MAIN = 0;
/** @hide */ public static native int LOG_ID_RADIO = 1;
/** @hide */ public static native int LOG_ID_EVENTS = 2;
/** @hide */ public static native int LOG_ID_SYSTEM = 3;
/** @hide */ public static native int println_native(int bufID,
int priority, String tag, String msg);
}
定義了2~7一共6個日志優先級別ID和4個日志緩沖區ID。回憶一下Android日志系統驅動程序Logger源代碼分析一文,在Logger驅動程序模塊中,定義了log_main、log_events和log_radio三個日志緩沖區,分別對應三個設備文件/dev/log/main、/dev/log/events和/dev/log/radio。這裡的4個日志緩沖區的前面3個ID就是對應這三個設備文件的文件描述符了,在下面的章節中,我們將看到這三個文件描述符是如何創建的。在下載下來的Android內核源代碼中,第4個日志緩沖區LOG_ID_SYSTEM並沒有對應的設備文件,在這種情況下,它和LOG_ID_MAIN對應同一個緩沖區ID,在下面的章節中,我們同樣可以看到這兩個ID是如何對應到同一個設備文件的。
在整個Log接口中,最關鍵的地方聲明了println_native本地方法,所有的Log接口都是通過調用這個本地方法來實現Log的定入。下面我們就繼續分析這個本地方法println_native。
二. 應用程序框架層日志系統JNI方法的實現。
在frameworks/base/core/jni/android_util_Log.cpp文件中,實現JNI方法println_native:
[color=amily:Consolas,'Courier]
[cpp] view plaincopy
/* //device/libs/android_runtime/android_util_Log.cpp
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#define LOG_NAMESPACE "log.tag."
#define LOG_TAG "Log_println"
#include <assert.h>
#include <cutils/properties.h>
#include <utils/Log.h>
#include <utils/String8.h>
#include "jni.h"
#include "utils/misc.h"
#include "android_runtime/AndroidRuntime.h"
#define MIN(a,b) ((a<b)?a:b)
namespace android {
struct levels_t {
jint verbose;
jint debug;
jint info;
jint warn;
jint error;
jint assert;
};
static levels_t levels;
static int toLevel(const char* value)
{
switch (value[0]) {
case 'V': return levels.verbose;
case 'D': return levels.debug;
case 'I': return levels.info;
case 'W': return levels.warn;
case 'E': return levels.error;
case 'A': return levels.assert;
case 'S': return -1; // SUPPRESS
}
return levels.info;
}
static jboolean android_util_Log_isLoggable(JNIEnv* env, jobject clazz, jstring tag, jint level)
{
#ifndef HAVE_ANDROID_OS
return false;
#else /* HAVE_ANDROID_OS */
int len;
char key[PROPERTY_KEY_MAX];
char buf[PROPERTY_VALUE_MAX];
if (tag == NULL) {
return false;
}
jboolean result = false;
const char* chars = env->GetStringUTFChars(tag, NULL);
if ((strlen(chars)+sizeof(LOG_NAMESPACE)) > PROPERTY_KEY_MAX) {
jclass clazz = env->FindClass("java/lang/IllegalArgumentException");
char buf2[200];
snprintf(buf2, sizeof(buf2), "Log tag \"%s\" exceeds limit of %d characters\n",
chars, PROPERTY_KEY_MAX - sizeof(LOG_NAMESPACE));
// release the chars!
env->ReleaseStringUTFChars(tag, chars);
env->ThrowNew(clazz, buf2);
return false;
} else {
我們都知道,手機時代的來臨的主要標志是啥?能夠方便的接入互聯網!互聯網展現給我們的方式一般都是網頁,網頁中又必不可少的擁有javascript,所以說,android提供
目前有越來越多的手機具備自動對焦的拍攝功能,這也意味著這些手機可以具備條碼掃描的功能。手機具備條碼掃描的功能,可以優化購物流程,快速存儲電子名片(二維碼)等。本文所述實例
學習和開發Android應用有一段時間了,今天寫一篇博客總結一下Android的apk文件反編譯。我們知道,Android應用開發完成之後,我們最終都會將應用打包成一個a
本文實例為大家分享了Android實現一個仿支付寶支付密碼的輸入框,主要實現如下:PasswordView.javapackage com.jackie.alipay.p