這個問題與路徑有關, 在函式庫的配合時,
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月8日 星期四
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);
搞定
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
錯誤:
1.確定是以ReadWrite的方式開啟的,
2.不應該要設定檔案夾或是檔案的權限, 因為這是在手機, 使用者是可能不會設定, 而且, 以前也不用,
搞了很久, 真是要去撞牆, 原來是權限忘了設:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
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結束後執行。
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結束後執行。
2011年11月8日 星期二
CharBuffer.toString() trap-Example: int32toHex
使用CharBuffer.toString()時, 要注意, 輸出的字串, 是從指標所在的位置開始寫的, 因此, 在輸出之前, 要加上: position(0), 如:
以下是一個範例, 將32位元有正負的整數, 傳成十六進位數字,
/**
* Convert 32 bits integer number to hex-decimal string
* @param num number to convert
* @return hex-decimal string
*/
public static String Int32ToHex(int num) {
final int BUFFER_SIZE=8;
final int BITS=32;
String pattern="0123456789ABCDEF";
CharBuffer digits=CharBuffer.allocate(BUFFER_SIZE);
int digit=0;
int ref=0x80000000;
int bitValue=0x8;
for(int i=0;i<BITS;++i) {
int offset=i%4;
if(offset==0 && i!=0) {
digits.append(pattern.charAt(digit));
digit=0;
bitValue=0x8;
}
if((num & ref)!=0) digit += bitValue;
bitValue >>= 1;
/***
* Notice that,
* 0x80000000(-2147483648) >> 1 is NOT 0x40000000, but 0xC0000000(-1073741824)
* (-->E0000000(536870912)-->F0000000(268435456)-->F8000000(-134217728))
* Always divide by 2, no matter positive or negative number
* and 0xFFFFFFFF(-1) >> 1 is NOT 0x7FFFFFFF, but still 0xFFFFFFFF
* For the positive integer, the bit operation is running just as expectation.
*/ if(ref==0x80000000) ref=0x40000000;
else ref >>= 1;
}
digits.append(pattern.charAt(digit));
digits.position(0);
return digits.toString();
}
以下是一個範例, 將32位元有正負的整數, 傳成十六進位數字,
/**
* Convert 32 bits integer number to hex-decimal string
* @param num number to convert
* @return hex-decimal string
*/
public static String Int32ToHex(int num) {
final int BUFFER_SIZE=8;
final int BITS=32;
String pattern="0123456789ABCDEF";
CharBuffer digits=CharBuffer.allocate(BUFFER_SIZE);
int digit=0;
int ref=0x80000000;
int bitValue=0x8;
for(int i=0;i<BITS;++i) {
int offset=i%4;
if(offset==0 && i!=0) {
digits.append(pattern.charAt(digit));
digit=0;
bitValue=0x8;
}
if((num & ref)!=0) digit += bitValue;
bitValue >>= 1;
/***
* Notice that,
* 0x80000000(-2147483648) >> 1 is NOT 0x40000000, but 0xC0000000(-1073741824)
* (-->E0000000(536870912)-->F0000000(268435456)-->F8000000(-134217728))
* Always divide by 2, no matter positive or negative number
* and 0xFFFFFFFF(-1) >> 1 is NOT 0x7FFFFFFF, but still 0xFFFFFFFF
* For the positive integer, the bit operation is running just as expectation.
*/ if(ref==0x80000000) ref=0x40000000;
else ref >>= 1;
}
digits.append(pattern.charAt(digit));
digits.position(0);
return digits.toString();
}
2011年11月3日 星期四
Spinner trap
發現spinner設定OnItemSelectedListener時, 會自動呼叫一次,
而且是選項0, 在網站上有找到類似的說法,
http://blog.csdn.net/androidbluetooth/article/details/6670153
結果解決的方法, 有點怪異,
原來是,
spinner.setSelection(itemID);
spinner.setOnItemSelectedListener(...);
結果在執行時, 會自動呼叫listener, 傳入的選項是0,
將這兩行交換,
先設定Listener, 再設定選項,
一切就OK了 !!
而且是選項0, 在網站上有找到類似的說法,
http://blog.csdn.net/androidbluetooth/article/details/6670153
結果解決的方法, 有點怪異,
原來是,
spinner.setSelection(itemID);
spinner.setOnItemSelectedListener(...);
結果在執行時, 會自動呼叫listener, 傳入的選項是0,
將這兩行交換,
先設定Listener, 再設定選項,
一切就OK了 !!
2011年11月2日 星期三
reference link
在Java 中都是用物件的連結,
例如:
Date a;
Date b=a;
則常a的值改變時,b也會跟著變,
此時, 用以下兩個指令:
(1) a=new Date(); 和
(2) a.setTime(new Date().getTime());
將會有不一樣的效果,
用前者, 則中斷了b 與 a 的連結, 原來, b 指向 a 的位址, 但是new 指令, 結束了 a 原來的位址, 而產生了一個新的位址(與本體), 因此, a, b 成為獨立的兩個變數.
進一步地探討, 如果:
a=b;
c=a;
那麼b-->a-->c 三個會連動, 但是如果,
a=b;
b=c;
則 a 將獨立, 而b,c 連動.
這一點在函數傳遞時也有影響,
a=null;
func(a); 在執行時, a 改變了, 外面的a 是不會變的, 但是如果
Date a;
func(a);
如果在函數中, 使用 a=b, 則連動就結束了,
但如果用a.setTime(...), 那函數結束後, a 的值也改了,
但如果用 b=a, 那a, b 就會連動,
有趣!!
例如:
Date a;
Date b=a;
則常a的值改變時,b也會跟著變,
此時, 用以下兩個指令:
(1) a=new Date(); 和
(2) a.setTime(new Date().getTime());
將會有不一樣的效果,
用前者, 則中斷了b 與 a 的連結, 原來, b 指向 a 的位址, 但是new 指令, 結束了 a 原來的位址, 而產生了一個新的位址(與本體), 因此, a, b 成為獨立的兩個變數.
進一步地探討, 如果:
a=b;
c=a;
那麼b-->a-->c 三個會連動, 但是如果,
a=b;
b=c;
則 a 將獨立, 而b,c 連動.
這一點在函數傳遞時也有影響,
a=null;
func(a); 在執行時, a 改變了, 外面的a 是不會變的, 但是如果
Date a;
func(a);
如果在函數中, 使用 a=b, 則連動就結束了,
但如果用a.setTime(...), 那函數結束後, a 的值也改了,
但如果用 b=a, 那a, b 就會連動,
有趣!!
訂閱:
文章 (Atom)