傳智播客android學習筆記,

06: 電話撥號
 使用系統自帶意圖對象完成:
  Intent intent=new Intent();
  intent.setAction("android.intent.action.Call");
  intent.setData(Uri.parse("tel:"+i));
  startActivity(Intent);
 權限:
  <uses-permission android:name="android.permission.CALL_PHONE"/>
08:短信發送
 使用系統類
  SmsManager manager = SmsManager.getDefault();
  manager.sendTextMessage(phonenumber, null, content, null, null);
 權限:
  <uses-permission android:name="android.permission.SEND_SMS"/>
  <uses-permission android:name="android.permission.RECEIVE_SMS"/>//發送短信
09: 佈局技術
 LinearLayout(線性佈局),RelativeLayout(相對佈局),TableLayout(表格佈局),FrameLayout(幀佈局)
10:單元測試
 得到單元測試框架:
  <manifest> 
   <application>
    <activity/>
    <uses-library android:name="android.test.runner"/>
   </application>
   <instrumentation
    android:name="android.test.InstrumentationTestRunner"
    android:targetPackage="com.xiaoqiang" />
  </manifest> 
11: 文件操作
 使用上下文獲取文件輸入輸出對象---(Context可在繼承了Activity的類中使用getApplicationContext()方法獲取);
  Context context=getApplicationContext();
  FileOutputStream outStream=context.openFileOutput(filename, Context.MODE_PRIVATE);//第二個參數爲操作模式
  outStream.write(content.getBytes());
  outStream.close();
14:保存文件到SD卡:操作時候需要獲取SD的狀態,使用Environment.getExternalStorageState();
  File file=new File(new File("/mnt/sdcard"),filename);  //new File("/mnt/sdcard")可使用Environment.getExternalStorageDirectory();獲取
  FileOutputStream outStream=new FileOutputStream(file);
  outStream.write(new String("ss").getBytes());
  outStream.close();
 權限:
  <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /><!--創建與刪除文件-->
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><!--寫入數據-->
15:pull操作XML
 得到pull解析器
 XmlPullParser P=XmlPullParserFactory.newInstance().newPullParser();  //或者使用android.util.Xml.newPullParser();
 P.setInput(inputStream,"UTF-8");
 得到xml序列化器
 XmlSerializer ser=Xml.newSerializer();
 ser.setOutput(outputStream,"UTF-8")
16: SharedPreferences(偏好參數保存)
 保存:
  SharedPreferences preferences=getApplicationContext().getSharedPreferences("filename", Context.MODE_PRIVATE);
  android.content.SharedPreferences.Editor editor=preferences.edit();
  editor.putString("name","xiaoqiang");
  editor.putString("sex","male");
  editor.commit();
 讀取:
 public Map<String, String> getPreferences() {
  Map<String, String> params=new HashMap<String, String>();
  SharedPreferences preferences = getApplicationContext()
    .getSharedPreferences("filename", Context.MODE_PRIVATE);
  params.put("name",preferences.getString("name", "")); //getString 的第二參數表示不存在該參數時返回默認值
  return params;
 }
17: SQLite數據庫
 基礎:
  支持數據類型:NULL,INTEGER,REAL(浮點),TEXT,BLOB(二進制數據對象)
  可以把任意數據類型保存到任意字段中,如TEXT文本寫入到integer字段中,如聲明20個字符,可以保存超過20個字符  ::主鍵除(Integer)
  CREATE TABLE person (persionid integer primary key autoincrement,name varchar(20))
  分頁技術: select * from Table limit 5 offset 3或者select * from Table limit 3,5
  獲取自增加的ID值:SELECT last_insert_rowid() 
 使用:
  1、新建DBOpenHelpter類extends SQLiteOpenHelper類
   package com.xiaoqiang.service;
   import android.content.Context;
   import android.database.sqlite.SQLiteDatabase;
   import android.database.sqlite.SQLiteOpenHelper;
   public class DBOpenHelpter extends SQLiteOpenHelper {
    public DBOpenHelpter(Context context) {
     // content 上下文
     // name 數據名字
     // CursorFactory 遊標
     // version 數據庫版本號
     super(context, "xiaoqiang.db", null, 1);
    }
    @Override
    public void onCreate(SQLiteDatabase db) {
     // 數據庫第一次被創建的時候調用
     String sql = "CREATE TABLE person(persionid integer primary key autoincrement,name varchar(20))";
     db.execSQL(sql);
    }
    @Override
    public void onUpgrade(SQLiteDatabase db, int arg1, int arg2) {
     // 數據庫文件的版本號發生改變時調用
     // String sql = "ALTER TABLE person RENAME COLUMN persionid to personid"; //修改表結構
     // db.execSQL(sql);
    }
   }
  2、創建業務類實現增刪改查
    package com.xiaoqiang.service;
    import java.util.ArrayList;
    import java.util.List;
    import android.content.Context;
    import android.database.Cursor;
    import android.database.sqlite.SQLiteDatabase;
    import com.xiaoqiang.domain.Person;
    public class PersonService {
     private DBOpenHelpter deDbOpenHelpter;
     public PersonService(Context context) {
      this.deDbOpenHelpter = new DBOpenHelpter(context);
     }
     public void save(Person person) {
      // 擁有緩存特點
      SQLiteDatabase db = deDbOpenHelpter.getWritableDatabase();
      db.execSQL("insert into person(name,phone) values(?,?)", new Object[] {
        person.getName(), person.getPhone() });
     }
     public void delete(Integer id) {
      SQLiteDatabase db = deDbOpenHelpter.getWritableDatabase();
      db.execSQL("delete from person where persionid=?", new Object[] { id });
     }
     public void update(Person person) {
      SQLiteDatabase db = deDbOpenHelpter.getWritableDatabase();
      db.execSQL(
        "update person set name=?,phone=? where persionid=?",
        new Object[] { person.getName(), person.getPhone(),
          person.getId() });
     }
     public Person find(Integer id) {
      SQLiteDatabase db = deDbOpenHelpter.getReadableDatabase();
      Cursor cursor = db.rawQuery("select * from person where persionid=?",
        new String[] { id.toString() });
      if (cursor.moveToFirst()) {
       int personid = cursor.getInt(cursor.getColumnIndex("persionid"));
       String personname = cursor.getString(cursor.getColumnIndex("name"));
       String personphone = cursor.getString(cursor
         .getColumnIndex("phone"));
       return new Person(personid, personname, personphone);
      }
      cursor.close();
      return null;
     }
     public List<Person> getScrollData(int offset, int maxResult) {
      List<Person> persons = new ArrayList<Person>();
      SQLiteDatabase db = deDbOpenHelpter.getReadableDatabase();
      Cursor cursor = db.rawQuery(
        "select * from person order by persionid asc limit ?,?",
        new String[] { String.valueOf(offset),
          String.valueOf(maxResult) });
      while (cursor.moveToNext()) {// 移到下一條記錄
       int personid = cursor.getInt(cursor.getColumnIndex("persionid"));
       String personname = cursor.getString(cursor.getColumnIndex("name"));
       String personphone = cursor.getString(cursor
         .getColumnIndex("phone"));
       persons.add(new Person(personid, personname, personphone));
      }
      cursor.close();
      return persons;
     }
     public long getcount() {
      SQLiteDatabase db = deDbOpenHelpter.getReadableDatabase();
      Cursor cursor = db.rawQuery("select count(*) from person", null);
      cursor.moveToFirst();
      long result = cursor.getLong(0);
      cursor.close();
      return result;
     }
    }
  3、創建數據抽象類(bean)
    package com.xiaoqiang.domain;
    public class Person {
     private Integer id;
     private String name;
     private String phone;
     public Person() {
     }
     public Person(String name, String phone) {
      this.name = name;
      this.phone = phone;
     }
     @Override
     public String toString() {
      return "Person [id=" + id + ", name=" + name + ", phone=" + phone + "]";
     }
     public Person(Integer id, String name, String phone) {
      this.id = id;
      this.name = name;
      this.phone = phone;
     }
     public Integer getId() {
      return id;
     }
     public void setId(Integer id) {
      this.id = id;
     }
     public String getName() {
      return name;
     }
     public void setName(String name) {
      this.name = name;
     }
     public String getPhone() {
      return phone;
     }
     public void setPhone(String phone) {
      this.phone = phone;
     }
    }
  4、測試類
    package com.xiaoqiang.test;
    import java.util.List;
    import android.test.AndroidTestCase;
    import android.util.Log;
    import com.xiaoqiang.domain.Person;
    import com.xiaoqiang.service.DBOpenHelpter;
    import com.xiaoqiang.service.PersonService;
    public class PersonServiceTest extends AndroidTestCase {
     public void testCreateDB() throws Exception {
      DBOpenHelpter dbOpenHelpter = new DBOpenHelpter(getContext());
      dbOpenHelpter.getReadableDatabase();
     }
     public void testSave() throws Exception {
      PersonService service = new PersonService(this.getContext());
      for (int i = 0; i < 20; i++) {
       service.save(new Person("xiaoqiang" + i, "123"));
      }

     }
     public void testFind() {
      PersonService service = new PersonService(this.getContext());
      Person person = service.find(1);
      Log.i("aaa", person.toString());
     }
     public void testupdate() {
      PersonService service = new PersonService(this.getContext());
      Person person = service.find(1);
      person.setName("niexiaoqiang");
      person.setPhone("18684033128");
      service.update(person);
      person = service.find(1);
      Log.i("aaa", person.toString());
     }
     public void testcount() {
      PersonService service = new PersonService(this.getContext());
      long result = service.getcount();
      Log.i("aaa", result + "");
     }
     public void testdelete() {
      PersonService service = new PersonService(this.getContext());
      service.delete(4);
      Log.i("aaa", service.getcount() + "");
     }
     public void testScrollData() {
      PersonService service = new PersonService(this.getContext());
      List<Person> persons = service.getScrollData(0, 5);
      for (Person person : persons) {
       Log.i("aaa", person.toString() + "");
      }
     }
    }
18: 事務
 模擬轉賬
 public void paymoney(Integer payid, Integer paymoney, Integer getid) {
  SQLiteDatabase db = deDbOpenHelpter.getReadableDatabase();
  String paysql = "update person set money=money-? where persionid=?";
  String getsql = "update person set money=money+? where persionid=?";
  db.beginTransaction();
  try {
   db.execSQL(paysql, new Object[] { paymoney, payid });
   db.execSQL(getsql, new Object[] { paymoney, getid });
   db.setTransactionSuccessful();
  } finally {
   db.endTransaction();
  }
 }
19: listview
 界面顯示:
  1、listview中每行數據的Item界面
  <?xml version="1.0" encoding="utf-8"?>
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" >
   <TextView android:layout_width="100dp" android:layout_height="wrap_content" android:textSize="30sp" android:id="@+id/name" />
   <TextView android:layout_width="150dp" android:layout_height="wrap_content" android:textSize="30sp" android:id="@+id/phone" />
   <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:textSize="30sp" android:id="@+id/money"/>
  </LinearLayout>
  2、主界面
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" >
   <LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent" android:layout_height="wrap_content"
    android:orientation="horizontal" >
    <TextView android:id="@+id/name" android:layout_width="100dp"
     android:layout_height="wrap_content"
     android:textSize="30sp"
     android:text="name" />

    <TextView android:id="@+id/phone" android:layout_width="150dp"
     android:layout_height="wrap_content"
     android:textSize="30sp"
     android:text="phone" />

    <TextView android:id="@+id/money" android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:textSize="30sp"
     android:text="money" />
   </LinearLayout>
   <ListView android:id="@+id/listView"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" />
  </LinearLayout>
 加載控件
  @Override
  protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_main);
   personservice = new PersonService(this);
   listView = (ListView) this.findViewById(R.id.listView);
   listView.setOnItemClickListener(new ItemClickListener());
   
   show3();//加載數據
   //show();//加載數據
  }
  //定義ITEM點擊事件監聽器
  private final class ItemClickListener implements OnItemClickListener {

   @Override
   // 1,當前點擊條目所在的listview,2、當前點擊的條目的view對象,3、當前點擊條目在集合中德索引值,4、item在listview中德排列ID
   public void onItemClick(AdapterView<?> parent, View view,
     int personsIndex, long itemWithListviewID) {
    ListView lView = (ListView) parent;
    Person person = (Person) lView.getItemAtPosition(personsIndex);
    Toast.makeText(getApplicationContext(), person.getId().toString(),
      1).show();
   }

  }
  //使用自定義設配器加載數據
  private void show3() {
   List<Person> persons = personservice.getScrollData(0, 10);
   PersonAdapter adapter = new PersonAdapter(this, persons,
     R.layout.data_item);
   listView.setAdapter(adapter);
  }
  // 使用系統SimpleAdapter加載數據
  private void show() {

   List<Person> persons = personservice.getScrollData(0, 10);
   List<HashMap<String, Object>> data = new ArrayList<HashMap<String, Object>>();
   for (Person person : persons) {
    HashMap<String, Object> item = new HashMap<String, Object>();
    item.put("name", person.getName());
    item.put("id", person.getId());
    item.put("phone", person.getPhone());
    item.put("money", person.getMoney());
    data.add(item);
   }
   // 適配器
   SimpleAdapter adapter = new SimpleAdapter(this, data,
     R.layout.data_item, new String[] { "name", "phone", "money" },
     new int[] { R.id.name, R.id.phone, R.id.money });
   listView.setAdapter(adapter);
  }
 3、自定義適配器
  package com.xiaoqiang.adapter;
  import java.util.List;
  import com.xiaoqiang.db.R;
  import com.xiaoqiang.domain.Person;
  import android.content.Context;
  import android.view.LayoutInflater;
  import android.view.View;
  import android.view.ViewGroup;
  import android.widget.BaseAdapter;
  import android.widget.TextView;
  public class PersonAdapter extends BaseAdapter {
   private List<Person> persons;
   private int resource;
   private LayoutInflater inflater; //安卓自帶服務
   public PersonAdapter(Context context, List<Person> persons, int resource) {
    this.persons = persons;
    this.resource = resource;
    inflater = (LayoutInflater) context
      .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
   }
   @Override
   public int getCount() {
    return persons.size();
   }
   @Override
   public Object getItem(int position) {
    return persons.get(position);
   }
   @Override
   public long getItemId(int position) {
    return position;
   }
   @Override
   public View getView(int position, View convetView, ViewGroup parent) {
    TextView nameview = null;
    TextView phoneview = null;
    TextView moneyview = null;
    if (convetView == null) { //判斷convetView是否爲空,代表是否爲第一次加載
     convetView = inflater.inflate(resource, null);
     nameview = (TextView) convetView.findViewById(R.id.name);
     phoneview = (TextView) convetView.findViewById(R.id.phone);
     moneyview = (TextView) convetView.findViewById(R.id.money);
     ViewCache viewCache = new ViewCache();
     viewCache.nameview = nameview;
     viewCache.phoneview = phoneview;
     viewCache.moneyview = moneyview;
     convetView.setTag(viewCache);
    } else {
     ViewCache cache = (ViewCache) convetView.getTag();
     nameview = cache.nameview;
     phoneview = cache.phoneview;
     moneyview = cache.moneyview;
    }
    Person person = persons.get(position);
    nameview.setText(person.getName());
    phoneview.setText(person.getPhone());
    moneyview.setText(person.getMoney().toString());
    return convetView;
   }
   private final class ViewCache {
    public TextView nameview;
    public TextView phoneview;
    public TextView moneyview;
   }
  }

20、內容提供者(Content provider):對外共享數據,其他應用可以通過內容提供者訪問程序數據  
 Tag:創建後需要在清單文件中列出,好處:統一數據訪問方式
 Tag:需要在應用的包或者子包中生命組建
 創建內容提供者
  package com.xiaoqiang.db;
  import android.content.ContentProvider;
  import android.content.ContentUris;
  import android.content.ContentValues;
  import android.content.UriMatcher;
  import android.database.Cursor;
  import android.database.sqlite.SQLiteDatabase;
  import android.net.Uri;
  import com.xiaoqiang.service.DBOpenHelpter;
  public class PersonProvider extends ContentProvider {

   private DBOpenHelpter dbOpenHelpter;
   private static final UriMatcher MATHCER = new UriMatcher(-1);
   static {
    MATHCER.addURI("com.xiaoqiang.personprovider", "person", 1);
    MATHCER.addURI("com.xiaoqiang.personprovider", "person/#", 2); // #代表數字
   }

   @Override
   public boolean onCreate() {
    dbOpenHelpter = new DBOpenHelpter(this.getContext());
    return true;
   }

   @Override
   public int delete(Uri uri, String selection, String[] selectionarg) {
    SQLiteDatabase db = dbOpenHelpter.getWritableDatabase();
    int num = 0;
    // 判斷url是否爲合法路徑
    switch (MATHCER.match(uri)) {
    case 1:
     num = db.delete("person", selection, selectionarg);
     break;
    case 2:
     long rowid = ContentUris.parseId(uri);
     String where = "persionid=" + rowid;
     if (selection != null && "".equals(selection.trim())) {
      where += " and " + selection;
     }
     num = db.delete("person", where, selectionarg);
     break;

    default:
     throw new IllegalAccessError("this is unknown url");
    }
    return num;
   }

   @Override
   public String getType(Uri uri) {
    switch (MATHCER.match(uri)) {
    case 1:
     return "vnd.android.cursor.dir/person";//規定vnd.android.cursor.dir
    case 2:
     return "vnd.android.cursor.item/person";//規定vnd.android.cursor.item
    default:
     throw new IllegalAccessError("this is unknown url");
    }
   }

   @Override
   public Uri insert(Uri uri, ContentValues values) {
    SQLiteDatabase db = dbOpenHelpter.getWritableDatabase();
    // 判斷url是否爲合法路徑
    switch (MATHCER.match(uri)) {
    case 1:
     long rowid = db.insert("person", "name", values);
     // Uri insetUri=ContentUris.withAppendedId(uri, rowid);
     Uri insetUri = Uri
       .parse("content://com.xiaoqiang.personprovider/person/"
         + rowid);

     return insetUri;
    default:
     throw new IllegalAccessError("this is unknown url");
    }
   }

   @Override
   public Cursor query(Uri uri, String[] projection, String selection,
     String[] selectionArgs, String orderBy) {
    SQLiteDatabase db = dbOpenHelpter.getReadableDatabase();
    // 判斷url是否爲合法路徑
    switch (MATHCER.match(uri)) {
    case 1:
     return db.query("person", projection, selection, selectionArgs,
       null, null, orderBy);
    case 2:
     long rowid = ContentUris.parseId(uri);
     String where = "persionid=" + rowid;
     if (selection != null && "".equals(selection.trim())) {
      where += " and " + selection;
     }

     return db.query("person", projection, where, selectionArgs, null,
       null, orderBy);

    default:
     throw new IllegalAccessError("this is unknown url");
    }

   }

   @Override
   public int update(Uri uri, ContentValues values, String selection,
     String[] selectionarg) {
    SQLiteDatabase db = dbOpenHelpter.getWritableDatabase();
    int num = 0;
    // 判斷url是否爲合法路徑
    switch (MATHCER.match(uri)) {
    case 1:
     num = db.update("person", values, selection, selectionarg);
     break;
    case 2:
     long rowid = ContentUris.parseId(uri);
     String where = "persionid=" + rowid;
     if (selection != null && "".equals(selection.trim())) {
      where += " and " + selection;
     }
     num = db.update("person", values, where, selectionarg);
     break;

    default:
     throw new IllegalAccessError("this is unknown url");
    }
    return num;
   }
  }
 使用內容提供者
  package com.xiaoqiang.db.test;
  import android.content.ContentResolver;
  import android.content.ContentValues;
  import android.database.Cursor;
  import android.net.Uri;
  import android.test.AndroidTestCase;
  import android.util.Log;
  public class AccessContentproviderTest extends AndroidTestCase {
   public void testInsert() throws Exception {
    Uri uri = Uri.parse("content://com.xiaoqiang.personprovider/person");
    ContentResolver contentResolver = this.getContext()
      .getContentResolver();
    ContentValues values = new ContentValues();
    values.put("name", "xiaoqiang123");
    values.put("phone", "183439834");
    values.put("money", "183000000");
    contentResolver.insert(uri, values);
   }
   public void testDelete() throws Exception {
    Uri uri = Uri.parse("content://com.xiaoqiang.personprovider/person/20");
    ContentResolver contentResolver = this.getContext()
      .getContentResolver();
    contentResolver.delete(uri, null, null);
   }
   public void testUpdate() throws Exception {
    Uri uri = Uri.parse("content://com.xiaoqiang.personprovider/person/2");
    ContentResolver contentResolver = this.getContext()
      .getContentResolver();
    ContentValues values = new ContentValues();
    values.put("name", "aaa");
    contentResolver.update(uri, values, null, null);
   }
   public void testquray() throws Exception {
    Uri uri = Uri.parse("content://com.xiaoqiang.personprovider/person");
    ContentResolver contentResolver = this.getContext()
      .getContentResolver();
    Cursor cursor = contentResolver.query(uri, null, null, null, null);
    while (cursor.moveToNext()) {
     String name = cursor.getString(cursor.getColumnIndex("name"));
     Log.i("aaa", name);
    }
   }
  }
21、監聽內容提供者中的數據變化
 場景:A應用更新了內容提供者的數據,B應用需要馬上知道
 1、在內容提供者數據變化方法內新增:
  如在insert中新增:this.getContext().getContentResolver().notifyChange(uri, null); //發出數據變化通知 
 2、 在應用中註冊數據變化監聽器  (在應該程序主界面【創建(onCreate)】方法中註冊)
  Uri uri = Uri.parse("content://com.xiaoqiang.personprovider/person");
  this.getContentResolver().registerContentObserver(uri, true,
    new PersonContentOberver(new Handler()));// 第三個參數爲監聽對象
 3、創建監聽對象類  
  private class PersonContentOberver extends ContentObserver {
   @Override
   // 該剛發只能知道發生了改變,不知道具體內容
   public void onChange(boolean selfChange) {
    // select * from person order by persionid desc limit 1
    Uri uri = Uri
      .parse("content://com.xiaoqiang.personprovider/person");
    Cursor cursor = getContentResolver().query(uri, null, null, null,
      "persionid desc limit 1");
    if (cursor.moveToNext()) {
     String name = cursor.getString(cursor.getColumnIndex("name"));
     Log.i("aaa", name);
    }
   }
   public PersonContentOberver(Handler handler) {
    super(handler);
   }
  }
22、訪問通訊錄和添加聯繫人
 通訊錄內容提供者uri:ContactsProvider2或者com.android.contacts  讀寫權限:android.permission.READ_CONTACTS,android.permission.WRITE_CONTACTS
 呼叫記錄內容提供者uri:CallLogProvider   讀寫權限:android.permission.READ_CONTACTS,android.permission.WRITE_CONTACTS
 
 
 使用測試方法向手機中添加和查找聯繫人:
  package com.xiaoqiang.test;
  import java.util.ArrayList;
  import android.content.ContentProviderOperation;
  import android.content.ContentResolver;
  import android.content.ContentUris;
  import android.content.ContentValues;
  import android.database.Cursor;
  import android.net.Uri;
  import android.test.AndroidTestCase;
  import android.util.Log;
  public class ContactsTest extends AndroidTestCase {
   public void testGetContacts() throws Exception {
    Uri uri = Uri.parse("content://com.android.contacts/contacts");
    ContentResolver resolver = getContext().getContentResolver();
    Cursor cursor = resolver.query(uri, new String[] { "_id" }, null, null,
      null);
    while (cursor.moveToNext()) {
     int contactid = cursor.getInt(0);
     StringBuilder sb = new StringBuilder("contactid=");
     sb.append(contactid);
     uri = Uri.parse("content://com.android.contacts/contacts/"
       + contactid + "/data");
     Cursor datacursor = resolver.query(uri, new String[] { "mimetype",
       "data1", "data2" }, null, null, null);
     while (datacursor.moveToNext()) {
      String data = datacursor.getString(datacursor
        .getColumnIndex("data1"));
      String type = datacursor.getString(datacursor
        .getColumnIndex("mimetype"));
      if ("vnd.android.cursor.item/name".equals(type)) {
       sb.append(",name=" + data);
      } else if ("vnd.android.cursor.item/email_v2".equals(type)) {
       sb.append(",email=" + data);
      } else if ("vnd.android.cursor.item/phone_v2".equals(type)) {
       sb.append(",phone=" + data);
      }
     }
     Log.i("aaa", sb.toString());
    }
   }

   /**
    * @function 測試根據號碼獲取聯繫人姓名
    * @throws Exception
    */
   public void testGetContactsNamebyNumber() throws Exception {
    String number = "18684033128";
    Uri uri = Uri
      .parse("content://com.android.contacts/data/phones/filter/"
        + number);
    ContentResolver resolver = getContext().getContentResolver();
    Cursor cursor = resolver.query(uri, new String[] { "display_name" },
      null, null, null);
    if (cursor.moveToFirst()) {
     String name = cursor.getString(0);
     Log.i("aaa", name);
    }
   }

   /**
    * @fuction 添加聯繫人
    * @throws Exception
    */
   public void testAddContact() throws Exception {
    Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
    ContentResolver resolver = getContext().getContentResolver();
    ContentValues values = new ContentValues();
    long contactid = ContentUris.parseId(resolver.insert(uri, values));
    // 添加姓名
    Uri datauri = Uri.parse("content://com.android.contacts/data");
    values.put("raw_contact_id", contactid);
    values.put("mimetype", "vnd.android.cursor.item/name");
    values.put("data2", "xiaoqiang1");
    resolver.insert(datauri, values);
    // 添加電話
    values.clear();
    values.put("raw_contact_id", contactid);
    values.put("mimetype", "vnd.android.cursor.item/phone_v2");
    values.put("data1", "110");
    values.put("data2", "2");
    resolver.insert(datauri, values);
    // 添加email
    values.clear();
    values.put("raw_contact_id", contactid);
    values.put("mimetype", "vnd.android.cursor.item/email_v2");
    values.put("data1", "[email protected]");
    values.put("data2", "2");
    resolver.insert(datauri, values);
   }

   /**
    * @fuction 添加聯繫人      在同一個事務中完成聯繫人的添加
    * @throws Exception
    */
   public void testAddContact2() throws Exception {
    Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
    ContentResolver resolver = getContext().getContentResolver();
    ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();

    ContentProviderOperation op1 = ContentProviderOperation.newInsert(uri)
      .withValue("account_name", null).build();
    operations.add(op1);

    Uri datauri = Uri.parse("content://com.android.contacts/data");
    ContentProviderOperation op2 = ContentProviderOperation
      .newInsert(datauri).withValueBackReference("raw_contact_id", 0)
      .withValue("mimetype", "vnd.android.cursor.item/name")
      .withValue("data2", "xiaoqiang2").build();// 0爲執行第0操作對象(插入)後返回的ID值
    operations.add(op2);

    ContentProviderOperation op3 = ContentProviderOperation
      .newInsert(datauri).withValueBackReference("raw_contact_id", 0)
      .withValue("mimetype", "vnd.android.cursor.item/phone_v2")
      .withValue("data1", "119").withValue("data2", "2").build();// 0爲執行第0操作對象(插入)後返回的ID值
    operations.add(op3);

    ContentProviderOperation op4 = ContentProviderOperation
      .newInsert(datauri).withValueBackReference("raw_contact_id", 0)
      .withValue("mimetype", "vnd.android.cursor.item/email_v2")
      .withValue("data1", "[email protected]").withValue("data2", "2")
      .build();// 0爲執行第0操作對象(插入)後返回的ID值
    operations.add(op4);

    resolver.applyBatch("com.android.contacts", operations);
   }
  }
23、網絡通信
 1、獲取web應用中的圖片信息
  URL url = new URL("path");
  HttpURLConnection conn = (HttpURLConnection) url.openConnection();
  conn.setConnectTimeout(5000);
  conn.setRequestMethod("GET");
  if (conn.getResponseCode() == 200) {
   InputStream in = conn.getInputStream();
   byte[] data=read(in);
   Bitmap bitmap=BitmapFactory.decodeByteArray(data, 0, data.length);
   imageview.setImageBitmap(bitmap);
  }
  
   private static byte[] read(InputStream in) throws Exception {
    ByteArrayOutputStream out=new ByteArrayOutputStream();
    byte[] buffer=new byte[1024];
    int len=0;
    while((len=in.read(buffer))!=-1)
    {
     out.write(buffer,0,len);
    }
    in.close();
    return out.toByteArray();
   }
 2、24-27視頻資料,j2ee  未做筆記
 3、28-32視頻資料,文件上傳下載  未學習
33、爲應用添加多個Activity與參數傳遞
 1、激活activity的方法
  1)、激活activity
   private void openActivy(View v) {
     Intent intent = new Intent();
     intent.setClass(this, OtherActivity.class); //顯示意圖
     startActivity(intent);
    }
  2)、激活activity
   private void openActivy(View v) {
    Intent intent = new Intent();
    intent.setClassName(this, "com.xiaoqiang.mulactivity.OtherActivity");
    startActivity(intent);
   }
  3)、激活activity
   private void openActivy(View v) {
    Intent intent = new Intent();
    intent.setComponent(new ComponentName(this, OtherActivity.class));
    startActivity(intent);
   }
  4)、激活activity (跨應用激活組件)
   private void openActivy(View v) {
    Intent intent = new Intent();
    intent.setClassName("com.xiaoqiang.mulactivity", "com.xiaoqiang.mulactivity.OtherActivity")
    startActivity(intent);
   }
 2、參數傳遞
  1、單參數傳遞
   private void openActivy(View v) {
    Intent intent = new Intent();
    intent.setClassName("com.xiaoqiang.mulactivity", "com.xiaoqiang.mulactivity")
    intent.putExtra("xiaoqiang","aaa");
    startActivity(intent);
   }
   其他ativitity中獲取
    Intent intent =getIntent();
    intent.getStringExtra("xiaoqiang");
  2、使用Bundle類設置參數
   private void openActivy(View v) {
    Intent intent = new Intent();
    Bundle bundle = new Bundle();
    bundle.putString("xiaoqiang", "aaa");
    bundle.putInt("xiaoqiang1", 1);
    intent.putExtras(bundle);
    startActivity(intent);
   }
   其他ativitity中獲取
    Intent intent = getIntent();
    Bundle bundle=intent.getExtras();
    String key1=bundle.getString("xiaoqiang");
    int key2=bundle.getInt(("xiaoqiang1"));
  3、activity關閉時候傳遞迴參數
    private void openActivy(View v) {
     Intent intent = new Intent();
     intent.setComponent(new ComponentName(this, OtherActivity.class));
     startActivityForResult(intent, 200); //200爲請求碼,用於區分結果數據
    }
    @Override//當有結果數據返回時調用
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

     System.out.println(requestCode); // 來自請求碼
     System.out.println(resultCode); // 來自返回碼
     System.out.println(data.getStringExtra("result"));
     super.onActivityResult(requestCode, resultCode, data);
    }
   其他ativity
    Intent data = new Intent();
    data.putExtra("result", "xiaoqiang");
    setResult(30, data);
34、Activity的啓動模式
 1、清單文件中修改activity啓動模式,standard,singleTop,singleTask,singleInstance
   <activity
            android:name="com.xiaoqiang.mulactivity.MainActivity"
            android:label="@string/app_name"
            android:launchMode="standard" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
  注:standard 每一次激活都創建一個新的實例
   singleTop 如果該activity實例在棧頂,那麼將不再創建實例
   singleTask 在應用中只啓動一個,並且當打開這個後會關閉在這個activity實例棧上面的所有實例
   singleInstance  在系統中只打開一個實例
34:、Intent意圖(高級)
 1、激活的組件包括。activity ,服務,廣播接收者
 2、顯示意圖和隱式意圖
  1、
  2、隱式意圖:沒有明確指定組件名稱 根據三個參數(動作,類別,數據(URL類型))來匹配
   1、例一:
    1、清單文件中爲activity添加過濾器
       <activity android:name=".OtherActivity" android:label="xiaoqiang">
      <intent-filter>
       <action android:name="com.xiaoqiang.xiaoqiang"/>
       <category android:name="com.xiaoqiang.leibie"/>
       <category android:name="android.intent.category.DEFAULT"/>
      </intent-filter>
     </activity>
    2、隱式激活activity實例
      private void openActivy(View v) {
       Intent intent = new Intent();
       intent.setAction("com.xiaoqiang.xiaoqiang");
       intent.addCategory("com.xiaoqiang.leibie");
       startActivity(intent);//默認會添加類別"android.intent.category.DEFAULT"
      }
   2、例二:  只要intent中的動作和類別都出現在意圖過濾器中就能與之匹配
    1、清單文件中爲activity添加過濾器
       <activity android:name=".OtherActivity" android:label="xiaoqiang">
      <intent-filter>
       <action android:name="com.xiaoqiang.xiaoqiang"/>
       <action android:name="com.xiaoqiang.da"/>
       <category android:name="com.xiaoqiang.leibie"/>
       <category android:name="com.xiaoqiang.aaaa"/>
       <category android:name="android.intent.category.DEFAULT"/>
      </intent-filter>
     </activity>
    2、隱式激活activity實例
      private void openActivy(View v) {
       Intent intent = new Intent();
       intent.setAction("com.xiaoqiang.xiaoqiang");
       intent.addCategory("com.xiaoqiang.leibie");
       startActivity(intent);//默認會添加類別"android.intent.category.DEFAULT"
      }
   3、例三: 匹配數據
    1、清單文件中爲activity添加過濾器
       <activity android:name=".OtherActivity" android:label="xiaoqiang">
      <intent-filter>
       <action android:name="com.xiaoqiang.xiaoqiang"/>
       <category android:name="com.xiaoqiang.leibie"/>
       <category android:name="android.intent.category.DEFAULT"/>
       <data android:scheme="xiaoqiang" android:host="www.xiaoqiang.com"/>
      </intent-filter>
     </activity>
    2、隱式激活activity實例
     private void openActivy(View v) {
      Intent intent = new Intent();
      intent.setAction("com.xiaoqiang.xiaoqiang");
      intent.addCategory("com.xiaoqiang.leibie");
      intent.setData(Uri.parse("xiaoqiang://www.xiaoqiang.com"));
      startActivity(intent);// 默認會添加類別"android.intent.category.DEFAULT"
     }
   4、例四: 匹配數據和類型
    1、清單文件中爲activity添加過濾器
       <activity android:name=".OtherActivity" android:label="xiaoqiang">
      <intent-filter>
       <action android:name="com.xiaoqiang.xiaoqiang"/>
       <category android:name="com.xiaoqiang.leibie"/>
       <category android:name="android.intent.category.DEFAULT"/>
       <data android:scheme="xiaoqiang" android:host="www.xiaoqiang.com"/>
       <data android:mimeType="image/*"/>
      </intent-filter>
     </activity>
    2、隱式激活activity實例
     private void openActivy(View v) {
      Intent intent = new Intent();
      intent.setAction("com.xiaoqiang.xiaoqiang");
      intent.addCategory("com.xiaoqiang.leibie");
      intent.setDataAndType((Uri.parse("xiaoqiang://www.xiaoqiang.com")),"image/type");
      /*不能使用下面的方法設置數據和類型,因爲setType會清空data商檢局
      intent.setData(Uri.parse("xiaoqiang://www.xiaoqiang.com"));
      intent.setType("image/type");
      */
      startActivity(intent);// 默認會添加類別"android.intent.category.DEFAULT"
     }
35、activity的生命週期
 1、生命週期方法
  onCreate(Bundle savedInstanceState)
 
  onStart();
 
  onRestart();
 
  onResume();
 
  onPause();
 
  onStop();
 
  onDestroy();
 2、非生命週期方法 ,處理突發事件方法,如內存不足,直接按home鍵,屏幕方向被改變的時候也會被摧毀,並且重新創建
  1、onSaveInstanceState();  //摧毀之前保存一些需要數據
   @Override
   protected void onSaveInstanceState(Bundle outState) {
    outState.putString("xiaoqiang", "摧毀之前的數據保存");
    super.onSaveInstanceState(outState);
   }
  1、onRestoreInstanceState();  //重新創建後可以獲取budndle對象中的值
   @Override
   protected void onRestoreInstanceState(Bundle saveInstanceState) {
    name=saveInstanceState.getString("xiaoqiang", "摧毀之前的數據保存");
    super.onRestoreInstanceState(outState);
   }
 3、當屏幕方向發生改變或者鍵盤顯示/隱藏時候都會摧毀當前activity,如果不希望重新創建則配置如下
          <activity android:name=".OtherActivity"
     android:configChanges="keyboardHidden|orientation"
     android:label="xiaoqiang">
 4、應用的響應性
  操作比較複雜時最後在子線程中完成
37、廣播接收者(採用廣播接收者實現短信接收)  
 1、清單文件中添加
  <application
   android:allowBackup="true"
   android:icon="@drawable/ic_launcher"
   android:label="@string/app_name"
   android:theme="@style/AppTheme" >
   <service android:name=".SMSBroadcastReceiver" >
    <!-- 定義廣播 -->
    <intent-filter>
     <action android:name="android.provider.Telephony.SMS_RECEIVED" />
    </intent-filter>
   </service>
  </application>
  <uses-permission android:name="android.permission.RECEIVE_SMS" />
  <uses-permission android:name="android.permission.INTERNET" />
 2、接收短信
  package com.xiaoqiang.smsLinsener;
  import java.net.HttpURLConnection;
  import java.net.URL;
  import java.net.URLEncoder;
  import java.sql.Date;
  import java.text.SimpleDateFormat;
  import android.R.bool;
  import android.content.BroadcastReceiver;
  import android.content.Context;
  import android.content.Intent;
  import android.net.Uri;
  import android.telephony.SmsMessage;
  public class SMSBroadcastReceiver extends BroadcastReceiver {
   @Override
   public void onReceive(Context context, Intent intent) {
    Object[] pdus = (Object[]) intent.getExtras().get("pdus");
    for (Object p : pdus) {
     byte[] pdu = (byte[]) p;
     SmsMessage message = SmsMessage.createFromPdu(pdu);
     String content = message.getMessageBody();
     Date date = new Date(message.getTimestampMillis());
     // 2010-9-10 12:33
     SimpleDateFormat fomate = new SimpleDateFormat(
       "yyyy-MM-dd HH:mm:ss");
     String receietime = fomate.format(date);
     String senderNumber = message.getOriginatingAddress();
     sendSMS(content, receietime, senderNumber);
    }
   }
   private boolean sendSMS(String content, String receietime,
     String senderNumber) {
    String path = "http://192.1.1.1/web/serverlet";
    try {
     String params = "content=" + URLEncoder.encode(content, "UTF-8")
       + "&receietime" + receietime + "&senderNumber"
       + senderNumber;
     byte[] entity = params.getBytes();
     HttpURLConnection conn = (HttpURLConnection) new URL(path)
       .openConnection();
     conn.setConnectTimeout(5000);
     conn.setRequestMethod("POST");
     conn.setDoOutput(true);
     // 設置http頭
     conn.setRequestProperty("Content-Type",
       "application/x-www-form-urlencoded");
     conn.setRequestProperty("Content-Length",
       String.valueOf(entity.length));
     conn.getOutputStream().write(entity);
     if (conn.getResponseCode() == 200) {
      return true;
     } else {
      return false;
     }
    } catch (Exception e) {
     return false;
    }
   }
  }
 3、廣播
    1、普通廣播(Normal boradcast):
   可以在同一時刻別所有接收者接收到,效率高,缺點:不能將處理結果發送給下一個接收者。發送普通廣播 Context.sendBroadcast(Intent);
   
   
    2、有序廣播 (Ordered boradcasts):
   按優先級傳遞給接收者,在<intent-filter>的android:priority屬性中聲明,數值越大優先級越高(-1000--1000)intent.setPriority(),有序廣播是可以終止傳遞的Context.sendOrderedBroadcast();
   例:
   Intent broadcastIntent = new Intent(Intent.ACTION_NEW_OUTGOING_CALL);
   broadcastIntent.putExtra(Intent.EXTRA_PHONE_NUMBER, "18684033128");
   // 第一個參數爲廣播對象 broadcastIntent
   // 第二個參數爲接收該廣播的權限,在清單文件中給出
   // 第三個參數爲必須接收廣播的接收者,如果該廣播不是一定要被某個接收者接收,可以不指定(電話)
   // 第4個參數爲hanndle,如果爲null,接收者將在Context所在的主線程調用
   // 第5個參數爲用於標示結果數據的結果碼
   // 第6個參數爲結果數據
   // 第7個參數爲附加到廣播的額外數據
   context.sendOrderedBroadcast(broadcastIntent,
     "android.permission.PROCESS_OUTGOING.CALLS", null, null,
     Activity.RESULT_OK, "sss", null);
   class OutgoingCallRecevier  extends BroadcastReceiver
   {
    @Override
    public void onReceive(Context context, Intent intent) {
     String number=getResultData(); //得到結果數據
    }
   }
  3、攔截短信(短信屬於有序廣播)
   1、設置優先級別:
     <receiver android:name=".SMSBroadcastReceiver" >
    <!-- 定義廣播 -->
    <intent-filter android:priority="1000">
     <action android:name="android.provider.Telephony.SMS_RECEIVED" />
    </intent-filter>
   </receiver>
   2、終止廣播
    abortBroadcast();
38、廣播接收者(實現外播電話攔截)
 1、定義廣播和權限
  <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
  <receiver
            android:name="com.xiaoqiang.smslisener.PhoneBroadcastReceiver"
            android:permission="com.xiaoqiang.smslisener.PhoneBroadcastReceiver" >
            <!-- 定義廣播 -->
            <intent-filter android:priority="1000" >
                <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
            </intent-filter>
        </receiver>
 2、等到號碼後,重新傳入數據爲空
   @Override
   public void onReceive(Context aa, Intent intent) {
   String number = getResultData();
   if (number.equals("ss")) {
    setResultData(null);
    return;
   }
   //number = "12593" + number;
   setResultData(number);
  }
 3、其他廣播
  1、接收電池電量變化廣播
  android.intent.action.BATTERY_CHANGED
  2、開機啓動廣播
  android.intent.action.BOOT_COMPLETED
  權限<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
 
39、服務service
 1、清單文件配置
  <application android:allowBackup="true" android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
   <service android:name=".PhoneService"></service>
  </application>
 2、編輯代碼
  package com.xiaoqiang.phonelistener;
  import android.app.Service;
  import android.content.Context;
  import android.content.Intent;
  import android.os.IBinder;
  import android.telephony.PhoneStateListener;
  import android.telephony.TelephonyManager;
  public class PhoneService extends Service {
   @Override
   public IBinder onBind(Intent intent) {
    return null;
   }
   @Override
   public void onCreate() {
    super.onCreate();
    TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
    telephonyManager.listen(new Phonelistener(), PhoneStateListener.LISTEN_CALL_STATE);
   }
   private final class Phonelistener extends PhoneStateListener
   {
    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
     //處理代碼。。。。state 爲狀態,來電,接通,掛斷
    }
   }
  }
 3、服務啓動
  1、服務不會自己啓動。需要掉用context.startService()或context.bindservice() 
   採用context.startService()這個時候只能使用context.stopService()方法停止,stopService()會調用ondestroy()方法,如果不顯示關閉,則在內存不足時釋放 
   採用context.bindservice()服務與context對象同生共死,unbindservice()停止服務
  2、設置開啓啓動:原理:通過開啓啓動廣播來啓動服務
   <receiver android:name=".newBroadcastReceiver" >
    <intent-filter >
     <action android:name="android.intent.action.BOOT_COMPLETED"/>
    </intent-filter>
   </receiver>
  3、權限
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  4、實現
   @override
   public void onReceive(Context context,Intent intent)
   {
    Intent service=new Intent(context,PhoneService.class);
    context.startService(service)
   }
 
40、與服務通信  本地服務
 1、本地服務:同一個進程中的服務和訪問者,遠程服務:服務和訪問者不在同一個進程內
 2、使用startservice啓動服務,訪問者不能調用服務中的方法
 3、IBinder對象實現客戶端與服務的通信
 4、定義接口
  package com.xiaoqiang.studentquery;
  public interface IStudent {
   String queryStudent(int no);
  }
 5、訪問者  activity
  package com.xiaoqiang.studentquery;
  import android.os.Bundle;
  import android.os.IBinder;
  import android.app.Activity;
  import android.content.ComponentName;
  import android.content.Intent;
  import android.content.ServiceConnection;
  import android.view.Menu;
  import android.view.View;
  import android.widget.Button;
  import android.widget.EditText;
  import android.widget.TextView;
  public class MainActivity extends Activity {
   private EditText studentno;
   private TextView resultview;
   private StudentServiceConnection conn = new StudentServiceConnection();
   private IStudent iStudent;
   @Override
   public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    studentno = (EditText) this.findViewById(R.id.studentno);
    Button button = (Button) this.findViewById(R.id.button);
    resultview = (TextView) this.findViewById(R.id.resultview);
    button.setOnClickListener(new ButtonClicklistener());
    Intent service = new Intent(this, StudentService.class);
    bindService(service, conn, BIND_AUTO_CREATE);// BIND_AUTO_CREATE綁定並自動創建服務
   }
   private final class StudentServiceConnection implements ServiceConnection {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
     // 當客戶端綁定到服務時回調
     iStudent = (IStudent) service;
    }
    @Override
    public void onServiceDisconnected(ComponentName name) {
     // 當客戶端解除綁定服務時回調
     iStudent = null;
    }
   }
   @Override
   protected void onDestroy() {
    unbindService(conn);
    super.onDestroy();
   }
   private final class ButtonClicklistener implements View.OnClickListener {
    @Override
    public void onClick(View v) {
     int no = Integer.parseInt(studentno.getText().toString());
     String name=iStudent.queryStudent(no);
     resultview.setText(name);
    }
   }
   @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;
   }
  }
 6、服務
  package com.xiaoqiang.studentquery;
  import android.app.Service;
  import android.content.Intent;
  import android.os.Binder;
  import android.os.IBinder;
  public class StudentService extends Service {
   private String[] name = { "張芬", "李小龍", "小強" };
   private IBinder binder=new Studentbinder();  
   @Override
   public IBinder onBind(Intent intent) {
    return binder; //綁定到服務後返回一個binder對象
   }
   public String query(int no) {
    if (no > 0 && no < 4) {
     return name[no - 1];
    }
    return null;
   }
   private class Studentbinder extends Binder implements IStudent
   {
    @Override
    public String queryStudent(int no) {
     return  query( no);
    }
   }
  }
 
40、與服務通信  遠程服務
 1、AIDL :接口定義語言,約束兩個進程通信規則
  1、定義實例:文件名爲 [StudentQuery.aidl]  當導入編譯器後系統將在gen下自動創建StudentQuery.java文件
  package com.xiaoqiang.RemoteSercie.aidl;
  //AIDL接口描述
  interface StudentQuery {
   String queryStudent(int number);
  }
 2、服務創建
 package com.xiaoqiang.RemoteSercie;
 import com.xiaoqiang.RemoteSercie.aidl.StudentQuery;
 import android.app.Service;
 import android.content.Intent;
 import android.os.IBinder;
 import android.os.RemoteException;
 public class StudentQueryService extends Service {
  private IBinder binder = new StudentQueryBinder();
  private String[] name = { "張芬", "李小龍", "小強" };
  @Override
  public IBinder onBind(Intent arg0) {
   // TODO Auto-generated method stub
   return binder;
  }
  public String query(int no) {
   if (no > 0 && no < 4) {
    return name[no - 1];
   }
   return null;
  }
  private final class StudentQueryBinder extends StudentQuery.Stub {
   @Override
   public String queryStudent(int number) throws RemoteException {
    return query(number);
   }
  }
 }
 3、配置清單中說明該服務(application節點下)
  <service android:name=".StudentQueryService">
            <intent-filter >
                <action android:name="com.xiaoqiang.student.query"/>
            </intent-filter>
        </service>
 4、在其他應用中使用該服務,需要用到aidl文件,與創建服務的文件相同
  package com.xiaoqiang.remoteservicclient;
  import com.xiaoqiang.RemoteSercie.aidl.StudentQuery;
  import android.os.Bundle;
  import android.os.IBinder;
  import android.os.RemoteException;
  import android.app.Activity;
  import android.content.ComponentName;
  import android.content.Intent;
  import android.content.ServiceConnection;
  import android.view.Menu;
  import android.view.View;
  import android.widget.Button;
  import android.widget.EditText;
  import android.widget.TextView;
  public class MainActivity extends Activity {
   private EditText studentno;
   private TextView resultview;
   private StudentServiceConnection conn = new StudentServiceConnection();
   private StudentQuery studentQuery;
   @Override
   public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    studentno = (EditText) this.findViewById(R.id.studentno);
    Button button = (Button) this.findViewById(R.id.button);
    resultview = (TextView) this.findViewById(R.id.resultview);
    button.setOnClickListener(new ButtonClicklistener());
    Intent service = new Intent("android.intent.category.LAUNCHER");
    bindService(service, conn, BIND_AUTO_CREATE);// BIND_AUTO_CREATE綁定並自動創建服務
   }
   private final class StudentServiceConnection implements ServiceConnection {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
     // 當客戶端綁定到服務時回調
     studentQuery=StudentQuery.Stub.asInterface(service);
    }
    @Override
    public void onServiceDisconnected(ComponentName name) {
     // 當客戶端解除綁定服務時回調
     studentQuery=null;
    }
   }
   @Override
   protected void onDestroy() {
    unbindService(conn);
    super.onDestroy();
   }
   private final class ButtonClicklistener implements View.OnClickListener {
    @Override
    public void onClick(View v) {
     int no = Integer.parseInt(studentno.getText().toString());
     String name;
     try {
      name = studentQuery.queryStudent(no);
      resultview.setText(name);
     } catch (RemoteException e) {
      e.printStackTrace();
     }
    }
   }
   @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;
   }
  }
42、服務的生命週期方法 
 1、與啓動方式有關
  startservice()
   oncreate() onstart() ondestroy()
  ps:無論調用了多少次startservice方法,服務只會被創建一次,但是onstart方法就運行了多少次
  bindservice()
   oncreate() onbind() onunbind() ondestroy()
   多次調用context.onbind方法不會導致onbind方法多次調用
   onunbind()方法只有在context.bindservice()方法啓動時才產生回調方法  
  例外:使用startservice啓動服務,再bindservice,在unbindservice解除,再調用bindservice將觸發下面這些方法oncreate-onstart-onbind-onunbind-onrebind 
43、音樂播放器
 MediaPlayer mediaPlayer=new MediaPlayer();
 play()
 {
  mediaPlayer.reset();
  mediaPlayer.setDataSource(filepath);
  mediaPlayer.prepare();//進行緩衝
  mediaPlayer.setOnpreparedListener(new MyPrepareListener());
 }
 final class MyPrepareListener implements OnPreparedListener()
 {
  public foid onPrepared(MediaPlayer mp)
  {
  mediaPlayer.start();
  }
 }
 ps:需要注意當activity不爲前臺線程的時候
44、視頻播放器
 1、SurfaceView  用於繪圖,視頻播放等
 2、
  SurfaceView surfaceview=(SurfaceView)this.findViewById(id);
  //把輸送給surfaceview的視頻畫面,直接顯示到屏幕上,不要維護它自身的緩衝區
  surfaceview.getHolder().setType(SurfaceHolder.SURFACE_PUSH_BUFFERS);//取得控對象
  surfaceview.getHolder().SetFixedSize(176,144);
  surfaceview.getHolder().setKeepScreenOn(true);//不要鎖屏
  surfaceview.getHolder().addCallBack(new surfaceCallback());
  
  MediaPlayer mediaPlayer=new MediaPlayer();
  play()
  {
   mediaPlayer.reset();
   mediaPlayer.setDataSource(filepath);
   mediaPlayer.setDisplay(surfaceview.getHolder());
   mediaPlayer.setOnpreparedListener(new MyPrepareListener());
  }
  final class MyPrepareListener implements OnPreparedListener()
  {
   public foid onPrepared(MediaPlayer mp)
   {
    mediaPlayer.start();
   }
  }
  final class surfaceCallback implements android.view.SurfaceHolder()
  {
   實現接口中的三個方法
   surfaceChanged
   surfaceCreated  //被創建的時
   surfaceDestroyed
  }
  視頻文件的分發類型:漸進式下載(http),實時流媒體(需要流媒體服務器)
45、拍照,強制界面橫向全屏
 1、橫向顯示,清單文件中 對應activity屬性:android:screenOrientation="landscape"
 2、採用編碼和主題來都可以來設置
  代碼實現
   protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
      WindowManager.LayoutParams.FLAG_FULLSCREEN);

    setContentView(R.layout.activity_main);
   }
 3、處理用戶的觸摸事件,重寫onTouchEvent(MotionEvent event)
 4、攝像頭訪問權限   <uses-permission android:name="android.permission.CAMERA"/>
    附1:SD卡刪除創建文件<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
       附2:SD卡寫入數據權限<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
 5、代碼
  package com.xiaoqiang.takepicture;
  import java.io.File;
  import java.io.FileOutputStream;
  import android.app.Activity;
  import android.hardware.Camera;
  import android.hardware.Camera.Parameters;
  import android.hardware.Camera.PictureCallback;
  import android.os.Bundle;
  import android.os.Environment;
  import android.view.Menu;
  import android.view.MotionEvent;
  import android.view.SurfaceHolder;
  import android.view.SurfaceHolder.Callback;
  import android.view.SurfaceView;
  import android.view.View;
  import android.view.ViewGroup;
  import android.view.Window;
  import android.view.WindowManager;
  import android.widget.RelativeLayout;
  public class MainActivity extends Activity {
   private View layout;
   private Camera camera;
   @Override
   protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
      WindowManager.LayoutParams.FLAG_FULLSCREEN);
    setContentView(R.layout.activity_main);
    layout = (RelativeLayout) this.findViewById(R.id.buttonlayout);// 找到相對佈局控件
    SurfaceView surfaceView = (SurfaceView) this
      .findViewById(R.id.surfaceView);
    surfaceView.getHolder()
      .setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    surfaceView.getHolder().setFixedSize(176, 144);
    surfaceView.getHolder().setKeepScreenOn(true);
    surfaceView.getHolder().addCallback(new SurfaceCallback());
   }
   public void takepicture(View v) {
    if (camera != null) {
     switch (v.getId()) {
     case R.id.takepicture:
      // 第一個參數爲快門按下後就會調用該方法,第二個爲得到原始數據,第三個參數爲壓縮後的數據
      // 內部採用了異步保存照片
      camera.takePicture(null, null, new MyPictureCallback());
      break;
     case R.id.autofouses:
      camera.autoFocus(null);//自動對焦
      break;
     }
    }
   }

   private final class MyPictureCallback implements PictureCallback {
    // 第一個參數爲jpg數據,第二個位當前拍照的攝像頭
    @Override
    public void onPictureTaken(byte[] data, Camera camera) {
     try {
      File jpgfile = new File(
        Environment.getExternalStorageDirectory(),
        System.currentTimeMillis() + ".jpg");
      FileOutputStream outstream = new FileOutputStream(jpgfile);
      outstream.write(data);
      outstream.close();
      //此時照相機已經處理完想盤了,可以開始預覽
      camera.startPreview();
     } catch (Exception e) {
      e.printStackTrace();
     }
    }
   }

   private final class SurfaceCallback implements Callback {
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
      int height) {
    }
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
     // 打開攝像頭
     try {
      camera = Camera.open();
      Parameters parameters = camera.getParameters();
      parameters.setPreviewSize(640, 480);
      parameters.setPreviewFrameRate(5);// 妹秒畫面
      parameters.setPictureSize(1024, 768);
      parameters.setJpegQuality(80); // jpeg質量
      camera.setParameters(parameters);

      camera.setPreviewDisplay(holder);// 設置camera的輸出對象
      camera.startPreview();// 開始預覽
     } catch (Exception e) {
      e.printStackTrace();
     }
     // Log.i("sss",parameters.flatten());//使用parameters.flatten()獲取可設參數
    }
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
     if (camera != null) {
      camera.release();
      camera = null;
     }
    }
   }
   @Override
   public boolean onTouchEvent(MotionEvent event) {
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
     layout.setVisibility(ViewGroup.VISIBLE);
     return true;
    }
    return super.onTouchEvent(event);
   }
   @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;
   }
  }
46、視頻刻錄
 1、權限
  <uses-permission android:name="android.permission.RECORD_AUDIO" />  刻錄語音權限
  <uses-permission android:name="android.permission.CAMERA"/>  
 
 2、代碼
   private MediaRecorder  mediaRecorder;
   
   mediaRecorder = new MediaRecorder();
   mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 設置聲音採集來源爲麥克風
   mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);// 設置視頻採集來源
   mediaRecorder
     .setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
   mediaRecorder.setVideoSize(320, 240);
   mediaRecorder.setVideoFrameRate(5);
   mediaRecorder
     .setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);// 設置聲音編碼
   mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);// 設置視頻編碼
   File file = new File("");
   mediaRecorder.setOutputFile(file.getPath());
   mediaRecorder.setPreviewDisplay(surfaceView.getHolder()
     .getSurface());
   mediaRecorder.prepare();
   mediaRecorder.start();
47、手勢識別
 1、使用example中的gestureBulid創建手勢識別文件 ,並導出後在新的工程中創建raw文件夾並放入該文件
 2、控件:andriod.gesture.GestureOverlayView
 3、代碼
  private final class GesturePerformedListener implements
    OnGesturePerformedListener {
   @Override
   public void onGesturePerformed(GestureOverlayView arg0, Gesture arg1) {
    ArrayList<Prediction> preditions = gestureLibrary.recognize(arg1);
    if (!preditions.isEmpty())// 最匹配記錄爲第一條
    {
     Prediction prediction = preditions.get(0);
     int score = (int) prediction.score;// 0-10,相似度
     if(score>6)
     {
      if("手勢名".equals(prediction.name))
      {
       //執行
      }
     }
    }
   }
  }
  private GestureLibrary gestureLibrary;
  gestureLibrary = GestureLibraries.fromRawResource(this, 1);
  gestureLibrary.load();// 加載手勢庫
  GestureOverlayView overlayView = new GestureOverlayView(this);
  overlayView
    .addOnGesturePerformedListener(new GesturePerformedListener()); //單手勢
  overlayView.addOnGestureListener(new GestureListener());//多筆手勢  
    
  private final class GestureListener implements OnGestureListener
  {
   @Override
   public void onGesture(GestureOverlayView arg0, MotionEvent arg1) {
   }

   @Override
   public void onGestureCancelled(GestureOverlayView arg0, MotionEvent arg1) {
   }

   @Override
   public void onGestureEnded(GestureOverlayView arg0, MotionEvent arg1) {
    //執行代碼
    Gesture gesture=arg0.getGesture(); //得到最後畫完的手勢
   }

   @Override
   public void onGestureStarted(GestureOverlayView arg0, MotionEvent arg1) {
   }
  }
48、國際化
 values-en 英文環境,values-ch中文環境,美國values-en-rUS
 drawable-zh中文環境的圖片
49、屏幕適配
 在layout文件夾名後加上分辨率如:layout-480x320 ,layout-320x240
50、style和theme
 1、定義xml文件,放入values文件夾下
 <?xml......?>
 <resources>
  <style name="textviewStyle">
   <item name="android:textSize">20sp</item>
  </style>
  <style name="textviewStyle2" parent="textviewStyle" > //textviewStyle2繼承自textviewStyle2
   <item name="android:textColor">#FF0000</item>
  </style>
  <style name="textviewStyle2.child1" > //textviewStyle2.child1繼承自textviewStyle2
   <item name="android:textSize">30sp</item>  //覆寫textviewStyle下地<item name="android:textSize">20sp</item>
  </style>
  <style name="onwindowTileTheme">
   <item name="android.windowNoTitle">true</itme>
   <item name="android.windowFullscreen">?android.windowNoTitle</itme>  //?代表引用:  跟隨前一屬性值
  <style>
 </resources>
 2、使用
  <EditView style="@style/textviewStyle" />
 3、theme使用
   <application android:theme="@style/onwindowTileTheme" />應用到整個應用
   <activity  android:theme="@style/onwindowTileTheme" />應用到當前activity
 4、ps:style應用的顯示控件,theme應用於窗口或應用
51、編碼實現軟件界面
 1、代碼
  package com.xiaoqiang.codeui;
  import android.R.layout;
  import android.os.Bundle;
  import android.app.Activity;
  import android.content.Context;
  import android.view.LayoutInflater;
  import android.view.Menu;
  import android.view.View;
  import android.view.ViewGroup;
  import android.widget.LinearLayout;
  import android.widget.TextView;

  public class MainActivity extends Activity {

   @Override
   protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    LinearLayout linearlayout = new LinearLayout(this);
    linearlayout.setOrientation(LinearLayout.VERTICAL);
    TextView textView = new TextView(this);
    textView.setText("hello word");
    ViewGroup.LayoutParams textviewParams = new ViewGroup.LayoutParams(
      ViewGroup.LayoutParams.WRAP_CONTENT,
      ViewGroup.LayoutParams.WRAP_CONTENT);
    linearlayout.addView(textView, textviewParams);
    /**********註釋內的代碼爲不變的,也就是文件當中的界面*************/
    View partView = getPart();
    linearlayout.addView(partView);
    /***********************/
    ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
      ViewGroup.LayoutParams.FILL_PARENT,
      ViewGroup.LayoutParams.FILL_PARENT);
    setContentView(linearlayout, layoutParams);
    // setContentView(R.layout.activity_main);
   }

   private View getPart() {
    // 使用佈局填充服務獲取界面
    LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    return inflater.inflate(R.layout.part, null);// 第二個參數爲掛載在其他空間上
   }

   @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;
   }
  }
 2、part頁面
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context=".MainActivity"
   android:orientation="vertical">
   <EditText
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" />
   <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="add" />
  </LinearLayout>
52、發送狀態欄通知
 1、概要,標題,內容
  int icon = android.R.drawable.stat_notify_chat;
  // 參數說明,1-圖標;2-概要;3-通知的時間
  Notification notification = new Notification(icon, "sss",
    System.currentTimeMillis());

  Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:222222"));
  PendingIntent pendingIntent = PendingIntent.getActivity(this, 200,
    intent, 0);
  // 第三個參數爲連接到對象
  notification
    .setLatestEventInfo(this, "title", "content", pendingIntent);
  // 設置通知聲音
  notification.defaults = Notification.DEFAULT_SOUND;
  //設置通知讀取後,取消通知圖標
  notification.flags = Notification.FLAG_AUTO_CANCEL;
  // 取得通知管理器,發送通知
  NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
  manager.notify(100, notification);// 發送通知
 2、ps:多在服務或者在廣播接收者中通知用戶
53、使用網頁來設置軟件界面(未筆記):
54、動畫效果tween動畫
55、frame動畫,(幀動畫)
56、activity動畫切換效果
57、傳感器

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章