Bài tập 33: Sử dụng ContentProvider trong Android


– Bài tập này Tôi sẽ hướng dẫn các bạn cách sử dụng ContentProvider. Cụ thể là cách đọc danh bạ, cách đọc lịch sử cuộc gọi, cách đọc Media và bookmark.

– Phần này rất nhiều và phong phú, bạn cần khám phá nó trên mạng nhiều hơn.

– Thời gian không cho phép do đó Tôi chỉ hướng dẫn những tính năng mà ta thường xuyên sử dụng nhất.

– Tôi có giao diện chính sau:

33_contentprovider_0

– Ta có cú pháp tổng quát:

 <standard_prefix>://<authority>/<data_path>/<id>

– Ví dụ để lấy tất cả các bookmark trong trình duyệt ta dùng cú pháp:

content://browser/bookmarks

– Để lấy toàn bộ danh bạ trong điện thoại ta dùng cú pháp:

content://contacts/people

– Để lấy 1 contact theo 1 định danh nào đó:

content://contacts/people/3

– Để lấy các kết quả trả về ta cũng dùng Cursor để quản lý.

– Có 2 cách sử dụng hàm lấy kết quả ở đây:

Cách 1:

CursorLoader loader=new  CursorLoader(context, uri, null, null, null, null);

Cursor c=loader.loadInBackground();

cách 2:

Cursor c = getContentResolver() .query(uri, null, null, null, null);

– Ta sẽ làm cụ thể từng chức năng trong ví dụ trên

– Bạn xem cấu trúc của bài tập này:

33_contentprovider_1

– Bạn xem XML Resource của màn hình chính (activity_main.xml):


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:id="@+id/LinearLayout1"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical"
 tools:context=".MainActivity" >

<Button
 android:id="@+id/btnshowallcontact"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:text="Show All Contact" />

<Button
 android:id="@+id/btnaccesscalllog"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:text="Access The Call Log" />

<Button
 android:id="@+id/btnmediastore"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:text="Access Media Store" />

<Button
 android:id="@+id/btnaccessbookmarks"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:text="Access Bookmarks" />

</LinearLayout>

– Source code xử lý MainActivity.java:


package tranduythanh.com;

import android.os.Bundle;
import android.provider.Browser;
import android.provider.CallLog;
import android.provider.CallLog.Calls;
import android.provider.MediaStore;
import android.provider.MediaStore.Audio.Media;
import android.app.Activity;
import android.content.CursorLoader;
import android.content.Intent;
import android.database.Cursor;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener{

Button btnshowallcontact;
 Button btnaccesscalllog;
 Button btnaccessmediastore;
 Button btnaccessbookmarks;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 btnshowallcontact=(Button) findViewById(R.id.btnshowallcontact);
 btnshowallcontact.setOnClickListener(this);
 btnaccesscalllog=(Button) findViewById(R.id.btnaccesscalllog);
 btnaccesscalllog.setOnClickListener(this);
 btnaccessmediastore=(Button) findViewById(R.id.btnmediastore);
 btnaccessmediastore.setOnClickListener(this);
 btnaccessbookmarks=(Button) findViewById(R.id.btnaccessbookmarks);
 btnaccessbookmarks.setOnClickListener(this);
 }

@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;
 }

@Override
 public void onClick(View v) {
 Intent intent=null;
 if(v==btnshowallcontact)
 {
 intent=new Intent(this, ShowAllContactActivity.class);
 startActivity(intent);
 }
 else if(v==btnaccesscalllog)
 {
 accessTheCallLog();
 }
 else if(v==btnaccessmediastore)
 {
 accessMediaStore();
 }
 else if(v==btnaccessbookmarks)
 {
 accessBookmarks();
 }
 }
 /**
 * hàm lấy danh sách lịch sử cuộc gọi
 * với thời gian nhỏ hơn 30 giây và sắp xếp theo ngày gọi
 */
 public void accessTheCallLog()
 {
 String [] projection=new String[]{
 Calls.DATE,
 Calls.NUMBER,
 Calls.DURATION
 };
 Cursor c=getContentResolver().query(
 CallLog.Calls.CONTENT_URI,
 projection,
 Calls.DURATION+"<?",new String[]{"30"},
 Calls.DATE +" Asc");
 c.moveToFirst();
 String s="";
 while(c.isAfterLast()==false){
 for(int i=0;i<c.getColumnCount();i++){
 s+=c.getString(i)+" - ";
 }
 s+="\n";
 c.moveToNext();
 }
 c.close();
 Toast.makeText(this, s, Toast.LENGTH_LONG).show();
 }
 /**
 * hàm đọc danh sách các Media trong SD CARD
 */
 public void accessMediaStore()
 {
 String []projection={
 MediaStore.MediaColumns.DISPLAY_NAME,
 MediaStore.MediaColumns.DATE_ADDED,
 MediaStore.MediaColumns.MIME_TYPE
 };
 CursorLoader loader=new CursorLoader
 (this, Media.EXTERNAL_CONTENT_URI,
 projection, null, null, null);
 Cursor c=loader.loadInBackground();
 c.moveToFirst();
 String s="";
 while(!c.isAfterLast()){
 for(int i=0;i<c.getColumnCount();i++){
 s+=c.getString(i)+" - ";
 }
 s+="\n";
 c.moveToNext();
 }
 Toast.makeText(this, s, Toast.LENGTH_LONG).show();
 c.close();
 }
 /**
 * hàm đọc danh sách Bookmark trong trình duyệt
 */
 public void accessBookmarks()
 {
 String []projection={
 Browser.BookmarkColumns.TITLE,
 Browser.BookmarkColumns.URL,
 };
 Cursor c=getContentResolver()
 .query(Browser.BOOKMARKS_URI, projection,
 null, null, null);
 c.moveToFirst();
 String s="";
 int titleIndex=c.getColumnIndex
 (Browser.BookmarkColumns.TITLE);
 int urlIndex=c.getColumnIndex
 (Browser.BookmarkColumns.URL);
 while(!c.isAfterLast())
 {
 s+=c.getString(titleIndex)+" - "+
 c.getString(urlIndex);
 c.moveToNext();
 }
 c.close();
 Toast.makeText(this, s, Toast.LENGTH_LONG).show();
 }
}

– Source XML xử lý xem danh bạn (activity_show_all_contact.xml):


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:id="@+id/LinearLayout1"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical"
 tools:context=".ShowAllContactActivity" >

<ListView
 android:id="@+id/listView1"
 android:layout_width="match_parent"
 android:layout_height="wrap_content" >
 </ListView>

<Button
 android:id="@+id/btnback"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="Back" />

</LinearLayout>

– Source code xử lý xem danh bạ ( ShowAllContactActivity.java):

– Tôi viết theo 2 cách : Dùng CursorLoader và getContentResolver


package tranduythanh.com;
import java.util.ArrayList;

import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.app.Activity;
import android.content.CursorLoader;
import android.database.Cursor;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;

public class ShowAllContactActivity extends Activity {
 Button btnback;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_show_all_contact);
 btnback=(Button) findViewById(R.id.btnback);
 btnback.setOnClickListener(new OnClickListener() {

 @Override
 public void onClick(View v) {
 // TODO Auto-generated method stub
 finish();
 }
 });
 showAllContacts1();
 }
 /**
 * hàm danh toàn bộ danh bạ
 * dùng CursorLoader
 */
 public void showAllContacts1()
 {
 Uri uri=Uri.parse("content://contacts/people");
 ArrayList<String> list=new ArrayList<String>();
 CursorLoader loader=new
 CursorLoader(this, uri, null, null, null, null);
 Cursor c1=loader.loadInBackground();
 c1.moveToFirst();
 while(c1.isAfterLast()==false){
 String s="";
 String idColumnName=ContactsContract.Contacts._ID;
 int idIndex=c1.getColumnIndex(idColumnName);
 s=c1.getString(idIndex)+" - ";
 String nameColumnName=ContactsContract.Contacts.DISPLAY_NAME;
 int nameIndex=c1.getColumnIndex(nameColumnName);
 s+=c1.getString(nameIndex);
 c1.moveToNext();
 list.add(s);
 }
 c1.close();
 ListView lv=(ListView) findViewById(R.id.listView1);
 ArrayAdapter<String>adapter=new ArrayAdapter<String>(this,
 android.R.layout.simple_list_item_1, list);
 lv.setAdapter(adapter);
 }
 /**
 * hàm danh toàn bộ danh bạ
 * dùng getContentResolver
 */
 public void showAllContacts2()
 {
 Uri uri=Uri.parse("content://contacts/people");
 ArrayList<String> list=new ArrayList<String>();
 Cursor c1=getContentResolver()
 .query(uri, null, null, null, null);
 c1.moveToFirst();
 while(c1.isAfterLast()==false)
 {
 String s="";
 String idColumnName=ContactsContract.Contacts._ID;
 int idIndex=c1.getColumnIndex(idColumnName);
 s=c1.getString(idIndex)+" - ";
 String nameColumnName=ContactsContract.Contacts.DISPLAY_NAME;
 int nameIndex=c1.getColumnIndex(nameColumnName);
 s+=c1.getString(nameIndex);
 c1.moveToNext();
 list.add(s);
 }
 c1.close();
 ListView lv=(ListView) findViewById(R.id.listView1);
 ArrayAdapter<String>adapter=new ArrayAdapter<String>(this,
 android.R.layout.simple_list_item_1, list);
 lv.setAdapter(adapter);
 }
 @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_show_all_contact, menu);
 return true;
 }

}

– Lưu ý cấp quyền cho ứng dụng:

AndroidManifest.xml:


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 package="tranduythanh.com"
 android:versionCode="1"
 android:versionName="1.0" >

<uses-sdk
 android:minSdkVersion="14"
 android:targetSdkVersion="17" />

<uses-permission android:name="android.permission.READ_CONTACTS" />
 <uses-permission android:name="android.permission.READ_CALL_LOG" />
 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
 <uses-permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS" />

<application
 android:allowBackup="true"
 android:icon="@drawable/ic_launcher"
 android:label="@string/app_name"
 android:theme="@style/AppTheme" >
 <activity
 android:name="tranduythanh.com.MainActivity"
 android:label="@string/app_name" >
 <intent-filter>
 <action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
 </intent-filter>
 </activity>
 <activity
 android:name="tranduythanh.com.ShowAllContactActivity"
 android:label="@string/title_activity_show_all_contact" >
 </activity>
 </application>

</manifest>

– Dòng 11, 12, 13, 14 là cấp quyền cho ứng dụng có thể truy suất các chức năng mong muốn.

– Bây giờ bạn thực hiện ứng dụng và quan sát, giờ Tôi chạy lên và dùng chức năng xem toàn bộ danh bạ:

33_contentprovider_2– Tương tự như vậy bản thử các chức năng còn lại trong ứng dụng.

– Bạn có thể tải coding mẫu đầy đủ ở đây: http://www.mediafire.com/download/kaac7d36ocvr8ba/LearnContentProvider.rar

– Bài tập kế tiếp các bạn sẽ được học về một kỹ thuật hoàn toàn mới trong Android và rất khó và rất hữu dụng, đó là kỹ thuật xử lý Đa Tiến Trình trong Android. Các bạn phải chú ý theo dõi vì nó vô cùng quan trọng, nó cũng giống như Intent là huyết mạch trong các ứng dụng của Android.

– Chúc các bạn thành công.

4 responses

  1. Cho em hỏi xíu! Tại sao nó cứ bị báo lỗi ở Cursorloader vậy ạ

  2. Lỗi Cursor do Android 6.0 nó cảnh báo , cần thêm checkSelfPermission trong hàm

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s