標籤:android 基礎 筆記 開發
- 測試的相關概念
- Android中的單元測試
- 日誌貓的介紹
- 登陸案例
- 把資料儲存到SD卡上
- Android中幾個常用的目錄
- 擷取SD卡的大小及可用空間
- 檔案許可權的概念
- SharedPreferences使用
- Android官方推薦的產生XML的方式
- Android官方推薦的解析XML的方式
測試的相關概念
好的程式不是開發出來的,是測試出來的。
-
根據是否知道來源程式源碼:
-
黑箱測試:不知源碼,只是測試程式的功能
-
白盒測試:知道源碼,根據原始碼進行測試
-
根據測試的粒度:(模組的大小)
-
單元測試:unit test
-
功能測試:function test
-
整合測試:integration test :幾個模組的測試,伺服器/用戶端的聯調
-
系統測試:system test: JavaEE企業級開發中常常用到
-
根據測試的次數:(暴力測試)
-
① 煙霧測試 (Smoke Test):smoke test,不停的執行操作,直到系統崩潰
-
② 猴子測試,測試方法如下
-
Adb shell:進入模擬器目錄,monkey 2000,通過monkey是隨機點擊2000次
# monkey –p 包名 次數:只測試某個應用程式adb shellmonkey -p com.bzh.beijingwisdom 2000
-
③ 壓力測試:pressure test
Android中的單元測試
-
手動增加單元測試的步驟
-
① 寫一個類繼承
AndroidTestCase
-
② 在資訊清單檔中增加指令集
<instrumentation android:name="android.test.InstrumentationTestRunner" android:targetPackage="程式包名" ></instrumentation>
-
③ 在資訊清單檔下的application節點下增加測試庫
<uses-library android:name="android.test.runner"/>
-
建立Android測試工程進行測試
-
建立工程
-
建立後的資訊清單檔
日誌貓的介紹
-
Android LogCat的擷取有兩種方式:
-
1、DDMS提供的LogCat視圖
-
2、通過adb命令列
-
DDMS提供的LogCat視圖如下
-
① 如果該視圖沒有開啟,點擊window->showview->other->android->Logcat來進行選擇
-
② 視圖的左側可以選擇或者添加過濾資訊,運行一個應用程式時,此處會預設建立一個該包的過濾。視圖的右上方地區用於選擇LogCat的log層級,共有verbose、debug、info、warn、error、assert6個可選項。:
-
③該視圖的主體部分是log的詳細資料,包括錯誤層級(Level)、時間(Time)、進程ID(PID)、線程ID(TID)、應用程式套件組合名(Application)、標籤(Tag)、日誌本文(Text)。
其中的TID並不等同於Java中的Thread.currentThread().getId(),而是我們Linux中的Thread ID,跟PID相同。
-
LogCat日誌的層級及使用
-
android.util.Log常用的方法有以下5個:
-
Log.v() Log.d() Log.i() Log.w() 以及 Log.e() 。
-
根據首字母對應VERBOSE,DEBUG,INFO, WARN,ERROR。
-
Log.v 的調試顏色為黑色的,任何訊息都會輸出,這裡的v代表verbose囉嗦的意思,平時使用就是Log.v(“”,”“);
-
Log.d的輸出顏色是藍色的,僅輸出debug調試的意思,但他會輸出上層的資訊,過濾起來可以通過DDMS的Logcat標籤來選擇.
-
Log.i的輸出為綠色,一般提示性的訊息information,它不會輸出Log.v和Log.d的資訊,但會顯示i、w和e的資訊,System.out輸出資訊是Info層級
-
Log.w的意思為橙色,可以看作為warning警告,一般需要我們注意最佳化Android代碼,同時選擇它後還會輸出Log.e的資訊。
-
Log.e為紅色,可以想到error錯誤,這裡僅顯示紅色的錯誤資訊,這些錯誤就需要我們認真的分析,查看棧的資訊了。
-
程式中我們可以使用Log類來輸出資訊
結果:
登陸案例
擷取/data/data/com.xxx.xxx/files路徑
String savePath = MainActivity.this.getFilesDir().getPath();
直接使用AndroidAPI擷取內部儲存路徑的輸入、輸出資料流
// 1FileInputStream fis = context.openFileInput("info3.txt");// 2FileOutputStream fos = context.openFileOutput("info3.txt", Context.MODE_PRIVATE);
把資料儲存到SD卡上
增加許可權
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
擷取SD卡的儲存路徑
String savePath = Environment.getExternalStorageDirectory().getPath();
Android中幾個常用的目錄
-
內部應用程式的預設檔案路徑
-
使用的API:
context.getFilesDir().getPath()
-
路徑:/data/data/com.itheima.getsdavail/files
// /data/data/com.itheima.getsdavail/filesLog.i(TAG, "內部應用程式的預設檔案目錄:" + getFilesDir().getPath());
-
內部應用程式的預設緩衝路徑
-
使用的API:
context.getCacheDir().getPath()
-
路徑:/data/data/com.itheima.getsdavail/cache
// /data/data/com.itheima.getsdavail/cacheLog.i(TAG, "內部應用程式的預設緩衝目錄:" + getCacheDir().getPath());
-
SD卡應用程式的預設檔案目錄
-
使用的API:
context.getExternalFilesDir(null).getPath()
-
路徑:/mnt/sdcard/Android/data/com.itheima.getsdavail/files
// /mnt/sdcard/Android/data/com.itheima.getsdavail/filesLog.i(TAG, "SD卡應用程式的預設檔案目錄:" + getExternalFilesDir(null).getPath());
-
SD卡應用程式的預設緩衝目錄
-
使用的API:
context.getExternalCacheDir().getPath()
-
路徑:/mnt/sdcard/Android/data/com.itheima.getsdavail/cache
// /mnt/sdcard/Android/data/com.itheima.getsdavail/cacheLog.i(TAG, "SD卡應用程式的預設緩衝目錄:" + getExternalCacheDir().getPath());
-
SD卡根路徑
-
使用的API:
Environment.getExternalStorageDirectory().getPath()
-
路徑:/mnt/sdcard
// /mnt/sdcardLog.i(TAG, "SD卡根路徑:" + Environment.getExternalStorageDirectory().getPath());
擷取SD卡的大小及可用空間
Andoird2.3版本以上的擷取方法
// 擷取到SD卡目錄File file = Environment.getExternalStorageDirectory();TextView tvTotal = (TextView) findViewById(R.id.tv_total);// 擷取SK卡目錄的總共空間大小,傳回值為long型 long totalSpace = file.getTotalSpace();// 使用AndroidAPI進行資料的格式化String total = Formatter.formatFileSize(this, totalSpace);tvTotal.setText(total);TextView tvAvail = (TextView) findViewById(R.id.tv_avail);// 擷取SK卡目錄的可用空間大小,傳回值為long型 long usableSpace = file.getUsableSpace();// 使用AndroidAPI進行資料的格式化String avail = Formatter.formatFileSize(this, usableSpace);tvAvail.setText(avail);
相容Andoird2.2版本的擷取方法
/*** 擷取手機外部可用空間大小 * * @return */public static long getAvailableExternalMemorySize() { // 判斷SD卡是否可用 if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) { // 擷取SD卡目錄 File path = Environment.getExternalStorageDirectory(); StatFs stat = new StatFs(path.getPath()); long blockSize = stat.getBlockSize(); long availableBlocks = stat.getAvailableBlocks(); return availableBlocks * blockSize; } else { throw new RuntimeException("Don‘t have sdcard."); }}
/** * 擷取手機外部空間大小 * * @return */public static long getTotalExternalMemorySize() { if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) { File path = Environment.getExternalStorageDirectory();// 擷取外部儲存目錄即 // SDCard StatFs stat = new StatFs(path.getPath()); long blockSize = stat.getBlockSize(); long totalBlocks = stat.getBlockCount(); return totalBlocks * blockSize; } else { throw new RuntimeException("Don‘t have sdcard."); }}
檔案許可權的概念
以下是一個典型linux下目錄檔案許可權圖
-
Linux下目錄檔案許可權由10位組成
-
第 1 位:
d為目錄,-為檔案
-
2 - 4位(目前使用者):
r為讀許可權,w為寫入權限,x 為可執行許可權
-
5 - 7位(目前使用者所在組):
r為讀許可權,w為寫入權限,x 為可執行許可權
-
8 - 10為(其他使用者):
r為讀許可權,w為寫入權限,x 為可執行許可權
簡圖如下
-
建立私人、追加、可讀、可寫入權限的檔案
-
主要是通過
context.openFileOutput()方法的第二個參數進行設定
-
①私人
-
代碼如下
public void Private(View v) throws Exception { FileOutputStream fos = context.openFileOutput("Private.txt", MODE_PRIVATE); fos.write("Private".getBytes()); fos.close();}
-
,可以看到私人的在其他使用者組中的許可權為
- - -
-
②可追加
-
代碼如下
FileOutputStream fos = openFileOutput("Append.txt", MODE_APPEND);fos.write("Append".getBytes());fos.close();
-
,可以看到可追加的在其他使用者組中的許可權為
- - -,與私人的一致,可追加和私人的許可權,並不能在檔案許可權中體現出來。
-
③可讀
-
代碼如下
FileOutputStream fos = openFileOutput("Read.txt", MODE_WORLD_READABLE);fos.write("Read".getBytes());fos.close();
-
,可以看到可讀的在其他使用者組中的許可權為
r - -
-
④可寫
-
代碼如下
FileOutputStream fos = openFileOutput("Write.txt", MODE_WORLD_WRITEABLE);fos.write("Write".getBytes());fos.close();
-
,可以看到可寫的在其他使用者組中的許可權為
- r -
SharedPreferences使用
-
使用步驟
-
① 通過內容相關的API擷取到SharedPreferences執行個體
SharedPreferences sp = getSharedPreferences("config", Context.MODE_PRIVATE);
-
② 通過SharedPreferences.Editor儲存資料
Editor editor = sp.edit();editor.putString("username", username);editor.putString("password", password);
-
③ 通過Editor提交資料
editor.commit();
-
④ 使用SharedPreferences執行個體對象擷取key對應的資料
String username = sp.getString("username", "");String password = sp.getString("password", "");
使用SharedPreferences建立的檔案如
可以看到使用SP隱藏檔,在內部應用程式目錄下建立了shared_prefs檔案夾,並在檔案夾下以指定的許可權,建立了一個XML檔案。
Android官方推薦的產生XML的方式
-
使用步驟
-
① 產生一個xml序列化器
-
② 設定序列化參數
-
③ 開始文檔
-
④ 產生根節點
-
⑤ 迴圈產生子節點元素
具體代碼如下,寫的有詳細注釋:
// 1. 產生一個xml序列化器XmlSerializer xmlSerializer = Xml.newSerializer();// 2. 設定序列化參數,參數1:xml檔案輸出資料流;參數2:xml檔案編碼格式FileOutputStream fos = openFileOutput("users.xml", Context.MODE_PRIVATE);xmlSerializer.setOutput(fos, "UTF-8");// 3. 開始文檔,參數1:XML文檔中第一行的encoding內容;參數2:是否是獨立的,不依賴約束xmlSerializer.startDocument("UTF-8", true);// 4. 產生users根節點xmlSerializer.startTag(null, "users");// 5. 迴圈產生user子節點元素for (User user : userList) { xmlSerializer.startTag(null, "user"); // 6. 設定標籤屬性 xmlSerializer.attribute(null, "id", user.getId()); // 7. 設定user屬性 xmlSerializer.startTag(null, "name"); xmlSerializer.text(user.getName()); xmlSerializer.endTag(null, "name"); // 8. 設定password屬性 xmlSerializer.startTag(null, "password"); xmlSerializer.text(user.getPassword()); xmlSerializer.endTag(null, "password"); xmlSerializer.endTag(null, "user");}xmlSerializer.endTag(null, "users");xmlSerializer.endDocument(); // 當文檔結束時,會把輸出資料流重新整理,所有資料輸出到檔案中。
序列化後的XML檔案如下:
Android官方推薦的解析XML的方式
-
使用步驟:
-
① 得到Xml解析器
-
② 得到Xml解析器參數
-
③ 擷取事件,XMLPull是類似於SAX的基於事件、一行一行解析的
-
④ 迴圈處理事件
-
⑤ 處理根節點、子節點、子節點元素等
代碼如下:
List<User> userList = null;User user = null;// 1. 得到Xml解析器XmlPullParser parser = Xml.newPullParser();// 2. 設定解析器InputStream in = getClass().getClassLoader().getResourceAsStream( "users.xml");// 參數1:解析的檔案流;參數2:解析XML的編碼格式parser.setInput(in, "UTF-8");// 3. 擷取事件,XMLPull是類似於SAX的基於事件、一行一行解析的int eventType = parser.getEventType();// 4. 迴圈處理事件while (eventType != XmlPullParser.END_DOCUMENT) { switch (eventType) { case XmlPullParser.START_TAG: if ("users".equals(parser.getName())) { // 根節點時,初始化集合 userList = new ArrayList<User>(); } else if ("user".equals(parser.getName())) { // 子項目時,初始化對象 user = new User(); // 擷取子項目中的屬性 String id = parser.getAttributeValue(0); user.setId(id); } else if ("name".equals(parser.getName())) { String name = parser.nextText(); user.setName(name); } else if ("password".equals(parser.getName())) { String password = parser.nextText(); user.setPassword(password); } break; case XmlPullParser.END_TAG: if ("user".equals(parser.getName())) { // 將元素添加到集合中 userList.add(user); } break; default: break; } eventType = parser.next();}System.out.println(userList.toString());
Android基礎筆記(二)