传智播客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、传感器

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

你可能感兴趣的:(android,学习笔记)