編輯:Android編程入門
內容提供器(Content Provider)主要用於在不同的應用程序之間實現數據共享的功能,它提供了一套完整的機制,允許一個程序訪問另一個程序中的數據,同時還能保證被訪數據的安全性。目前,使用內容提供器是Android 實現跨程序共享數據的標准方式。不同於文件存儲和SharedPreferences 存儲中的兩種全局可讀寫操作模式,內容提供器可以選擇只對哪一部分數據進行共享,從而保證我們程序中的隱私數據不會有洩漏的風險。接下來,我們開始內容提供器的學習。content provider的原理說明,參見另外一篇博客(android高級---->ContentProvider的源碼分析)
目錄導航:
一、 內容提供器的用法:
二、 ContentResolver的基本用法:
三、 內容URI的基本介紹:
創建一個簡單項目,結構如下:
一、 在activity_main.xml文件中創建一個ListView的布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ListView android:id="@+id/listView" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout>
二、 在MainActivity.java中:
package com.example.linux.getcontact; import android.database.Cursor; import android.os.Bundle; import android.provider.ContactsContract; import android.support.v7.app.AppCompatActivity; import android.widget.ArrayAdapter; import android.widget.ListView; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { private ListView listView; ArrayAdapter<String> adapter; List<String> contactsList = new ArrayList<String>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listView = (ListView) findViewById(R.id.listView); adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, contactsList); listView.setAdapter(adapter); readContacts(); } private void readContacts() { Cursor cursor = null; try { // 查詢聯系人數據 cursor = getContentResolver().query( ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null); while (cursor.moveToNext()) { // 獲取聯系人姓名 String displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)); // 獲取聯系人手機號 String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); contactsList.add(displayName + "\n" + number); } } catch (Exception e) { e.printStackTrace(); } finally { if (cursor != null) { cursor.close(); } } } }
三、 讀取系統聯系人是需要聲明權限的,在AndroidManifest.xml中增加權限:
<uses-permission android:name="android.permission.READ_CONTACTS" />
上一個自己的程序中訪問其他應用程序的數據。總體來說思路還是非常簡單的,只需要獲取到該應用程序的內容URI,然後借助ContentResolver進行CRUD 操作就可以了。以下我們創建自己的內容提供器。
項目結構:
一、 創建一個與數據庫表對應的Bean:Person.java:
package com.example.linux.contentproviderserver.model; /** * Created by Linux on 2016/3/4. */ public class Person { private Integer _id; private String name; private String age; public Integer get_id() { return _id; } public void set_id(Integer _id) { this._id = _id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } }
二、 接著建立一個關於數據庫的工具類:DBOpenHelper.java
package com.example.linux.contentproviderserver.util; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; /** * Created by Linux on 2016/3/4. */ public class DBOpenHelper extends SQLiteOpenHelper { private static final String DATABASE_NAME = "person.db"; //數據庫名稱 private static final int DATABASE_VERSION = 1;//數據庫版本 private static final String CREATE_TABLE_PERSON = "CREATE TABLE person (_id integer primary key autoincrement, name varchar(20), age varchar(10))"; private static final String DROP_TABLE_PERSON = "DROP TABLE IF EXISTS person"; public DBOpenHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(CREATE_TABLE_PERSON); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL(DROP_TABLE_PERSON); onCreate(db); } }
三、 創建一個自己的繼承了ContentProvider的內容提供器:PersonProvider.java
private final static String TAG = "PersonProvider"; private DBOpenHelper dbOpenHelper; private static final UriMatcher MATCHER = new UriMatcher(UriMatcher.NO_MATCH); private static final int PERSONS = 1; private static final int PERSON = 2; private static final String AUTHORITY = "com.example.linux.contentproviderserver.action.PersonProvider"; private static final String PATH_1 = "person"; private static final String PATH_2 = "person/#"; static { Log.i(TAG, "on PersonProvider static"); MATCHER.addURI(AUTHORITY, PATH_1, PERSONS); MATCHER.addURI(AUTHORITY, PATH_2, PERSON); } @Override public boolean onCreate() { Log.i(TAG, "on PersonProvider create"); this.dbOpenHelper = new DBOpenHelper(this.getContext()); return false; }
// 插入person表中的所有記錄 /person // 插入person表中指定id的記錄 /person/10 @Override public Uri insert(Uri uri, ContentValues values) { Log.i(TAG, "uri: " + uri.getPath() + ", values: " + values.getAsString("name")); SQLiteDatabase db = dbOpenHelper.getWritableDatabase(); switch (MATCHER.match(uri)) { case PERSONS: // 特別說一下第二個參數是當name字段為空時,將自動插入一個NULL。 long rowid = db.insert("person", "name", values); Uri insertUri = ContentUris.withAppendedId(uri, rowid);// 得到代表新增記錄的Uri this.getContext().getContentResolver().notifyChange(uri, null); return insertUri; case PERSON: Log.i("some", "soem"); return null; default: throw new IllegalArgumentException("Unkwon Uri:" + uri.toString()); } }
@Override public int delete(Uri uri, String selection, String[] selectionArgs) { SQLiteDatabase db = dbOpenHelper.getWritableDatabase(); int count = 0; switch (MATCHER.match(uri)) { case PERSONS: count = db.delete("person", selection, selectionArgs); return count; case PERSON: long id = ContentUris.parseId(uri); String where = "_id=" + id; if (selection != null && !"".equals(selection)) { where = selection + " and " + where; } count = db.delete("person", where, selectionArgs); return count; default: throw new IllegalArgumentException("Unkwon Uri:" + uri.toString()); } }
@Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { SQLiteDatabase db = dbOpenHelper.getWritableDatabase(); int count = 0; switch (MATCHER.match(uri)) { case PERSONS: count = db.update("person", values, selection, selectionArgs); return count; case PERSON: long id = ContentUris.parseId(uri); String where = "_id=" + id; if (selection != null && !"".equals(selection)) { where = selection + " and " + where; } count = db.update("person", values, where, selectionArgs); return count; default: throw new IllegalArgumentException("Unkwon Uri:" + uri.toString()); } }
@Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { Log.i(TAG, "PersonProvider query"); SQLiteDatabase db = dbOpenHelper.getReadableDatabase(); int matchResult = MATCHER.match(uri); switch (MATCHER.match(uri)) { case PERSONS: return db.query("person", projection, selection, selectionArgs, null, null, sortOrder); case PERSON: long id = ContentUris.parseId(uri); String where = "_id=" + id; if (selection != null && !"".equals(selection)) { where = selection + " and " + where; } return db.query("person", projection, where, selectionArgs, null, null, sortOrder); default: throw new IllegalArgumentException("Unkwon Uri:" + uri.toString()); } }
//返回數據的MIME類型。 @Override public String getType(Uri uri) { Log.i(TAG, "PersonProvider get type"); switch (MATCHER.match(uri)) { case PERSONS: return "vnd.android.cursor.dir/person"; case PERSON: return "vnd.android.cursor.item/person"; default: throw new IllegalArgumentException("Unkwon Uri:" + uri.toString()); } }
五、 在MainActivity方法,為了方便得到數據庫中的數據,添加了查詢與增加方法:
package com.example.linux.contentproviderserver; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.Toast; import com.example.linux.contentproviderserver.util.DBOpenHelper; /** * writer: huhx * 內容提供器的服務端 */ public class MainActivity extends AppCompatActivity { private final static String TAG = "PersonProvider"; private DBOpenHelper dbOpenHelper; SQLiteDatabase database = null; private StringBuffer stringBuffer = null; @Override protected void onCreate(Bundle savedInstanceState) { Log.i(TAG, "main on create."); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); dbOpenHelper = new DBOpenHelper(this); database = dbOpenHelper.getWritableDatabase(); } // 查詢所有的數據 public void queryAll(View view) { stringBuffer = new StringBuffer(); Cursor cursor = database.rawQuery("select * from person", null); cursor.moveToFirst(); while(cursor.moveToNext()) { String name = cursor.getString(1); int age = cursor.getInt(2); stringBuffer.append("name: " + name + ", age: " + age + "\n"); } if (stringBuffer.toString().equals("")) { Toast.makeText(MainActivity.this, "nothing", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(MainActivity.this, stringBuffer, Toast.LENGTH_SHORT).show(); } } //插入數據 public void insertData(View view) { Object[] object = new Object[]{"linux", 23}; database.execSQL("insert into person(name, age) values(?, ?)", object); } @Override protected void onDestroy() { super.onDestroy(); database.close(); } }
項目結構:
一、在MainActivity中增加了查詢與插入功能:
package com.example.linux.contentproviderclient; import android.content.ContentResolver; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Toast; /** * 內容提供器的客戶端 */ public class MainActivity extends AppCompatActivity { private StringBuffer stringBuffer = new StringBuffer(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } // 插入數據 public void insert(View view) { ContentResolver contentResolver = getContentResolver(); Uri insertUri = Uri.parse("content://com.example.linux.contentproviderserver.action.PersonProvider/person"); ContentValues values = new ContentValues(); values.put("name", "wangkuifeng"); values.put("age", 23); Uri uri = contentResolver.insert(insertUri, values); Toast.makeText(MainActivity.this, "insert success: " + uri, Toast.LENGTH_SHORT).show(); } // 查詢數據 public void query(View view) { ContentResolver contentResolver = getContentResolver(); Uri queryUri = Uri.parse("content://com.example.linux.contentproviderserver.action.PersonProvider/person/5"); Cursor queryResult = contentResolver.query(queryUri, null, null, null, null); int count = queryResult.getCount(); for (queryResult.moveToFirst(); !queryResult.isAfterLast(); queryResult.moveToNext()) { String name = queryResult.getString(1); int age = queryResult.getInt(2); stringBuffer.append("name: " + name + ", age: " + age + "\n"); } Toast.makeText(MainActivity.this, stringBuffer.toString() + "\ncount: " + count, Toast.LENGTH_SHORT).show(); queryResult.close(); } }
一、基本概念最權威和官方的介紹請看google的api文檔http://developer.android.com/training/basics/actionbar/s
一,簡述線程池:線程池是如何工作的:一系列任務出現後,根據自己的線程池安排任務進行。如圖: 線程池的好處:重用線程池中的線程,避免因為線程的創建和銷毀所帶來的性能開銷。能
Android 意圖(Intent)和過濾器(Filter)Android意圖是一個要執行的操作的抽象描述。它可以通過 startActivity 來啟動
如果說Android上的app是一個有血有肉的人的話,那麼人靠衣裝馬靠鞍,那麼控件就是把app裝扮的漂漂亮亮的“衣服”。那麼安卓的控件到底是如何架