android如何封裝
㈠ android listview是怎麼封裝的
從你的問題中我總結出來的知識點包括: cursor查詢資料庫中的數據 AsyncTask非同步操作 創建listview有關的Adapter適配器 大體流程操作如下: 由於資料庫操作屬於耗時操作,因此嘩茄要放在非同步線程中執行,cursor在查詢出數據以後,封裝到集合當中,這就需要我們首先定義出一個實體類bean。bean中包含你從資料庫中cursor出來的欄位。查詢出來的欄位封裝到bean中,然後通過Adapter適配器將插敘出來的數據進行顯示。 下面寫出關鍵代碼: cursor查詢資料庫 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); }創建悶凱Adapter適配器: listViewAdapter = new ListViewAdapter(this, XXXX); // 創建適配器 XXXX_list.setAdapter(listViewAdapter);bean實體亂罩察類代碼、Adapter設置數據代碼略
㈡ 安卓有沒有辦法把安裝在手機上的軟體封裝成安裝包
安卓系統沒有這樣的功能,實現這個功能需要把原安裝包的解壓安裝過程再逆向實現。目前市場上也沒有這樣功能的軟體。可以把安裝批處理文件解析後自己編譯一下。
㈢ android 怎麼封裝jni
一、底層實現:
c文件:hardware/libhardware_legacy/power/power.c
以其中set_screen_state(int)函數為例
其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表示其他的類已經定義了這段代碼裡面的內容,這里只是做聲明。
"C」表示的一種編譯和連接規約,這里為下一步c++調用其做准備.
比如void foo(int,int);該函數被C編譯器編譯後在庫中的名字為_foo,
而C++編譯器則會產生像_foo_int_int之類的名字用來支持函數重載和類型安全連接。
由於編譯後的名字不同,C++程序不能直接調用C函數。
因此C++提供了一個C連接交換指定符號extern「C」來解決這個問題而不是一種語言。
C表示這段代碼可以是符合C語言的編譯和連接規約的任何語言,如Fortran、assembler等。
二、cpp構成jni橋梁
一個CPP文件調用之,則需添加其頭文件,比如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: //定義函數:
9: static int setScreenState(JNIEnv *env, jobject clazz, jboolean on)
10: {
11: return set_screen_state(on);//以此實現cpp到c的調用
12: }
13:
14: static JNINativeMethod method_table[] = {//此處實現java對cpp的調用轉化 注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[]表格所含的本地函數
24: return AndroidRuntime::registerNativeMethods(
25: env, "android/os/Power",
26: method_table, NELEM(method_table));
27: }
28: };
注2:
typedef struct {
const char* name; //Java中函數的名字
const char* signature; //用字元串是描述了函數的參數和返回值
void* fnPtr; //函數指針,指向C函數
} JNINativeMethod;
其中比較難以理解的是第二個參數,例如
"()V"
"(II)V"
"(Ljava/lang/String;Ljava/lang/String;)V"
實際上這些字元是與函數的參數類型一一對應的。
"()" 中的字元表示參數,後面的則代表返回值。例如"()V" 就表示void Func();
"(II)V" 表示 void Func(int, int);
具體的每一個字元的對應關系如下
字元 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
數組則以"["開始,用兩個字元表示
[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函數的參數是class,則以"L"開頭,以";"結尾中間是用"/" 隔開的包及類名。而其對應的C函數名的參數則為jobject. 一個例外是String類,其對應的類為jstring
Ljava/lang/String; String jstring
Ljava/net/Socket; Socket jobject
如果JAVA函數位於一個嵌入類,則用$作為類名間的分隔符。
例如 "(Ljava/lang/String;Landroid/os/FileUtils$FileStatus;)Z"
三、java的封裝實現
frameworks/base/core/java/android/os/Power.java //此處路徑跟cpp中注冊jni處的路徑是一致的.待細研究是否有關系
1: package android.os;
2: public class Power
3: {
4: ...
5: public static native int setScreenState(boolean on); //被native修飾的表示調用了非java語言的本地方法
6: ...
7: }
四、java中對其調用
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);
...
}
㈣ Kotlin Coroutine在 Android 中的使用和封裝
kotlin出來很多年,並被google被賦予Android首選開發語言的地位,還是有必要研究一下的,基礎語法不再復述了,只簡單聊聊kotlin中的核心內容之一:協程 Coroutine。
相關概念和API可以直接進入[官網](https://kotlinlang.org/)查詢,
不過不推薦kotlin中文網,文章翻譯的略顯生硬,看了更容易迷惑。
本文不講基礎(基礎我也不怎麼清楚。。),適合喜歡拿來主義的同學
協程作為輕量級的線程,是建立在線程之上的調度,比線程節省資源但不意味著不消耗資源,在Android這種系統資源相對珍貴的環境中,當非同步繁瑣的調用或者切換線程,如何及時的回收也是必要的工作。
### 一、添加依賴配置
coroutine 是在kotlin 1.3中發布的1.0正式版,所以建議優先使用這個版本。
項目根目錄中gradle配置:
主mole中gradle配置
假如你的其他mole也使用kt代碼,也需要添加上述依賴,不然有可能會出現找不到class或符號相關編譯錯誤
二、替換RxJava和升級Retrofit
一般項目中會引用retrofit + RxJava的組合進行網路請求,或者你單獨封裝了一層RxJava來進行非同步操作、切換線程來處理你的業務
RxJava雖然操作符眾多(得有100個以上了吧),上手不易,但著實好用,一條鏈走下來搞定你的全部業務,如果有網路請求配合上retrofit這種支持Rx的庫,不要太給力。
不過函數式開發有個通病,這條鏈子上會創建大量對象,回收內存抖動你不得不考慮,雖然使用了線程池,可開銷不容小覷。
RxJava 雖然可以鏈式調用,但終究還是基於回調形式,而協程完全做到了同步方式寫非同步代碼。
看下以前Retrofit的寫法(簡易)
RxJava 的調用鏈上使用RxLife來綁定生命周期(或者使用Uber的autodispose),很常見的代碼。
對於RxJava你還有可能會封裝一個小工具(主要是為了生命周期和回收問題)
現在呢,想用協程怎麼辦,假設你現在已經知道了如何啟動一個協程
也知道了launch 和 async的區別(返回值不同),也知道了需要一個返回值和多個返回值的選擇(async 和 rece),那在Android中如何使用呢
三、封裝
你可以像封裝RxJava一樣,封裝一個工具來使用協程,同時遵循一些原則:
#### 1 調度器
你開啟的協程需要有調度器,就像RxJava自由切換線程一樣,但主線程調度器最好察配迅指定Main來避免不必要的麻煩。
舉個例子,你使用RxJava+autodipose來綁定 生命周期,但你在子線程用RxJava又開啟了一個新線程,調度回UI線程刷新view的時候會發生崩潰
#### 2 父協程和子協程有強烈的層級關系
cancel一個Job 會拋出 CancellationException ,但這個異常不需要開發人員管理,但如果協程內部發生了非 CancellationException ,則會使用這個異常來取消父Coroutine。為了保證穩定的Coroutine層級關系,這敗此種行為不能被修改。 然後當所有的子Coroutine都終止後,父Coroutine會收到原來拋出的異常信息。
下邊是個協程的簡易封裝案例
context 視業務情況而定是否傳入
然後在你的act或Fragment中直接調用
對於Retrofit修改更為簡單,2.6版本已經支持了協程,網上有很多介紹
將Observable返回值修改為你需要的bean, 加上suspend標記即可,
下邊是示例代碼:
### 四、混淆
網上的帖子大多以demo的思路來寫,商用肯定要混淆了,不添加proguard你混淆後就死翹翹了,所以直接貼上來
coroutine的配置
假如release打包後你的Retrofit 請求結果發生了npe,檢查下你的bean是否添加了不混淆配置
### 其他
研究協程沒多久,有錯誤或建議歡賣李迎指出,共同交流
另外推薦雲在千峰的[博客](http://blog.chengyunfeng.com/?p=1088) ,是我目前看過的最友好的coroutine系列文章
㈤ Android 基類BaseActivity的封裝
摘要
本篇總結了前人寫的BaseActivity,自己在開發過程中也添添補補,刪刪改改,現在總結下。
本篇很多知識借鑒和學習了知乎上iYng大大的回答,先感謝一波。順便上原文鏈接:
https://www.hu.com/question/47045239/answer/105086885
正文
一般來說,不同的項目的BaseActivity不盡相同,根據不同的業務邏輯和功能需求,會有很多區別。這里總結了一些,如下:
視圖相關
一般的Activity里都會用到很多的findViewById這個方法,而且每次都要強制類型轉換,這樣會顯得很繁瑣,如果在BaseActivity里封裝好,就能省事:
這樣只要是繼承了BaseActivity就能輕松使用LinearLayout llContent = findView(R.id.ll_content);,免去了諸多類型轉換的麻煩。
然後說起視圖,一般的Activity里都會需要初始化視圖和數據,所以可以暴露兩個方法initView()和initData():
然後在setContentView里去調用,一般都是先initView,然後再initData:
這樣子類里都必須重寫initView()和initData()了,邏輯也能清晰點,不然什麼東西都放在onCreate里,就很亂了;
用戶模塊(業務相關【可選】)
不過一般的app,只要是有登錄的,就會有用戶模塊,也會根據用戶標識id去進行一些網路操作,所以用戶模塊可以在BaseActivity中暴露一些方法,比如用戶id的獲取:
這里就是返回了SharedPreference里存儲的用戶id,在用戶id大量被使用的場景下,這樣的封裝還是很有必要的,使用起來也更便捷。當然如果只是純展示的app就不一定需要了,或許顯得多餘。
界面間跳轉傳參
很多時候,Activity之間都會傳參,所以可以封裝一個參數處理的函數initParam(),在BaseActivity的onCreate里去判斷是否有參數傳過來;
然後把initParam()方法暴露給子類:
這個方法並不是必須重寫的,因為傳參也沒有想像中那麼多,並不需要強制重寫這個方法。
一般會在Application類里去定義一個isDebug來判斷是否開啟調試(開發者模式):
在BaseActivity里,我們可以把isDebug作為總開關,然後控制是否顯示調試信息:
這樣一鍵關閉調試,不用去一個個刪項目里的Log信息,是不是很贊?
每次Toast,都用Toast.makeText(...).show();是不是很煩?那麼可以在BaseActivity里封裝下,比如:
這里ToastUtils就是一個Toast封裝類,裡面的內容估計大家都懂。然後這樣一來,所有子類在使用時,只需要瀟灑寫一句toast("xxxx")就行了,當然也可以一並封裝Toast.LENGTH_LONG和Toast.LENGTH_SHORT,按需封裝吧。
其他
軟鍵盤
有的app里,用戶輸入的情景會比較多,這個時候,軟鍵盤的隱藏就用的多了,用戶輸入完之後,或者用戶點擊屏幕空白處,都應該去隱藏軟鍵盤,這樣的話,可以考慮在BaseActivity里寫隱藏的方法:
上面3個方法也是很實用的。dispatchTouchEvent方法不需要手動調用,只要是有點擊事件,並且點擊在軟鍵盤和EditText區域外,就會隱藏軟鍵盤。
防止快速點擊
有時候,用戶(特別是測試猿)會瘋狂的點擊app,這一舉動的原因和意義不明,但是我們可以設置防止快速點擊給app造成的傷害和負擔:
這樣在1秒之內只會響應一次,麻麻再也不用擔心我手抽筋亂點了。
那麼怎麼用呢?舉個栗子,可以在onClick介面里去判斷下嘛:
頁面跳轉:startActivity、startActivityForResult
這個也是可選的,可以封裝下,達到每次跳轉不需要傳this或者XXXXX.this這種參數:
這些方法還是很便捷的,使用時可以簡單的使用startActivity(MainActivity.class);,也可以傳Bundle參數。
是否允許全屏
設置一個成員變數mAllowFullScreen
通過在BaseActivity的onCreate方法里判斷mAllowFullScreen來設置是否允許全屏:
然後給子類暴露一個方法來設置mAllowFullScreen:
設置沉浸式狀態欄
跟設置全屏一樣一樣的:
然後BaseActivity的onCreate里:
然後定義steepStatusBar()方法,用來設置沉浸式狀態欄:
這里就要判斷系統版本了。只有在KITKAT以上才有作用。
最後給子類暴露方法,設置 isSetStatusBar的值:
設置是否允許屏幕旋轉
跟前面兩種思路一樣,通過判斷變數,在onCreate里設置咯:
BaseActivity里的onCreate方法:
最後暴露方法設置isAllowScreenRoate的值:
總結
上面的這些方法大都是比較常用的,有些雖然不是很常用,但是寫了也會方便一點,把這篇文章當做一個匯總,然後按需使用唄。
㈥ android 應用依賴某個庫怎麼封裝成sdk
方法一
使用eclipse導出jar包:我們知道一個java項目是可以用eclipse導出jar包的,安卓工程也一樣,只要按普通的方法export就可以了。不過,export出來的包是沒大者有混淆過的,如果你要混淆,還需要單獨對你的jar包執行一次proguard程序,可參考proguard使用指南。
方法二
使用腳本打包:我個人比較喜歡該方法,因為android工程項目並不是只有JAVA代含褲碼,有的資源也需要提供出來,而使腳本可以更加定製化一些。
android的SDK默認提供了一個ant打包的腳本,具體使用方法,可參考之前的BLOG,使用ant打包APK及依賴包最佳解決辦法
我們可以看出,打包,最終調用的其談仿簡實是android sdk下的ant腳本,既然安卓已經幫我們寫好了ant腳本,我們就好好利用。
使用上面的BLOG中介紹的方法,先在工程目錄中生成你的build.xml,然後自己寫一個target
<target name="sdk"
depends="-set-release-mode, -release-obfuscation-check, -compile, -post-compile, -obfuscate">
</target>
這段target代碼,就是只執行到了混淆的腳本。然後我們在build.xml中選擇右鍵,run as, 第二個ant Build,然後選擇要執行的target為我們加上的sdk。
等執行完成後,就會在project/bin/proguard/obfuscated.jar找到你所要的jar包。
㈦ React-Native-Android怎麼封裝原生組件
Android React Native 已經將幾個常用的原生組件進行了封裝,比如 ScrollView 和 TextInput,但是並不是所有系統的原始組件都被封裝了,因此有的時候我們不得不自己動手封裝一下,從而能夠使用那些React Native沒有為我們封裝的原生組件,比如WebView,官方並沒有提供Android端的實現,那麼我們現在就動手封裝一下WebView。
之前寫過一篇文章Android React Native使用原生模塊,而使鉛亮用原生UI組件的方法和使用原生模塊的方法十分類似。
首先,我需要繼承SimpleViewManager這個泛型類,和原生掘激蘆模塊類似,需要重寫getName()方法,將UI組件名稱暴露給javascript層,接著需要重寫createViewInstance方法,在里判帶面返回我們需要使用的原生UI組件的實例,這里就是WebView。然後就是暴露一些必要屬性給javascript層,為了簡單起見,我們這里只暴露兩個屬性,一個是url,一個是html,一旦javascript層設置了url,就會載入一個網頁,而一旦設置了html,則會去載入這段html,而屬性的暴露是使用註解,將註解設置在對應的set方法上,之後再set方法中處理UI的更新,比如一旦設置了url,在setUrl裡面就要載入網頁。最終我們的ViewManager就是這樣子的
public class ReactWebViewManager extends SimpleViewManager<WebView> {
public static final String REACT_CLASS = "RCTWebView";
@Override
public String getName() {
return REACT_CLASS;
}
@Override
protected WebView createViewInstance(ThemedReactContext reactContext) {
WebView webView= new WebView(reactContext);
webView.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
});
return webView;
}
@ReactProp(name = "url")
public void setUrl(WebView view,@Nullable String url) {
Log.e("TAG", "setUrl");
view.loadUrl(url);
}
@ReactProp(name = "html")
public void setHtml(WebView view,@Nullable String html) {
Log.e("TAG", "setHtml");
view.loadData(html, "text/html; charset=utf-8", "UTF-8");
}
}
和原生模塊一樣,原生UI組件也需要進行注冊,實現ReactPackage介面,進行WebView的注冊。
public class AppReactPackage implements ReactPackage {
@Override
public List<NativeMole> createNativeMoles(ReactApplicationContext reactContext) {
return Collections.emptyList();;
}
@Override
public List<Class<? extends JavaScriptMole>> createJSMoles() {
return Collections.emptyList();
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Arrays.<ViewManager>asList(
new ReactWebViewManager());
}
}
將這個ReactPackage添加到ReactInstanceManager實例中去
.addPackage(new AppReactPackage())
然後在javascript層新建一個WebView.js文件。輸入下面的內容
'use strict';
var { requireNativeComponent,PropTypes } = require('react-native');
var iface = {
name: 'WebView',
propTypes: {
url: PropTypes.string,
html: PropTypes.string,
},
};
mole.exports = requireNativeComponent('RCTWebView', iface);
可以看到,我們只是在裡面指定了屬性的類型。
到目前為止,你已經可以使用這個WebView組件了。
var WebView=require('./WebView');
㈧ React-Native-Android怎麼封裝原生組件
參考如下內容:首先在Android中嵌入ReactNative:每一個AndroidStudioproject下包含多個mole,所以,從命令行進入到mole根目錄,運行:[plain]viewplain$npminit$npminstall--savereact-native$curl-o.flowconfig/facebook/react-native/master/.flowconfig上述命令會創建一些react-native依賴的一些模塊,在package.json文件的scripts屬性中添加:[javascript]viewplain"start":"nodenode_moles/react-native/local-cli/cli.jsstart"註:如果scripts中存在其他鍵值對,則以逗號為分隔符。在mole的根目錄創建index.android.js文件,並將一下內容下入index.android.js文件:[javascript]viewplain'usestrict';importReactfrom'react';import{AppRegistry,StyleSheet,Text,View}from'react-native';classHelloWorldextendsReact.Component{render(){return(Hello,World)}}varstyles=StyleSheet.create({container:{flex:1,justifyContent:'center',},hello:{fontSize:20,textAlign:'center',margin:10,},});AppRegistry.registerComponent('HelloWorld',()=>HelloWorld);在AndroidStudio中,在moudle的build.gradle文件中添加一下內容:[javascript]viewplainallprojects{repositories{maven{//AllofReactNative(JS,Androidbinaries)isinstalledfromnpmurl"$rootDir/node_moles/react-native/android"}}}在AndroidManifest.xml文件中添加網路訪問許可權(僅在開發或調試中需要該許可權):
㈨ android 怎麼封裝jni
android 怎麼封裝jni
一、底層實現:
c檔案:hardware/libhardware_legacy/power/power.c
以其中set_screen_state(int)函式為例
其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
", 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] = '