編輯:關於Android編程
一個好的Android應用開發框架,可以加快Android開發速度,今天筆記基於許多開源項目自寫了一款Android應用框架。
框架包括:界面管理(Activity管理)、數據庫操作(orm框架、加密等)、http交互、緩存管理、下載管理、路徑管理、日志輸出、網絡管理、系統命令、加解密、stl容器、任務管理、奔潰管理、存儲管理、其它輔助管理…。
解決思路如下:
界面管理:使用Stack記錄Activity的運行軌跡,並在每個Activity添加一個廣播處理自定義事件。
private static Stack mActivityStack;//進行Activity運行記錄數據庫管理:對數據庫的操作要求orm框架、加解密等,采用的是greendao和sqlcrypt開源項目解決。
http交互:實現http交互方式有同步、異步操作。采用的是android-async-http開源項目解決。
緩存管理:實現緩存方式有內存緩存、磁盤緩存。其中內存緩存只針對圖片處理,磁盤緩存是針對某目錄,實現的方式有:先進先出、最大量、使用頻率等。
下載管理:下載管理方式有多線程下載、單線程下載。
路徑管理:簡單的說就是對程序的目錄管理,分圖片、視頻、音頻、緩存目錄等。
日志輸出:基於Log的管理(分調式、發布模式和文件輸出、log輸出)。
網絡管理:2G、3G、4G等聯網方式不同的管理和監聽。
系統命令:直接命令運行。
加解密:aes、base64、des、md5等加密方式。
stl容器:重寫stl部分容器。
任務管理:基於AsyncTask任務的管理。
奔潰管理:捕捉奔潰信息,並提供發送接口。采用的是acra方法解決。
存儲管理:主要是SharedPreferences和Properties的管理。
其它輔助管理:版本、內存、手機格式、字符串操作……等等。
項目如圖:
效果如圖:
+
<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD48cD48YnIgLz48L3A+PHA+z+C52LLiytS0+sLro7o8L3A+PHA+PC9wPjxwcmUgY2xhc3M9"brush:java;"> @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_tree);
TFilePathManager.getInstance().initConfig(null); // 默認目錄(下載??圖片、視頻??緩存等目??
// 優先考慮內存條,其次手機內存??
}
public void onClickTestPath(View view) { // 測試路徑
TFilePathManager.getInstance().initConfig(
Environment.getExternalStorageDirectory().getPath()
+ File.pathSeparator + "test");
// 程序目錄裡面分了圖片、緩存區、下載圖、音頻區、視頻區
TFilePathManager.getInstance().getAppPath();
TFilePathManager.getInstance().getAudioPath();
TFilePathManager.getInstance().getCachePath();
TFilePathManager.getInstance().getDownloadPath();
TFilePathManager.getInstance().getImagePath();
}
public void onClickTestLog(View view) { // 測試日志
TLog.enablePrintToFileLogger(true);
for (int i = 0; i < 100; i++)
TLog.i(TAG, "123456" + i);
// TLog.release(); //關閉程序可釋??
// 日志是放在程序目錄下
// TLog.enableIgnoreAll(enable);
// TLog.enableIgnoreWarn(enable);
}
public void onClickTestTActivity(View view) { // 測試TActivity
Intent intent = new Intent();
intent.setClass(this, TestTActivity.class);
startActivity(intent);
}
public void onClickTestHttp1(View view) { // 測試Http1
Intent intent = new Intent();
intent.setClass(this, TestHttp1.class);
startActivity(intent);
}
public void onClickTestHttp2(View view) { // 測試Http2
Intent intent = new Intent();
intent.setClass(this, TestHttp2.class);
startActivity(intent);
}
public void onClickTestThreadsdown(View view) { // 測試多線程下載
Intent intent = new Intent();
intent.setClass(this, TestDowns.class);
startActivity(intent);
}
public void onClickTestCrash(View view) { // 崩潰
int result = 1 / 0;
}
public void onClickTestSqlEncrypt(View view) { // 測試sql加密
Intent intent = new Intent();
intent.setClass(this, TestSqlEncrypt.class);
startActivity(intent);
}
public void onClickTestDAO(View view) { // 測試orm數據庫
Intent intent = new Intent();
intent.setClass(this, TestDAO.class);
startActivity(intent);
}
public void onClickTestDB(View view) { // 測試Think數據庫
Intent intent = new Intent();
intent.setClass(this, TestDB.class);
startActivity(intent);
}
public void onClickTestCache(View view) { // 測試緩存
Intent intent = new Intent();
intent.setClass(this, TestCache.class);
startActivity(intent);
}
public void onClickTConfig(View view) { // 測試配置信息
TPreferenceConfig.getInstance().initConfig(this);
TPropertiesConfig.getInstance().initConfig(this);
TIConfig iConfig = TPreferenceConfig.getInstance();
iConfig.setBoolean("123", true);
boolean result = iConfig.getBoolean("123", false);
iConfig = TPropertiesConfig.getInstance();
iConfig.setBoolean("1234", true);
result = iConfig.getBoolean("1234", false);
}
public void onClickEncryption(View view) { // 測試加密
String src = "[email protected]";
String encrypted = "";
String key = "banketree";
try {
encrypted = TAes.encrypt(key, src);
String tempString = TAes.decrypt(key, encrypted);
encrypted = TBase64.encode(src.getBytes());
tempString = TBase64.decode(encrypted).toString();
encrypted = TDes.encrypt(key, src);
tempString = TDes.decrypt(key, encrypted);
TLog.i(this, tempString);
} catch (Exception e) {
e.printStackTrace();
}
}
public void onClickZip(View view) { // 測試解壓縮
try {
TCompressUtils.compressJar("");
TCompressUtils.compressZip("");
TCompressUtils.uncompressJar("");
TCompressUtils.uncompressZip("");
} catch (Exception e) {
e.printStackTrace();
}
}
奔潰處理回調:
@Override public void onAppCrash(String crashFile) { TLog.d(TAG, "Creating Dialog for " + crashFile); Intent dialogIntent = new Intent(this, TestCrash.class); dialogIntent.putExtra(TCrash.EXTRA_REPORT_FILE_NAME, crashFile); dialogIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(dialogIntent); }
mMemoryCacheSize = 2 * 1024 * 1024;// 2M mDiscCacheSize = 2 * 1024 * 1024;// 2M mDiscCacheFileCount = 100;// 一百個文件 mMemoryCache = TCacheManager.createLruMemoryCache(mMemoryCacheSize); try { mDiscCache1 = TCacheManager.createReserveDiscCache(TFilePathManager .getInstance().getCachePath(), "test"); } catch (Exception e) { e.printStackTrace(); } try { mDiscCache2 = TCacheManager.createFileCountLimitedDiscCache( mDiscCacheFileCount, TFilePathManager.getInstance() .getCachePath()); } catch (Exception e) { e.printStackTrace(); }
try { Drawable demo = getResources().getDrawable(R.drawable.ic_launcher); Bitmap bitmap = ((BitmapDrawable) demo).getBitmap(); if (arg0 == mTest1Button) { mMemoryCache.put("123", bitmap); mMemoryCache.put("1234", bitmap); mMemoryCache.get("123"); mMemoryCache.get("1234"); } else if (arg0 == mTest2Button) { mDiscCache1.put("123", mContext.getCacheDir()); mDiscCache1.get("123"); } else if (arg0 == mTest3Button) { mDiscCache2.put("123", mContext.getCacheDir()); mDiscCache2.get("123"); } } catch (Exception e) { makeText(e.getMessage()); }
@Override public void onClick(View arg0) { if (testComparatorButton == arg0) { Log.i("", ""); UIBroadcast.sentEvent(mContext, 1001, 1002, ""); } } @Override public void processEvent(Intent intent) { super.processEvent(intent); int mainEvent = intent.getIntExtra(UIBroadcast.MAINEVENT, -1); // 主事?? int subEvent = intent.getIntExtra(UIBroadcast.EVENT, -1);// 次事?? makeText("哈哈觸發??" + mainEvent + subEvent);// 每個Activity可接收廣?? }
if (view == mCancelButton) { mTAsyncHttpClient.cancelRequests(this, true); mTAsyncHttpClient.cancelAllRequests(true); } else if (view == mGetButton) { url = "https://httpbin.org/get"; mTAsyncHttpClient.get(url, new AsyncHttpResponseHandler() { @Override public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) { debugHeaders(headers); debugStatusCode(statusCode); debugResponse(new String(responseBody)); } @Override public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) { debugHeaders(headers); debugStatusCode(statusCode); if (responseBody != null) { debugResponse(new String(responseBody)); } TLog.e(this, error.getMessage()); } @Override public void onProgress(int bytesWritten, int totalSize) { super.onProgress(bytesWritten, totalSize); } @Override public void onRetry(int retryNo) { makeText(String.format("Request is retried, retry no. %d", retryNo)); } }); } else if (view == mPostButton) { url = "http://httpbin.org/post"; mTAsyncHttpClient.post(mContext, url, getRequestHeaders(), getRequestEntity(), null, new AsyncHttpResponseHandler() { @Override public void onStart() { } @Override public void onSuccess(int statusCode, Header[] headers, byte[] response) { debugHeaders(headers); debugStatusCode(statusCode); debugResponse(new String(response)); } @Override public void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwable e) { debugHeaders(headers); debugStatusCode(statusCode); debugThrowable(e); if (errorResponse != null) { debugResponse(new String(errorResponse)); } } }); } else if (view == mPutButton) { url = "http://httpbin.org/put"; mTAsyncHttpClient.put(this, url, getRequestHeaders(), getRequestEntity(), null, new AsyncHttpResponseHandler() { @Override public void onStart() { } @Override public void onSuccess(int statusCode, Header[] headers, byte[] response) { debugHeaders(headers); debugStatusCode(statusCode); debugResponse(new String(response)); } @Override public void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwable e) { debugHeaders(headers); debugStatusCode(statusCode); debugThrowable(e); if (errorResponse != null) { debugResponse(new String(errorResponse)); } } }); } else if (view == mDeleteButton) { url = "http://httpbin.org/delete"; mTAsyncHttpClient.delete(this, url, getRequestHeaders(), null, new AsyncHttpResponseHandler() { @Override public void onStart() { } @Override public void onSuccess(int statusCode, Header[] headers, byte[] response) { debugHeaders(headers); debugStatusCode(statusCode); debugResponse(new String(response)); } @Override public void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwable e) { debugHeaders(headers); debugStatusCode(statusCode); debugThrowable(e); if (errorResponse != null) { debugResponse(new String(errorResponse)); } } }); } else if (view == mFileButton) { url = "https://httpbin.org/robots.txt"; mTAsyncHttpClient.get(this, url, getRequestHeaders(), null, new FileAsyncHttpResponseHandler(this) { @Override public void onStart() { } @Override public void onSuccess(int statusCode, Header[] headers, File response) { debugHeaders(headers); debugStatusCode(statusCode); debugFile(response); } @Override public void onFailure(int statusCode, Header[] headers, Throwable throwable, File file) { debugHeaders(headers); debugStatusCode(statusCode); debugThrowable(throwable); debugFile(file); } private void debugFile(File file) { if (file == null || !file.exists()) { debugResponse("Response is null"); return; } try { debugResponse(file.getAbsolutePath() + "\r\n\r\n" + TFileUtils.getStringFromFile(file)); } catch (Throwable t) { TLog.e(TAG, "Cannot debug file contents" + t.getMessage()); } if (!deleteTargetFile()) { TLog.d(TAG, "Could not delete response file " + file.getAbsolutePath()); } } }); } else if (view == mGZipButton) { url = "http://httpbin.org/gzip"; mTAsyncHttpClient.get(this, url, null, null, new BaseJsonHttpResponseHandler() { @Override public void onStart() { } @Override public void onSuccess(int statusCode, Header[] headers, String rawJsonResponse, SampleJSON response) { debugHeaders(headers); debugStatusCode(statusCode); if (response != null) { debugResponse(rawJsonResponse); } } @Override public void onFailure(int statusCode, Header[] headers, Throwable throwable, String rawJsonData, SampleJSON errorResponse) { debugHeaders(headers); debugStatusCode(statusCode); debugThrowable(throwable); if (errorResponse != null) { debugResponse(rawJsonData); } } @Override protected SampleJSON parseResponse(String rawJsonData, boolean isFailure) throws Throwable { return null; // return new ObjectMapper().readValues( // new JsonFactory().createParser(rawJsonData), // SampleJSON.class).next(); } }); } else if (view == mRedirect302Button) { url = "http://httpbin.org/redirect/6"; HttpClient client = mTAsyncHttpClient.getHttpClient(); if (client instanceof DefaultHttpClient) { // enableRedirects/enableRelativeRedirects/enableCircularRedirects mTAsyncHttpClient.setEnableRedirects(true, true, true); } mTAsyncHttpClient.get(url, new AsyncHttpResponseHandler() { @Override public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) { debugHeaders(headers); debugStatusCode(statusCode); debugResponse(new String(responseBody)); } @Override public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) { debugHeaders(headers); debugStatusCode(statusCode); if (responseBody != null) { debugResponse(new String(responseBody)); } TLog.e(this, error.getMessage()); } @Override public void onProgress(int bytesWritten, int totalSize) { super.onProgress(bytesWritten, totalSize); } @Override public void onRetry(int retryNo) { makeText(String.format("Request is retried, retry no. %d", retryNo)); } }); } else if (view == mJsonButton) { url = "http://httpbin.org/headers"; mTAsyncHttpClient.get(this, url, null, null, new BaseJsonHttpResponseHandler () { @Override public void onStart() { } @Override public void onSuccess(int statusCode, Header[] headers, String rawJsonResponse, SampleJSON response) { debugHeaders(headers); debugStatusCode(statusCode); if (response != null) { debugResponse(rawJsonResponse); } } @Override public void onFailure(int statusCode, Header[] headers, Throwable throwable, String rawJsonData, SampleJSON errorResponse) { debugHeaders(headers); debugStatusCode(statusCode); debugThrowable(throwable); if (errorResponse != null) { debugResponse(rawJsonData); } } @Override protected SampleJSON parseResponse(String rawJsonData, boolean isFailure) throws Throwable { return null; // return new ObjectMapper().readValues( // new JsonFactory().createParser(rawJsonData), // SampleJSON.class).next(); } }); } else if (view == mLoginButton) { url = "http://myendpoint.com"; RequestParams params = new RequestParams(); params.put("username", "banketree"); params.put("password", "111111"); params.put("email", "[email protected]"); // params.put("profile_picture", new File("pic.jpg")); // Upload a // File // params.put("profile_picture2", someInputStream); // Upload // anInputStream // map = new HashMap (); // map.put("first_name", "James"); // map.put("last_name", "Smith"); // params.put("user", map); // * Set set = new HashSet (); // // unordered collection // * set.add("music"); // * set.add("art"); // * params.put("like", set); // url params: // "like=music&like=art" // // * List list = new ArrayList (); // // Ordered collection // * list.add("Java");<> // * list.add("C"); // * params.put("languages", list); // url params: // "languages[]=Java&languages[]=C" // // * String[] colors = { "blue", "yellow" }; // Ordered collection // * params.put("colors", colors); // url params: // "colors[]=blue&colors[]=yellow" // * // * List
此框架參考了ThinkAndroid,在寫此項目之前,筆者一直使用ThinkAndroid框架開發項目,所以很多思想來源於此。Think框架介紹如下:
ThinkAndroid是一個免費的開源的、簡易的、遵循Apache2開源協議發布的Android開發框架,其開發宗旨是簡單、快速的進行Android應用程序的開發,包含Android mvc、簡易sqlite orm、ioc模塊、封裝Android httpclitent的http模塊,具有快速構建文件緩存功能,無需考慮緩存文件的格式,都可以非常輕松的實現緩存,它還基於文件緩存模塊實現了圖片緩存功能,在android中加載的圖片的時候,對oom的問題,和對加載圖片錯位的問題都輕易解決。他還包括了一個手機開發中經常應用的實用工具類,如日志管理,配置文件管理,android下載器模塊,網絡切換檢測等等工具。
下載地址:https://github.com/white-cat/ThinkAndroid
項目下載
首先apk不能被代碼混淆(或未經編譯優化),如果混淆了,反編譯出來的代號還是看不懂, 當然,在你沒反編譯出來之前,你也不知道有沒有混淆。 網上各種反編譯工具,&
本實例實現每隔5秒上傳一次,通過服務器端獲取手機上傳過來的文件信息並做相應處理;采用Android+Struts2技術。一、Android端實現文件上傳1)、新建一個An
上一節的顯示賬單明細 上中,賬單明細的顯示已經基本實現,本文主要整理下代碼,實現此窗口的查詢和刪除功能;按下Menu菜單
百度google大家多說的是任務管理器 kill掉adb 或者重啟adb server,但我任務管理器就沒有adb ,猜測是某個程序占用了adb端口。於是按此思路查找。5
作為一名Android開發者,相信你對Android方法數不能超過65K