標籤:android des style blog http color
一、內容觀察者的運行原理
運行過程通常為A應用對內容提供者暴露的資料進行修改,而B應用負則專門責監聽內容提供者資料的變化。
1、簡單的小示範
首先在內容提供者寫一個MyContentProvider類繼承ContentProvider如下
public class MyContentProvider extends ContentProvider
繼承後會自動重寫6個方法(增刪改查onCreat和getBytes)在B應用對應修改的方法(增刪改)中發出通知,getContext().getContentResolver().notifyChange(uri, null);
通知A應用(觀察者內容發生變化),A應用的
Uri uri=Uri.parse("content://qjq");
getContentResolver().query(uri, null, null, null, null);
Log.i(TAG, "查詢已完成");
//監聽資料的改變。參數二notifyForDescendents boolean 是否級聯
getContentResolver().registerContentObserver(uri, true, new MyContentObserver(new Handler()));
Log.i(TAG, "已經設定了監聽");}
private class MyContentObserver extends ContentObserver{}//重寫建構函式和onChange方法
二、使用內容觀察者監聽簡訊資料的改變(掌握)
簡訊的資料存放的位置,
源碼的資訊清單檔裡面
簡訊的存放的位置
核心的URI
代碼:
二、簡訊監聽器
getContentResolver().registerContentObserver(Uri.parse("content://sms"), true, new MyContentObserver(new Handler()));MyContentObserver為自己new的一個類繼承ContentObserver重寫onChange方法代碼如下
public void onChange(boolean selfChange) {
// TODO Auto-generated method stub
super.onChange(selfChange);
//如果簡訊內容改變 方法會被系統自動調用
//擷取最新的那條簡訊 (查詢簡訊資料 需要許可權 讀簡訊的許可權)
//address 號碼 ,body 內容
Cursor c = getContentResolver().query(Uri.parse("content://sms"), new String[]{"address","body"}, null, null, "_id desc");
c.moveToFirst();
String address=c.getString(0);
String body=c.getString(1);
Log.i(TAG, "address:"+address+",body:"+body);
c.close(); }
三、ANR異常(即使用者點擊按鈕5秒沒響應的時候西永就會快顯視窗)瞭解
寫一個anr按鈕
在mainactivity裡面寫代碼如下
注意以後不能再activity裡面不能執行耗時的操作,如果出現耗時的操作,應該開線程
Android的程式預設是單線程即為主線程或者是UI線程。
如何開啟線程
開線程有兩種方式
第一種方式
new Thread(){
public void run() {
};
}.start();
第二方式
new Thread(new Runnable() {
@Override
public void run() {
}
}).start();
四、【案例】實現點擊開始按鈕TextView框裡面顯示1+...+100的結果的變化過程
1.介面一個編輯框一個按鈕
2.Mainactivity代碼如下如果不使用訊息處理器會報錯誤
07-13 02:38:25.215: E/AndroidRuntime(21713): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.只有主線程才可以操作顯示
Mainactivity代碼如下:
public class MainActivity extends Activity {
protected static final int UPDATE_SUM = 0;//只是一種標示
private TextView tv_number;
//訊息處理器
public Handler mHandler = new Handler() {
//處理訊息的方法,輸入handle按提示alt+/就可出來
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case UPDATE_SUM:
int sum = (Integer) msg.obj;
tv_number.setText(sum + "");
break;
default:
break;
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv_number = (TextView) findViewById(R.id.tv_number);
}
public void add(View v) {
new Thread() {
public void run() {
int i = 0;
int sum = 0;
while (i <= 100) {
i++;
sum += i;
//tv_number.setText(sum+""); 子線程不能操作顯示發訊息給主線程
/**
* 思路:
* 1 建立訊息
* 2 把資料設定給訊息對象
* 3 發送訊息
*/
Message msg = Message.obtain();//obtain獲得,即擷取訊息
msg.what = UPDATE_SUM;//給訊息設定唯一標示
msg.obj = sum;
mHandler.sendMessage(msg);//訊息發送後就會交給mHanlder裡面的handleMessage()方法
SystemClock.sleep(200);
}
}
}.start();
}
五、Android下訊息機制的實現。
1、網路通訊協定
Get請求,資料寫在URL的後面,1kb
Post請求資料在實體裡面
六、【案例五】網狀圖片查看器
在Android2.3以下可以直接使用以下代碼讀取網狀圖片,2.3以上必須使用訊息處理器來處理
try {//多學一招alt+shift+z(x,y是大小寫互換)包裹塊來try ...catch
String path = et_path.getText().toString();
// 1 封裝網路路徑 URL注意不是Uri
URL url=new URL(path);
// 2 開啟串連 url.openConnection()
HttpURLConnection conn=(HttpURLConnection) url.openConnection();
//3 設定串連的參數 (逾時時間長度、請求的方式)
conn.setConnectTimeout(10000);
conn.setRequestMethod("get");//小寫是錯的注意了改成GET
//4 判斷響應碼:200成功
if (conn.getResponseCode()==200){
//5 擷取伺服器回送的流資料
InputStream is= conn.getInputStream();
//把流處理成一張圖片 再顯示
Bitmap bitmap=BitmapFactory.decodeStream(is);
//設定圖片顯示
iv.setImageBitmap(bitmap);
}
使用訊息處理器以及緩衝圖片全部代碼如下
public class MainActivity extends Activity {
private final static String TAG = "MainActivity";
protected static final int SUCCESS_GET_IMAGE = 0;
protected static final int ERROR_GET_IMAGE = 1;
private ImageView iv;
private EditText et_path;
private Handler mHandler = new Handler(){
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case SUCCESS_GET_IMAGE:
File file = (File) msg.obj;
//設定圖片的顯示
iv.setImageURI(Uri.fromFile(file));
break;
case ERROR_GET_IMAGE:
Toast.makeText(getApplicationContext(), "擷取圖片失敗", 0).show();
break;
default:
break;
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_path = (EditText) findViewById(R.id.et_path);
iv = (ImageView) findViewById(R.id.iv);
}
public void get(View v){
new Thread(){
public void run() {
try {
String path = et_path.getText().toString();
File file = new File(Environment.getExternalStorageDirectory(),getFileName(path));
//判斷圖片是否存在
if(file.exists()){
//直接使用
Log.i(TAG, "使用了緩衝的圖片");
Message msg = Message.obtain();
msg.what = SUCCESS_GET_IMAGE;
msg.obj = file;
mHandler.sendMessage(msg);
}else{
//1 封裝網路路徑 URL
URL url = new URL(path);
//2 開啟串連 url.openConnection()
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//逾時時間長度
conn.setConnectTimeout(5000);
//請求的方式
conn.setRequestMethod("GET");
//4 判斷響應碼:200成功
if(conn.getResponseCode() == 200){
//5 擷取伺服器回送的流資料
InputStream is = conn.getInputStream();
//把流處理成一張圖片 再顯示
Bitmap bitmap = BitmapFactory.decodeStream(is);//使用位元影像工廠處理為圖片
//緩衝在sdcard
FileOutputStream stream = new FileOutputStream(file);
//format 圖片的格式
//quality 圖片的品質
//stream 輸出資料流
bitmap.compress(CompressFormat.JPEG, 100, stream);
Log.i(TAG, "下載了圖片,並且緩衝到了sdcard");
//發訊息給主線程
Message msg = Message.obtain();
msg.what = SUCCESS_GET_IMAGE;
msg.obj = file;
mHandler.sendMessage(msg);
}else{
Message msg = Message.obtain();
msg.what = ERROR_GET_IMAGE;
mHandler.sendMessage(msg);
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
Message msg = Message.obtain();
msg.what = ERROR_GET_IMAGE;
mHandler.sendMessage(msg);
}
};
}.start();
}
//擷取檔案的名字
public String getFileName(String path){
return path.substring(path.lastIndexOf("/")+1);
}
@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 true;
}
}
3.使用SmartImageView 開源空間擷取網頁圖片,將loopj.android.image包複製到src目錄下另外布局裡面的標籤要改成loopj.android.image.SmartImageView即包名加上SmartImageView
iv.setImageUrl("http://10.0.2.2:8080/tomcat.png");
七、從伺服器上擷取json資料
InputStream is = conn.getInputStream();//其實是一個json格式的字串
//如何把json格式的字串 轉化為對象集合
//1 把流變為字串
//2 把字串變為JSONArray
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while((len = is.read(buffer)) != -1){
bos.write(buffer, 0, len);
}
String json = bos.toString();
bos.close();
is.close();
//2 把字串變為JSONArray
JSONArray array = new JSONArray(json);
for(int i = 0;i<array.length();i++){
JSONObject jsonObject = array.getJSONObject(i);
int id = jsonObject.getInt("id");
String name = jsonObject.getString("name");
int age = jsonObject.getInt("age");
Log.i(TAG, "id:"+id+",name:"+name+",age:"+age);