這篇文章可能會有點多,但是因為這兩個禮拜可能會很忙,
所以先留著接口(interface?哈哈)之後補。
首先這是廣播註冊、送出與監聽的方法,專案檔下載在這裡。
貼上主要的程式碼:
package com.example.broadcastTest;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
/** 測試broadcast */
public class MainActivity extends Activity {
final String TAG = getClass().getSimpleName();
Button button;
TextView textView;
// 這裡用static 是為了thread用途,建議如果夠大的話,用Service包起來
static boolean threadIsStop;
final String ACTION_BROAD_CAST = "susanTestYAHU";
final String KEY_INTENT_SIMPLE = "intent用的key值";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.text_show);
button = (Button) findViewById(R.id.button1);
// 一個開關的設置
if (threadIsStop) {
button.setText(R.string.lb_switch_turnOn);
} else {
button.setText(R.string.lb_switch_turnOff);
}
button.setTag(threadIsStop);
button.setOnClickListener(mOnClickListener);
}
OnClickListener mOnClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
boolean onThread = (Boolean) button.getTag();
if (onThread) {
// 關閉程序
threadIsStop = true;
button.setTag(false);
button.setText(R.string.lb_switch_turnOn);
} else {
// 開啟程序
button.setText(R.string.lb_switch_turnOff);
threadIsStop = false;
startThread();
// FIXME 這個demo可能會有thread不同步的問題,不過不是主要的目的所以不管
button.setTag(true);
}// end if
}// end onClick
};
@Override
protected void onResume() {
// 註冊監聽器
IntentFilter mIntentFilter = new IntentFilter();
mIntentFilter.addAction(ACTION_BROAD_CAST);
registerReceiver(mBroadcastReceiver, mIntentFilter);
super.onResume();
}
@Override
protected void onPause() {
/*
* 如果使用broadcast receiver來改變UI內容,則必須要註冊在onResume和onPuase中
* 如果需要註冊全域,可以寫在Manifest中, 可參考:http://yangguangfu.iteye.com/blog/1063732
* 裡面的"系統註冊"。其中也有更多的詳細介紹。
*/
unregisterReceiver(mBroadcastReceiver);
super.onPause();
}
void startThread() {
new Thread(new Runnable() {
@Override
public void run() {
Log.d(TAG, "thread啟動");
long count = 0;
while (!threadIsStop) {
// 開啟程序,定時送出一個broadcast
Intent intent = new Intent();
/* 注意送出的Action要和接收的一樣 */
intent.setAction(ACTION_BROAD_CAST);
// 填入值
intent.putExtra(KEY_INTENT_SIMPLE, count);
// 送出廣播
sendBroadcast(intent);
Log.d(TAG, "sendBroadcast count: " + count);
count++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}// end try
}// end while
}// end run
}).start();
};
/** 廣播的監聽器 */
BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_BROAD_CAST)) {
/*
* 查Action,意味著這邊可以同時接收許多Action,
* 但是在register的時候也必須要填入filiter之內,要不根本進不來
*/
long value = intent.getLongExtra(KEY_INTENT_SIMPLE, 0);
textView.setText("value notify: " + value);
}
}
};
@Override
protected void onDestroy() {
/*
* 這裡設定當activity結束時thread也應該結束,如果是包在Service裡面寫就可以追蹤
* 參考:http://androidsusan.blogspot.tw/2013/03/service.html
*/
threadIsStop = true;
super.onDestroy();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
// getMenuInflater().inflate(R.menu.activity_main, menu);
return false;
}
}
其實這沒什麼好講的,只是要注意在註冊broadcast receiver的方法也可以在manifest中做掉,就是差別在全域的註冊和區域的註冊哩。
動態和靜態的註冊可以參考這裡,不過這篇有點難讀,請慢慢服用。
------------我是不想要換篇新文章的分隔線------------
再來就是CursorLoader監聽其狀態的作法,專案下載在這裡。
專案實作了獲取手機聯絡人相關訊息,如果要實作必須要注意它有權限必須登入。
主要是使用了LoaderCallbacks<Cursor>物件,這裡必須使用getLoaderManager()獲得LoaderManager物件,呼叫initLoader()初始化LoaderCallbacks物件,然後就可以在其中實作。
注意這是3.0以後才有的東西,話說我看了一下很久以前上架的程式,3.x的裝置幾乎沒有(沒有顯示?)超過2.3.x版本的裝置大概都超過了七成,可能樣本數不是很足夠,不過現在開發似乎都不是很想開發3.0以下的版本了呀...
關於LoaderManager的部分,這裡有一些介紹,
如果你看英文會比比看中文還要快樂,可以略為參考這裡。
主要程式碼:
package com.example.cursorloader;
import android.app.Activity;
import android.app.LoaderManager;
import android.app.LoaderManager.LoaderCallbacks;
import android.app.ProgressDialog;
import android.content.CursorLoader;
import android.content.Loader;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Contacts.Photo;
import android.util.Log;
import android.view.Menu;
import android.widget.TextView;
/** {@link CursorLoader}監聽的方法 */
public class MainActivity extends Activity {
final String TAG = getClass().getSimpleName();
TextView textView, tx_info;
ProgressDialog mProgressDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textView);
tx_info = (TextView) findViewById(R.id.TextView_info);
tx_info.setText("還沒開始!");
// 設定轉轉轉
mProgressDialog = new ProgressDialog(MainActivity.this);
mProgressDialog.setMessage("Please Wait..");
mProgressDialog.setCancelable(false);
}
LoaderCallbacks<Cursor> mLoaderCallbacks = new LoaderCallbacks<Cursor>() {
// 我們可以實作一個新的callback來實作更完整的呼叫方法
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
Log.d(TAG, "獲取cursor " + id);
CursorLoader mCursorLoader;
// 設定Cursor搜尋條件,這邊可以在建構子時操作
mCursorLoader = new CursorLoader(MainActivity.this);
mCursorLoader.setUri(Phone.CONTENT_URI);
String[] PHONES_PROJECTION = new String[] { Phone.DISPLAY_NAME,
Phone.NUMBER, Photo.PHOTO_ID, Phone.CONTACT_ID };
mCursorLoader.setProjection(PHONES_PROJECTION);
// 創立就馬上執行
mCursorLoader.loadInBackground();
return mCursorLoader;
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor mCursor) {
// 這個介面的意思是如果在onCreateLoader()中創立的loader結束時在這裡就會有反應。
if (mProgressDialog.isShowing()) {
mProgressDialog.dismiss();
}
tx_info.setText("Complete!!");
// 結束後的動作
Log.d(TAG, "獲取cursor" + mCursor);
if (mCursor != null) {
Log.d(TAG, "cursor count: " + mCursor.getCount());
if (mCursor.getCount() > 0) {
StringBuffer mBuffer = new StringBuffer();
while (mCursor.moveToNext()) {
// 獲得名字
mBuffer.append(mCursor.getString(mCursor
.getColumnIndex(Phone.DISPLAY_NAME)));
mBuffer.append("\n");
mBuffer.append(mCursor.getString(mCursor
.getColumnIndex(Phone.NUMBER)));
mBuffer.append("\n");
mBuffer.append("\n");
}// end while
textView.setText(mBuffer.toString());
}// end if(mCursor.getCount()>0)
mCursor.close();
}// end if(mCursor!=null)
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
// TODO 這是reset的方法,沒有用到
}
};
@Override
protected void onResume() {
mProgressDialog.show();
LoaderManager mLoaderManager = getLoaderManager();
// 利用觀察者模式來設計監控loader的方法,其中前兩個參數是判定方法可以由控制項操作LoaderCallbacks的內容
mLoaderManager.initLoader(1, null, mLoaderCallbacks);
super.onResume();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
// getMenuInflater().inflate(R.menu.activity_main, menu);
return false;
}
}
有空來補,最近在開始學ios,最麻煩的是兩個鍵盤不一樣,操作mac習慣以後換回來windows系統就整個卡卡的。可是mac的eclipse快速鍵又不太熟悉,突然覺得生命太長了可能要睡少一點才能在知識上面有所收穫才是...
沒有留言:
張貼留言
你好,我是小書,如果文章內容有錯誤,或是看到有建議以及任何感想時,歡迎提出分享,我們一起學習一起努力。