2013-09-08

將純文字檔案讀取成String的快速流程

這方法從stackoverflow看到[參考網址],怕忘記,紀錄一下

這方法完全用java標準library,非常方便:
static String convertStreamToString(java.io.InputStream is) {
    java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
    return s.hasNext() ? s.next() : "";
}

以上為原始範例,直接貼上在大部分情況就可以使用,但如果需要處理中文檔案,回文有提到部分改善方式,使用加入UTF-8的constructor,變成像這樣:

//Path→File→FileInputStream fIn,最後需要一個try/catch,非常瑣碎.....
BufferedInputStream bIn = new BufferedInputStream(fIn); //預設buffer=8192
Scanner scanner = new Scanner(bIn, "UTF-8").useDelimiter("\\A");
String content = scanner.hasNext() ? scanner.next() : "";
scanner.close();

目前存取超過8192字元文件正常,繼續測試中。





2013-07-23

簡易版Android Studio導入外部library流程

以下用gson-2.2.4.jar測試:

(1) 複製.jar到要導入的Module目錄下,Android Studio會自動抓到對應檔案:


(2) 在Android Studio的Project視窗中,右鍵點.jar,選add as library

(3) 隨便要取甚麼名字,不贅述,然後開啟Module內的build.gradle,在dependencies中加入這段(.jar的檔名可以從左邊copy...):
compile files('/libs/gson-2.2.4.jar')

[  至此已經可以正常使用,以下為選用流程,自行參考  ]

(4) 對整個專案做一次cleanup的build (是在Project的目錄下,非Module)


(5) 如果多個檔案要加入,有些比較快的輸入格式,對整個樹枝狀目錄或複數檔案
compile fileTree(dir: 'libs', include: '*.jar')
compile files('libs/001.jar', 'libs/002.jar')

(6) 有個建議是說可以透過mavenCentral()網路下載進行compile,取代掉compile files那段,改成:
compile 'com.google.code.gson:gson:2.2.4'
目前透過(6) compile正常使用中

2013-07-19

有關Layout

一些檢視自己Layout的數量:
1. ViewGroup不要超過10層
2. View總數不要超過80

一些提升效率的方法:
1. 無用的外框改用<merge>取代,常跟<include>搭配  (這邊我實作成fragment還有問題)
2. 使用<stub>預設是不繪製UI,但可以findViewById => setVisbility,設定為可見才開始繪製

(還正在K書中,龜速補充...)

來源:Professional Android 4 Application Development 這本書

2013-07-13

Android Studio編譯時因為編碼問題產生的錯誤

使用Android Studio 0.1 - 0.2這段期間,因為gradle預設是使用MS950編碼,所以常常會有明明都沒顯示error,卻在debug時跑出一堆根本不知道哪來的error/warning

查了一下發現已經有日本人回報了,也有人回應對應的做法:
在build.gradle中加入這段(是要module中的那個,也就是接著目錄src下面的那個,修改最外層那個comment說是top-level的是沒用的!)
tasks.withType(Compile) {
    options.encoding = "UTF-8"
}


基本上改掉這個之後,debug就完全不會有顯示出亂碼的問題了,這部分好像也可以在設定中的File and Code Templates項目→Templates→Gradle File修改預設模板,以後新增Module應該都會直接套用上。




xml參數設定研究

AndroidManifest.xml:
<manifest>:
android:versionCode - 內部的版本號,整數,通常每次+1
android:versionName - 顯示給客戶端看的版本號,自訂,例如0.1beta
android:installLocation - 軟體安裝位置,選擇"internalOnly"強制使用內部空間(Widget、Live Wallpaper、App with ongoing Services、輸入法、裝置管理與接收器建議使用這個),其他選項有"preferExternal"或"auto"。
<activity>:
android:screenOrientation - 設定此Activity的方向,通常用來強制landscape或portrait
android:lunchMode - 執行模式,設定singleTask可確保永遠只會執行同一個Activity,不論透過何種方式呼叫。
要設定強制橫屏/豎屏就是設置以上兩個,當然也可以寫在code中,在onResume中設定setRequestOrientation,但我比較喜歡寫在xml中,系統一開始就決定是橫向,不會讓使用者執行之後看到一下豎屏才轉橫(同理,我也比較喜歡把隱藏標題列等設定寫在xml中)
android:theme - 就是整個activity的主要造型,這很容易懂,但有個有趣的衍伸作法,在官方Dialog的文件中有個提示,如果要建立一個自訂內容(setView)的Dialog,其實有個作法是直接把它當成一個Activity來作,最後把這個Activity的theme設定成Dialog:
<activity android:theme="@android:style/Theme.Holo.Dialog" >
算是theme很有趣的應用方法。


style.xml:
這部分的設定如果使用系統內建的,也可以直接在Manifest中指定,但最好還是獨立出來寫,比較不會混淆。
<style>:
parent - 繼承內建的theme開始修改,例如android:Theme.Holo.Light.NoActionBar,可以直接隱藏標題列。

layout類.xml:
android:id - 這屬性通常都是寫@+id/xxxxxx,可是在某些內建的元件使用時,是可以使用@android:id/的,例如自訂Dialog View時,就可以使用@android:id/message以及@android:id/title,如此builder的method就可以同樣應用上來。

讀取資源檔時產生NullPointerException

原本想把專案中各class的TAG還有常數統一整理成資源檔,讓整個架構更有層次感,像是這樣:
public class Main extends Activity{
    final private static String TAG = getString(R.string.tag_main);
    ..........
    ..........
但在修改之後卻連onCreate都進不去就掛了。

研究了好幾個小時才了解,原來getString這個function實際上是Context.getResouce().getString(),也就是說在Activity 初始化之前(super.onCreate),"基本上"是不可以調用getString來取得資源檔的字串,當然是有些取得的方法啦,參考的是這篇:

http://stackoverflow.com/questions/6261990/strange-nullpointerexception

基本上就是要先建立一個Activity extends Application作為接口,然後在Main取得資源檔前先調用這個class,大致上步驟如下:
(1)在AndroidManiifest.xml中新增一個application:
<manifest ...>
    ...
    <application  android:name="com.mypackage.MyApplication" ... >
       ...
    </application>
    ...

</manifest>

(2)建立對應的MyApplication.java,並且把getString寫入:
public class MyApplication extends Application
{
    private static MyApplication s_instance;

    public MyApplication ()
    {
        s_instance = this;
    }

    public static Context getContext()
    {
        return s_instance;
    }

    public static String getString(int resId)
    {
        return getContext().getString(resId);    
    }

}

(3)從原Main中調用MyApplication.getString方法:
private final String TAG = MyApplication.getString(R.string.tag_main);
看到這邊,我決定....直接把TAG hardhoding在上面了(死).....