網頁

顯示具有 Android教學 標籤的文章。 顯示所有文章
顯示具有 Android教學 標籤的文章。 顯示所有文章

2010年6月23日 星期三

關於介面與執行序Only the original thread that created a view hierarchy can touch its views.

Android 是一個多功多執行的作業系統,雖然可以多執行緒
但是遵循著mvc模式 ,所以當非UI的執行序,嘗試去改變ui介面的程式就會出現錯誤而關閉程式
例如

寫了一個遊戲,遊戲的核心是一個執行緒,定期需要計算遊戲的內容,且需要定時的更新畫面,然而跟跟新畫面,需要呼叫 invalidate 這個方法,偏偏這個方法使會變更介面,所以android只好把你強迫關閉程式。告訴你Only the original thread that created a view hierarchy can touch its views

最簡單的方法就是不要使用 invalidate 改用 postInvalidate();

但只是剛好invalidate 有 postInvalidate(); 可以幫助更新畫面,但是如果要更變tTextBox內容,或是 setContentView(view); 那可就沒那麼幸運了。

事實上這樣龜毛的規則並不是Android訂製的,c#的開發使用者也是有著相同的困腦,
但在c# 會使用委派來將 要改變介面的事情 透過委派 交給 UI的執行序去執行。

然而在Android 使用了比較值覺得寫法
runOnUiThread(new Runnable(){
public void run() {
//要改變介面的程式寫在這裡
}});

這樣android就會裡面的程式碼,改由ui的執行序來執行,而不會出錯了,
所以類推本來寫postInvalidate(); 可以改寫成

runOnUiThread(new Runnable(){
public void run() {
invalidate
}});



通常錯誤如下:
06-23 15:47:40.123: ERROR/AndroidRuntime(393): Uncaught handler: thread Thread-10 exiting due to uncaught exception
06-23 15:47:40.135: ERROR/AndroidRuntime(393): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

2010年6月19日 星期六

Android 常用小技巧

//全螢幕
貼再 Activity 的onCreate
requestWindowFeature(Window.FEATURE_NO_TITLE);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN , WindowManager.LayoutParams.FLAG_FULLSCREEN);


//強迫橫銀幕
在AndroidManifest.xml 中的 的 activity 屬性宣告


軟貓玩具
http://www.blogger.com/

//開啟使用網路權限
在AndroidManifest.xml 中的加入


//不讓手機自動進入休眠,持續背光
1.先在
在AndroidManifest.xml 中的加入


2.在程式中宣告
private PowerManager.WakeLock mWakeLock = mPowerManager.newWakeLock(mPowerManager.SCREEN_BRIGHT_WAKE_LOCK, "BackLight");
啟動持續背光模式
mWakeLock.acquire(); 通常加在 protected void onResume() 要不然
離開程式返回的時候效果就消失了

關閉持續背光
mWakeLock.release(); 通常加在 protected void onPause()
否則程式離開程式之後手機一直耗電

//使用GPS
在AndroidManifest.xml 中的加入



程式中宣告
LocationManager locationManger = (LocationManager)getSystemService(Context.LOCATION_SERVICE);

註冊gps 觸發事件為 LocationListener
locationManger.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, LocationListener); //1000ms 跟新一次 時間越短越耗電

private final LocationListener LocationListener = new LocationListener()
{

@Override
public void onLocationChanged(Location location)
//GPS移動的時候
@Override
public void onProviderDisabled(String provider)
@Override
public void onProviderEnabled(String provider)

@Override
public void onStatusChanged(String provider, int status, Bundle extras)
//gps定位完成沒偵測
};

2009年12月2日 星期三

Android 令人振奮的消息

中華電信延期太久遲遲不能跟google合作收費機制購買market上的軟體,
中華電信 和 遠傳電信 決定自己開設自己的 market(app store) 這兩家無獨有偶的都賣Android 和 windows moblie 軟體 (新聞網址) (遠傳s市集)
未來三年智慧行手機,將會達到市占率50%, 智慧手機,所以國內電信業者對於軟體的銷售也是非常積極投入,搶這塊大餅。
google 之前都是用佛心在經營market 所以下載收費軟體的人太少了,寫andorid的程式就像在做公益一樣,後來GameLoft因為andfroid 實在太佛心了賺不到錢,所以乾脆退出不玩了(http://android.cool3c.com/article/14446),這樣的消息無疑對開發者是一個疑慮,
大廠都不看好這個市場了,前景非常不樂觀。
現在中華電信 和遠傳電信推出這個收費平台,這代表開發者們我們辛苦的程式有機會回收實質的金錢效應,只要將我們開發的軟體放到這兩家平台上銷售,就可以得到 70%營收的回饋,
當然不是隨便寫寫就可以賺錢,拿android的玩家都是3C達人不是笨蛋,他們一定會去android market 那個佛心市場找找軟體,找到免費的為什麼還要花錢,所以眼前的競爭對手很明確就是要比market上的免費軟體來的實用,方便,好玩 ,新奇。

雖然失去了market的全球市場,不過這總是一個跳板機會,未來android market全球市場是否能夠興起付費軟體不確定,不過短期內google checkout收費機 應該是不會登入台灣,先把軟體開發在台灣這個市場測試自己的軟體,也營收一些金錢讓自己的辛苦有直接的回饋,不能餬口也喝口湯。
我是軟貓玩具(http://toimy.blogspot.com/)
或許你們會以為我是在幫這兩家電信打廣告,其實寫這個文章的理由是因為一個巴掌打不響,我也是一個軟體開發者,曾經在java game上賺過一些小錢但是大部分都被廠商抽走,自己只有回收15-20%,為什麼邀請大家一起來開發,這樣不是搶我自己的市場,答案是否定的,因為當這兩家電信上面的APP夠多,才會掀起使用習慣,國人自然習慣來這裡就是會找到比market上更多好用的軟體也甘願付費,現在的遠傳上面的軟體遊戲根本不到20個,程式加一加不到兩百個,如果我有android 一點都不想上去逛,沒有新軟體沒有什麼新意,更別說下載......,越多人開發雖然競爭的人多,但是下載人數更多:所以大家一起來開發,大家一起賺錢才能夠把這個遊戲規則建立起來,一起來寫Android 吧。

2009年10月1日 星期四

Android教學程式設計-音樂撥放第一彈 MediaPlayer

Android程式設計-音樂撥放第一彈 MediaPlayer
Android播放音樂很簡單,在SDK裡簡單了說明了如果要撥放音樂只需要簡單的程式即可達到撥放的功能,
可以播放mp3 wav AAC格式,播放資源檔裡的音樂只需要兩行
MediaPlayer mp = MediaPlayer.create(context, R.raw.檔名);
mp.start();

哇這麼簡單阿,那趕快來試試看,但是怎麼把音樂放到資源檔裡面呢,很簡單
只要打開程式專案的資料夾,例如我的專案放在
D:\Android\Code\Music1
打開資料夾,看到res資料夾,裡面就擺放著所有資源檔,
進入res資料夾,注意音樂或是音效統一要放在raw資料夾下面
預設是沒有這個資料夾的,所以我們建立raw資料夾,並將音樂檔案複製到這個資料夾下方
完成之後回到Eclipse,我們並沒有看到該檔案存在res下,那是因為還沒更新,
只要點選右鍵選擇Refresh,就會發現加到資源檔裡,例如我加入的是Hony.mp3
程式只要寫下
MediaPlayer mp = MediaPlayer.create(context, R.raw.Hony);
mp.start();

但是你會發現,奇怪為什麼R.raw. ? 沒有發現Hony這個檔案
這是因為R.java 不接受res檔名, 注意這裡很容易出錯
res下方的檔案名稱,只接受小寫的英文字母,和數字,不接受任何大寫的檔案
更別說中文名稱的檔案了,甚至數字開頭的檔案名稱他也不吃,這是需要注意的
將檔名改成hony.mp3後在點選 refresh 就可以看到hony.mp3 加到資源檔了.如果想要播放sd卡裡的音樂呢?
SDK寫
MediaPlayer mp = new MediaPlayer();
mp.setDataSource("路徑");
mp.prepare();
mp.start();
但實際把程式貼到Eclipse
mp.setDataSource("路徑");
mp.prepare();
會出現surround with try/catch
因為讀取了SD卡可能會有錯誤,所以要加入如果讀取錯誤該怎麼處理錯誤的
最少要寫成這樣才能執行
MediaPlayer mp = new MediaPlayer();
try {
mp.setDataSource("路徑");
mp.prepare();
} catch (IllegalArgumentException e) {
} catch (IllegalStateException e) {
} catch (IOException e) {
}
mp.start();

現在還不知道路徑是什麼,簡單介紹一下Android為linux系統,Linux與windows系統的檔案系統有觀念上得不同
就是linux 的每個一個資料夾或是檔案,都是有權限的,最大權限的那個帳號叫做root,這個帳號可以對所有檔案進行
刪除或變更,但是我們並不是這個帳號,我們只是一般使用者,所以Android 上得大部分的檔案我們都沒有權限取存他

如果程式要存取檔案之前,都必需要有足夠的權限喔,模擬器現在有三大資料夾Data,SDcare,system
data 我們可以存取,但是sdcare為什麼不行喔,這真的很奇怪(因為建立AVD的時候沒有給予sd卡空間)(sdcard 的 permissions 只有d--------- 表示,沒有建立sdcard,所以不可以上傳任何資料)
但是怎麼把檔案上傳到模擬器的SD卡裡面呢?這裡有兩個問題,第一個問題,模擬器要模擬SD卡,所以在AVD設定時就要設定了,如下圖
第二個問題怎麼上傳。
第一步 設定一個擁有64M的模擬器
這樣我們的模擬器就有64M的 SD卡了
第二步 怎麼上傳檔案到模擬器呢,我們需要DDMS的幫助
DDMS簡單說,他是幫我們控制模擬器的程式,例如你需要模擬程式進行過程當中,有一通電話撥進來
或是程式執行時,有一通簡訊進來了,或是呢現在GPS的訊號是在經緯度多少,這一方面的手機控制,都是透過 DDMS
不過DDMS不只有這些功能,他主要幫助Debug的工具,所以需要和他博一些感情。
啟動DDMS在IDE的這個地方
然後我們透過DDMS這個按鈕將檔案上傳到sdcard裡面,注意上傳之前,如下圖在sdcard上點一下,
讓他呈現反白,如果沒有點選他,上傳的圖示就沒有作用.
目前我們只能傳到sdcard 還不能建立目錄,因為ddms並沒有很完整的檔案管理介面,所以下一章節我會介紹一下如何管理
還有這個章節如果一直沒有辦法把檔案傳道sdcard 那就先傳到data下面也可以,只是撥放路徑要改就可以,
看過下一章節或許比較可以控制模擬器上的檔案
上傳完成之後
我們把程式碼的路徑 改成 \sdcard\test.mp3
啟動程式, ㄟ ,美妙的音樂傳了出來, 真是感動阿

4: import java.io.IOException;

6: import android.app.Activity;
7: import android.media.MediaPlayer;
8: import android.os.Bundle;

10: public class Music1 extends Activity {
11: /** Called when the activity is first created. */
12: @Override
13: public void onCreate(Bundle savedInstanceState) {
14: super.onCreate(savedInstanceState);
15: setContentView(R.layout.main);
16: MediaPlayer mp = new MediaPlayer();
17: try {
18: mp.setDataSource("/sdcard/test.mp3");
19: mp.prepare();
20: } catch (IllegalArgumentException e) {
21: } catch (IllegalStateException e) {
22: } catch (IOException e) {
23: }
24: mp.start();
25: }
26: }


為什麼說很感動呢?因為其實為了撥放出這一段音樂, 我花了超過四個小時的時間尋找和探索如何把檔案上傳到sdcard 還有我一直以為路徑要寫成 file:\\\sdcard\test.mp3
錯誤連連,所以新手們,程式碼一直錯誤別害怕,這個都是因為我們還不習慣這個程式語言
不習慣這個介面,只要我們多摸他,多了解他的習性, 還是可以做出來,堅持的動力是因為
有很多人都走過向我們證明一定可以辦的到,只是需要熟悉 ,美妙的聲音 多Run幾次 真爽
雖然只有幾行的程式碼.