2012年1月6日 星期五

eclipse找不到HTC Desire

使用HTC開發程式, 可是 Windows | View | Device 看不到我可愛的HTC Device, 該安裝的都安裝了, 手機也沒有問題, 因為手機接在另一台 Win7 的電腦上時, 可以正常debug 程式, 在網上爬,...過程就不說了, 結果是, 在安裝移除程式, 把HTC的三個驅動都移除, 然後重新安裝.....OK,搞定 (移除前後, 看安裝移除程式,一個樣,看不出有何不同)

 

2012年1月3日 星期二

proguard and drawable not found

加上proguard後, 有一些resource/drawable找不到了, 因為, 在程式中是使用字串名稱去反查圖檔, 經過了 proguard, 名稱換了, 就找不到了, 有趣的是, 在apk中, 檔案都在, 名稱也沒有換, 看起來, proguard有作一個對照檔。怎麼辦? 在 proguard.cfg 加上幾行
-keepclassmembers class **.R$* {
    public static int back;
    public static int log;
    public static int click;
}
搞定 !!
這也讓我思考,是否有必要保留以名稱來找圖檔。

proguard

使用混淆器,proguard
1.從R12之後, default.properties 改名為 project.properties
2.project.properties的檔頭上說:
檔案上說 "Do not modify this files",不要理他,加上一行
proguard.config = proguard.cfg
也可以加上路徑 ".\proguard.cfg" 或是絕對路徑。
3.要Export Package才起作用(專案|右鍵Android Tools)

4.用新版的proguard
   原先的錯誤是
   爬文,說proguard不支援路徑中帶有空白字元,要修改SDK location,
   又說,修改 android-sdk路徑下,proguard路徑下,proguard.bat,
   將 %* 改成 %1,%2,...,%9,...看到一篇說,改成新版的progrard就好,       
   試著下載新版(4.7),解壓縮,直接覆蓋到adroid-sdk下之proguard,
   搞定。
中間還有一個插曲,使用Export unsigned..產生的APK複製到我的HTC Desire手機,無法安裝,但是使用Export signed就好了,APK檔案,從756K 降至 568K, BinGo!

別忘了,將專案下,proguard路徑下的對照檔,與產生的APK放在一起,以備偵錯使用。

2011年12月8日 星期四

AIDL, couldn't find import for class sni.lib.Note.GestureOperation

這個問題與路徑有關, 在函式庫的配合時,
sni.lib.Note..........class GestureOperation
com.sni.Note.......package to host the Service
sni.lib.Page..........package as Client to link the Service

製作了一個AIDL在com.sni.Note,
package com.sni.Note;
import com.sni.Note.GestureOperation;
interface INoteService {
 GestureOperation[] getOperations();
 }
出現
couldn't find import for class sni.lib.Note.GestureOperation
的錯誤,

然後, 加上GestureOperation.aidl的AIDL檔:
parcelable GestureOperation;
原來的錯誤沒有了,
但是所產生(gen)的java檔報錯,
GestureOperation cannot be resolved to a type
並要求import,
如果用了import, 那就違反了檔頭所說的:
* This file is auto-generated.  DO NOT MODIFY.
這是因為 GestureOperation.aidl 和GestureOperation.java不在一起,
怎麼辦?

將GestureOperation.aidl移至sni.lib.Note, 讓他們生活在一起,
當然, import的路徑要改,
import com.sni.Note.GestureOperation
結果, 原來import的錯誤又回來了,
如果在GestureOperation前加上package, 如:
package sni.lib.Note;
parcelable GestureOperation;
結果出現新的錯誤:
interface GestureOperation should be declared in a file called sni\lib\Note\GestureOperation.aidl.

所以, 暫時看起來沒有解, 有網路文章說, 與路徑有關, 就是GestureOperation放到sni.lib.Note, 但是 aidl compiler找不到, 目前有一個解, 是可以用, 但是如果有多個class要同時使用時, 就要費一點腦子,
sni.lib.Note .............. 放 GestureOperation (java & aidl), INoteGesture.aidl
com.sni.Note ........... 定義Service, 這是因為所需的資料在這個類別裡,
sni.lib.Page .............. 執行 bindService
這樣子, 是可以正常執行的, 因為
INoteGesture ..... GestureOpeartion.aidl ....... GestureOperation.java
都在一起, 避開了路徑的問題

另外在Serivce, action的定義名稱是自取的, 可以與package名稱不相干.

在bindService時也出現錯誤, (回傳 false), 這是因為在GroupActivity底下的Activity是無法使用bindService, 在我的個案中, 使用
getApplicationContext().bindService 依然不行, 但是使用
getParent().bindService就可以了, 這個在網路上有比較完整的討論,
http://blog.tourizo.com/2009/04/binding-services-while-in-activitygroup.html
http://randomizedsort.blogspot.com/2010/11/service-binding-workaround-in-tab.html

還有一點必須注意的是, bindService傳回true, 不代表就可以使用service interface, 必須等onConnection完成. 這是容易理解.



2011年12月6日 星期二

getLaunchIntentForPackage return null

1.確定被呼叫的APP有安裝 (getInstalledPackage)
2.確定被呼叫的APP可以正常執行 (MAIN, LAUNCHER有設定)
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
可是....就是回傳null,

結果發現是:
    <data android:scheme="id" />
在作怪, 只要有這一行, 就回傳null, 換句話說, 若是有 data/scheme就不能用getLauncherForPackage,

所以, 就改用 setClass
     Intent intent = new Intent(Intent.ACTION_MAIN);
     intent.setClassName(packageName, activityName);
     intent.setData(Uri.parse("id://"+id));
     startActivity(intent);
搞定

attempt to write a readonly database

錯誤:
12-06 10:16:43.523: E/AndroidRuntime(286): java.lang.RuntimeException: Unable to start activity ComponentInfo{sni.Note.Comm/sni.Note.Comm.CommActivity}: android.database.sqlite.SQLiteException: attempt to write a readonly database: BEGIN EXCLUSIVE;

1.確定是以ReadWrite的方式開啟的,
2.不應該要設定檔案夾或是檔案的權限, 因為這是在手機, 使用者是可能不會設定, 而且, 以前也不用,

搞了很久, 真是要去撞牆, 原來是權限忘了設:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

2011年11月13日 星期日

AsyncTask & notifyDataChanged

adapter 的notifyDataChanged()必須在UI thread 中呼叫, 如果不是, 例如, 如果在adapter中, 自行呼叫 notifyDataChanged() 將會造成許多問題, 例如, 按鍵無法接受。在我的個案中,按鍵無法接受,不管是長按或是短按,但是,滑動光學滑鼠之後,就正常了,查網,的確有這個問題。
http://stackoverflow.com/questions/4566101/how-to-fix-notifydatasetchanged-listview-problems-in-dynamic-adapter-wrapper-and

解決的方法是使用AsyncTask, 例如:
 class AppendTask extends AsyncTask<Integer, Float, Exception> {
    @Override
    protected void onPreExecute() {
    ... run in UI thread
 
 
 return float-value; 
    }
    @Override
    protected Exception doInBackground(Integer... params) {
    ...
    ... run in WORKING thread
    ...publishProgress(a,b,c);
    }
 
 @Override
     protected void onProgressUpdate(Float progress) {
     ...run in UI thread
     }
    @Override
    protected void onPostExecute(Exception e) {
     ... run in UI thread
  }
  AsyncTask 的三個參數中,第一個參數(Integer), 是doInBackground()的輸入參數類別,是不定個數的參數。第二個參數(Float) 是onProgressUpdate的輸入參數類別,也是不定個數。第三個參數(如例中之Exception)則為doInBackground的傳回值類別,也是onPostExecute()的輸入類別。
四個函數,只有doInBackground在Working thread(沒有UI的thread)中執行,onPreExecute()第一個被執行,接著就執行doInBackground(), 這是不能省略的函數,在函數中可呼叫(也可以不呼叫)onProgressUpdate一次或多次。onPostExecute()則是在doInBackground結束後執行。