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、傳感器