一、底層實(shí)現(xiàn):
10多年的新羅網(wǎng)站建設(shè)經(jīng)驗(yàn),針對設(shè)計(jì)、前端、開發(fā)、售后、文案、推廣等六對一服務(wù),響應(yīng)快,48小時及時工作處理。網(wǎng)絡(luò)營銷推廣的優(yōu)勢是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動調(diào)整新羅建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。成都創(chuàng)新互聯(lián)公司從事“新羅網(wǎng)站設(shè)計(jì)”,“新羅網(wǎng)站推廣”以來,每個客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。
c文件:hardware/libhardware_legacy/power/power.c
以其中set_screen_state(int)函數(shù)為例
其Android.mk中添加:
LOCAL_MODULE:= libpower 編譯成lib
LOCAL_SRC_FILES += power.c
hardware/libhardware_legacy/power/power.c
1: int
2: set_screen_state(int on)
3: {
4: QEMU_FALLBACK(set_screen_state(on));
5:
6: LOGI("*** set_screen_state %d", on);
7:
8: initialize_fds();
9:
10: //LOGI("go_to_sleep eventTime=%lld now=%lld g_error=%s\n", eventTime,
11: // systemTime(), strerror(g_error));
12:
13: if (g_error)
14: goto failure;
15:
16: char buf[32];
17: int len;
18: if(on)
19: len = snprintf(buf, sizeof(buf), "%s", on_state);
20: else
21: len = snprintf(buf, sizeof(buf), "%s", off_state);
22:
23: buf[sizeof(buf) - 1] = '\0';
24: len = write(g_fds[REQUEST_STATE], buf, len);
25: if(len 0) {
26: failure:
27: LOGE("Failed setting last user activity: g_error=%d\n", g_error);
28: }
29: return 0;
30: }
其頭文件power.h中:
1: #if__cplusplus
2: extern "C" { //注1
3: #endif
4: enum {
5: PARTIAL_WAKE_LOCK = 1, // the cpu stays on, but the screen is off
6: FULL_WAKE_LOCK = 2 // the screen is also on
7: };
8:
9: // while you have a lock held, the device will stay on at least at the
10: // level you request.
11: int acquire_wake_lock(int lock, const char* id);
12: int release_wake_lock(const char* id);
13:
14: // true if you want the screen on, false if you want it off
15: int set_screen_state(int on);
16:
17: // set how long to stay awake after the last user activity in seconds
18: int set_last_user_activity_timeout(int64_t delay);
19:
20:
21: #if __cplusplus
22: } // extern "C"
23: #endif
注1:
注1:extern表示其他的類已經(jīng)定義了這段代碼里面的內(nèi)容,這里只是做聲明。
"C”表示的一種編譯和連接規(guī)約,這里為下一步c++調(diào)用其做準(zhǔn)備.
比如void foo(int,int);該函數(shù)被C編譯器編譯后在庫中的名字為_foo,
而C++編譯器則會產(chǎn)生像_foo_int_int之類的名字用來支持函數(shù)重載和類型安全連接。
由于編譯后的名字不同,C++程序不能直接調(diào)用C函數(shù)。
因此C++提供了一個C連接交換指定符號extern“C”來解決這個問題而不是一種語言。
C表示這段代碼可以是符合C語言的編譯和連接規(guī)約的任何語言,如Fortran、assembler等。
二、cpp構(gòu)成jni橋梁
一個CPP文件調(diào)用之,則需添加其頭文件,比如frameworks/base/core/jni/android_os_Power.cpp.
1: #include "JNIHelp.h"
2: #include "jni.h"
3: #include "android_runtime/AndroidRuntime.h"
4: #include hardware_legacy/power.h
5: namespace android{
6: ....
7:
8: //定義函數(shù):
9: static int setScreenState(JNIEnv *env, jobject clazz, jboolean on)
10: {
11: return set_screen_state(on);//以此實(shí)現(xiàn)cpp到c的調(diào)用
12: }
13:
14: static JNINativeMethod method_table[] = {//此處實(shí)現(xiàn)java對cpp的調(diào)用轉(zhuǎn)化 注2
15: { "acquireWakeLock", "(ILjava/lang/String;)V", (void*)acquireWakeLock },
16: { "releaseWakeLock", "(Ljava/lang/String;)V", (void*)releaseWakeLock },
17: { "setLastUserActivityTimeout", "(J)I", (void*)setLastUserActivityTimeout },
18: { "setScreenState", "(Z)I", (void*)setScreenState },
19: { "shutdown", "()V", (void*)android_os_Power_shutdown },
20: { "rebootNative", "(Ljava/lang/String;)V", (void*)android_os_Power_reboot },
21: };
22: int register_android_os_Power(JNIEnv *env) //此處注冊jni
23: { //向VM(即AndroidRuntime)登記 gMethods[]表格所含的本地函數(shù)
24: return AndroidRuntime::registerNativeMethods(
25: env, "android/os/Power",
26: method_table, NELEM(method_table));
27: }
28: };
注2:
typedef struct {
const char* name; //Java中函數(shù)的名字
const char* signature; //用字符串是描述了函數(shù)的參數(shù)和返回值
void* fnPtr; //函數(shù)指針,指向C函數(shù)
} JNINativeMethod;
其中比較難以理解的是第二個參數(shù),例如
"()V"
"(II)V"
"(Ljava/lang/String;Ljava/lang/String;)V"
實(shí)際上這些字符是與函數(shù)的參數(shù)類型一一對應(yīng)的。
"()" 中的字符表示參數(shù),后面的則代表返回值。例如"()V" 就表示void Func();
"(II)V" 表示 void Func(int, int);
具體的每一個字符的對應(yīng)關(guān)系如下
字符 Java類型 C類型
V void void
Z jboolean boolean
I jint int
J jlong long
D jdouble double
F jfloat float
B jbyte byte
C jchar char
S jshort short
數(shù)組則以"["開始,用兩個字符表示
[I jintArray int[]
[F jfloatArray float[]
[B jbyteArray byte[]
[C jcharArray char[]
[S jshortArray short[]
[D jdoubleArray double[]
[J jlongArray long[]
[Z jbooleanArray boolean[]
上面的都是基本類型。如果Java函數(shù)的參數(shù)是class,則以"L"開頭,以";"結(jié)尾中間是用"/" 隔開的包及類名。而其對應(yīng)的C函數(shù)名的參數(shù)則為jobject. 一個例外是String類,其對應(yīng)的類為jstring
Ljava/lang/String; String jstring
Ljava/net/Socket; Socket jobject
如果JAVA函數(shù)位于一個嵌入類,則用$作為類名間的分隔符。
例如 "(Ljava/lang/String;Landroid/os/FileUtils$FileStatus;)Z"
三、java的封裝實(shí)現(xiàn)
frameworks/base/core/java/android/os/Power.java //此處路徑跟cpp中注冊jni處的路徑是一致的.待細(xì)研究是否有關(guān)系
1: package android.os;
2: public class Power
3: {
4: ...
5: public static native int setScreenState(boolean on); //被native修飾的表示調(diào)用了非java語言的本地方法
6: ...
7: }
四、java中對其調(diào)用
frameworks/base/services/java/com/android/server/PowerManagerService.java
import android.os.Power;
public class PowerManagerService extends IPowerManager.Stub
implements LocalPowerManager, Watchdog.Monitor {
...
int err = Power.setScreenState(on);
...
}
一、簡介
為什么要對日志進(jìn)行封裝?
封裝前:快捷鍵輸入loge便可打印出Log.e(TAG, "onCreate: ", );需要輸入?yún)?shù)TAG和參數(shù)msg。 且我們可以在Logcat頁面查看日志信息。
缺點(diǎn):
(1)輸入的參數(shù)較多且重復(fù)
(2)當(dāng)打印的日志信息過多時,不方便查找我們所需的信息
(3)無法快速指定是哪一行打印出來的信息
(4)應(yīng)用發(fā)布到市場上時,需要手動一個個刪除打印的日志
封裝后:只需輸入你想打印的msg,使用方便。且可以在Logcat頁點(diǎn)擊類名即可跳轉(zhuǎn)到相應(yīng)的位置。
二、Log具體封裝
從你的問題中我總結(jié)出來的知識點(diǎn)包括: cursor查詢數(shù)據(jù)庫中的數(shù)據(jù) AsyncTask異步操作 創(chuàng)建listview有關(guān)的Adapter適配器 大體流程操作如下: 由于數(shù)據(jù)庫操作屬于耗時操作,因此要放在異步線程中執(zhí)行,cursor在查詢出數(shù)據(jù)以后,封裝到集合當(dāng)中,這就需要我們首先定義出一個實(shí)體類bean。bean中包含你從數(shù)據(jù)庫中cursor出來的字段。查詢出來的字段封裝到bean中,然后通過Adapter適配器將插敘出來的數(shù)據(jù)進(jìn)行顯示。 下面寫出關(guān)鍵代碼: cursor查詢數(shù)據(jù)庫 Cursor cursor = database.rawQuery("select * from 表名 where 字段='查詢字段'",null);代碼封裝到bean中:while (cursor.moveToNext()) {Bean bean = new Bean();bean.setId(cursor.getString(0));bean.setName(cursor.getString(1));XXXX.add(XXXXbean);}創(chuàng)建Adapter適配器: listViewAdapter = new ListViewAdapter(this, XXXX); // 創(chuàng)建適配器 XXXX_list.setAdapter(listViewAdapter);bean實(shí)體類代碼、Adapter設(shè)置數(shù)據(jù)代碼略
方法一
使用eclipse導(dǎo)出jar包:我們知道一個java項(xiàng)目是可以用eclipse導(dǎo)出jar包的,安卓工程也一樣,只要按普通的方法export就可以了。不過,export出來的包是沒有混淆過的,如果你要混淆,還需要單獨(dú)對你的jar包執(zhí)行一次proguard程序,可參考proguard使用指南。
方法二
使用腳本打包:我個人比較喜歡該方法,因?yàn)閍ndroid工程項(xiàng)目并不是只有JAVA代碼,有的資源也需要提供出來,而使腳本可以更加定制化一些。
android的SDK默認(rèn)提供了一個ant打包的腳本,具體使用方法,可參考之前的BLOG,使用ant打包APK及依賴包最佳解決辦法
我們可以看出,打包,最終調(diào)用的其實(shí)是android sdk下的ant腳本,既然安卓已經(jīng)幫我們寫好了ant腳本,我們就好好利用。
使用上面的BLOG中介紹的方法,先在工程目錄中生成你的build.xml,然后自己寫一個target
target name="sdk"
depends="-set-release-mode, -release-obfuscation-check, -compile, -post-compile, -obfuscate"
/target
這段target代碼,就是只執(zhí)行到了混淆的腳本。然后我們在build.xml中選擇右鍵,run as, 第二個ant Build,然后選擇要執(zhí)行的target為我們加上的sdk。
等執(zhí)行完成后,就會在project/bin/proguard/obfuscated.jar找到你所要的jar包。
開發(fā)封裝就是將設(shè)計(jì)調(diào)試好的程序,進(jìn)行打包封裝成用戶可以接受的!此項(xiàng)包括安裝界面,程序說明,幫助文檔,版本信息等等
封裝,例如android中一個View就是封裝了一系列的方法,這些方法系統(tǒng)已經(jīng)給你封裝好了,你只需要去調(diào)用即可。
繼承,例如一個Activity(界面),創(chuàng)建一個界面就需要去繼承它,因?yàn)閍ndroid中每個界面都是一個activity組成的(Fragment也是運(yùn)行在activity中的)。
多態(tài),這個比較抽象也比較難解釋,就像一個View,給它注冊一個點(diǎn)擊事件來說吧,系統(tǒng)用的只是一個接口,但是用戶可以用一個實(shí)現(xiàn)接口的類來處理這個點(diǎn)擊事件,這就是多態(tài)性,因?yàn)閷τ赼ndroid來講,它根本不知道用戶會起個什么名實(shí)的類,它只要你實(shí)現(xiàn)它的接口即可。