編輯:關於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 = "banketree@qq.com";
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", "banketree@qq.com");
// 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
項目下載
Android apk反編譯工具介紹
首先apk不能被代碼混淆(或未經編譯優化),如果混淆了,反編譯出來的代號還是看不懂, 當然,在你沒反編譯出來之前,你也不知道有沒有混淆。 網上各種反編譯工具,&
Android實現上傳文件到服務器實例詳解
本實例實現每隔5秒上傳一次,通過服務器端獲取手機上傳過來的文件信息並做相應處理;采用Android+Struts2技術。一、Android端實現文件上傳1)、新建一個An
Android 個人理財工具六:顯示賬單明細 下
上一節的顯示賬單明細 上中,賬單明細的顯示已經基本實現,本文主要整理下代碼,實現此窗口的查詢和刪除功能;按下Menu菜單
Android開發adb.exe and can be executed.錯誤解決方法
百度google大家多說的是任務管理器 kill掉adb 或者重啟adb server,但我任務管理器就沒有adb ,猜測是某個程序占用了adb端口。於是按此思路查找。5
android Unable toexecute dex: method ID not in [0, 0xffff]: 65536問題
作為一名Android開發者,相信你對Android方法數不能超過65K