實(shí)例解析Android系統(tǒng)中的ContentProvider組件用法
ContentProvider為Android四大組件之一,主要用來(lái)應(yīng)用程序之間的數(shù)據(jù)共享,也就是說(shuō)一個(gè)應(yīng)用程序用ContentProvider將自己的數(shù)據(jù)暴露出來(lái),其他應(yīng)用程序通過(guò)ContentResolver來(lái)對(duì)其暴露出來(lái)的數(shù)據(jù)進(jìn)行增刪改查。
ContenProvider與ContentResolver之間的對(duì)話同過(guò)Uri(通用資源標(biāo)識(shí)符),一個(gè)不恰當(dāng)?shù)谋扔骶秃孟駷g覽器要顯示一個(gè)網(wǎng)頁(yè)要有一個(gè)東西發(fā)送請(qǐng)求,這相當(dāng)于ContentResolver,你要拿東西就要知道去哪里拿,你就得知道服務(wù)器的域名或網(wǎng)址,而這個(gè)網(wǎng)址就相當(dāng)于Uri,當(dāng)?shù)竭_(dá)服務(wù)器的時(shí)候服務(wù)器要有個(gè)東西來(lái)處理,這就相當(dāng)于ContenProvider。
A程序通過(guò)ContenProvider來(lái)暴露數(shù)據(jù)的基本步驟:
1、實(shí)現(xiàn)一個(gè)ContenProvider的子類(lèi),并重寫(xiě)query,insert,update,delete等這幾個(gè)方法,
2、在androidmanifest.xml中注冊(cè)ContenProvider,指定的android:authorities屬性
B程序通過(guò)ContentResolver來(lái)操作A程序暴露出來(lái)的數(shù)據(jù)的基本步驟
1、通過(guò)content的getContentResolver()來(lái)獲取ContentResolver對(duì)象
2、通過(guò)ContentResolver對(duì)象來(lái)query,insert,update,delete來(lái)進(jìn)行操作
在實(shí)現(xiàn)query,insert,update,delete時(shí)有一個(gè)重要的參數(shù)Uri類(lèi),Uri一個(gè)中要的方法Uri.parse(String str)用來(lái)解析str字符串,而str字符串格式一般都有A程序提供給B程序,B程序按照指定的格式去請(qǐng)求 。比如:content//:com.android.xiong.ConentProviderTestA.firstContentProvider/xiong 其格式一般分為三個(gè)部分:content//:這部分是固定不變的 而com.android.xiong.ConentProviderTestA.firstContentProvider表A程序在androidmanifest.xml注冊(cè)的android:authorities屬性,xiong則表示資源部分
<provider
android:name="com.android.xiong.conentprovidertesta.FirstContentProvider"
android:authorities="com.android.xiong.ConentProviderTestA.firstContentProvider"
android:exported="true" >
</provider>
實(shí)例如下


A程序:
UserInfo.java
package com.android.xiong.conentprovidertesta;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
public class FirstContentProvider extends ContentProvider {
// UriMatcher類(lèi)主要用來(lái)匹配Uri
private static final UriMatcher uriMatcher = new UriMatcher(
UriMatcher.NO_MATCH);
private MySqlite mysqlite;
static {
// 注冊(cè)向外部程序提供的Uri
uriMatcher.addURI(UserInfo.AUTOR, "userinfo", 1);
uriMatcher.addURI(UserInfo.AUTOR, "userinfoall", 2);
}
//刪除數(shù)據(jù)
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int number = 0;
if (uriMatcher.match(uri) == 1) {
// 根據(jù)條件刪除數(shù)據(jù),并獲取刪除的行數(shù)
number = mysqlite.getReadableDatabase().delete("user_info",
selection, selectionArgs);
}
// 通知數(shù)據(jù)已經(jīng)改變
getContext().getContentResolver().notifyChange(uri, null);
return number;
}
@Override
public String getType(Uri uri) {
return null;
}
//插入數(shù)據(jù)
@Override
public Uri insert(Uri uri, ContentValues values) {
String name = values.getAsString(UserInfo.User.NAME).toString();
String age = values.getAsInteger(UserInfo.User.AGE).toString();
String maxId = "select max(id) id from user_info";
Cursor cursor = mysqlite.getReadableDatabase().rawQuery(maxId, null);
cursor.moveToFirst();
int userid = cursor.getInt(0) + 1;
if (uriMatcher.match(uri) == 1) {
mysqlite.getWritableDatabase().execSQL(
"insert into user_info values(?,?,?)",
new String[] { String.valueOf(userid), name, age });
}
return uri;
}
// 連接數(shù)據(jù)庫(kù)
@Override
public boolean onCreate() {
mysqlite = new MySqlite(getContext(), "userinfo.db", null, 1);
return true;
}
//查詢數(shù)據(jù)
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteDatabase sqlite = mysqlite.getReadableDatabase();
String str = "select name,age from user_info";
if (uriMatcher.match(uri) == 1) {
str += " where " + selection;
}
Cursor cursor = sqlite.rawQuery(str, selectionArgs);
return cursor;
}
//修改數(shù)據(jù)
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
SQLiteDatabase sqlite = mysqlite.getReadableDatabase();
int number = 0;
if (uriMatcher.match(uri) == 1) {
number = sqlite.update("user_info", values, selection,
selectionArgs);
}
return number;
}
}
FirstContentProvider.java
package com.android.xiong.conentprovidertesta;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
public class FirstContentProvider extends ContentProvider {
// UriMatcher類(lèi)主要用來(lái)匹配Uri
private static final UriMatcher uriMatcher = new UriMatcher(
UriMatcher.NO_MATCH);
private MySqlite mysqlite;
static {
// 注冊(cè)向外部程序提供的Uri
uriMatcher.addURI(UserInfo.AUTOR, "userinfo", 1);
uriMatcher.addURI(UserInfo.AUTOR, "userinfoall", 2);
}
//刪除數(shù)據(jù)
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int number = 0;
if (uriMatcher.match(uri) == 1) {
// 根據(jù)條件刪除數(shù)據(jù),并獲取刪除的行數(shù)
number = mysqlite.getReadableDatabase().delete("user_info",
selection, selectionArgs);
}
// 通知數(shù)據(jù)已經(jīng)改變
getContext().getContentResolver().notifyChange(uri, null);
return number;
}
@Override
public String getType(Uri uri) {
return null;
}
//插入數(shù)據(jù)
@Override
public Uri insert(Uri uri, ContentValues values) {
String name = values.getAsString(UserInfo.User.NAME).toString();
String age = values.getAsInteger(UserInfo.User.AGE).toString();
String maxId = "select max(id) id from user_info";
Cursor cursor = mysqlite.getReadableDatabase().rawQuery(maxId, null);
cursor.moveToFirst();
int userid = cursor.getInt(0) + 1;
if (uriMatcher.match(uri) == 1) {
mysqlite.getWritableDatabase().execSQL(
"insert into user_info values(?,?,?)",
new String[] { String.valueOf(userid), name, age });
}
return uri;
}
// 連接數(shù)據(jù)庫(kù)
@Override
public boolean onCreate() {
mysqlite = new MySqlite(getContext(), "userinfo.db", null, 1);
return true;
}
//查詢數(shù)據(jù)
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteDatabase sqlite = mysqlite.getReadableDatabase();
String str = "select name,age from user_info";
if (uriMatcher.match(uri) == 1) {
str += " where " + selection;
}
Cursor cursor = sqlite.rawQuery(str, selectionArgs);
return cursor;
}
//修改數(shù)據(jù)
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
SQLiteDatabase sqlite = mysqlite.getReadableDatabase();
int number = 0;
if (uriMatcher.match(uri) == 1) {
number = sqlite.update("user_info", values, selection,
selectionArgs);
}
return number;
}
}
MySqlite.java
package com.android.xiong.conentprovidertesta;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
public class MySqlite extends SQLiteOpenHelper {
static final String sql = "create table user_info(id int,name varchar(30),age int)";
public MySqlite(Context context, String name, CursorFactory factory,
int version) {
super(context, name, factory, version);
// TODO Auto-generated constructor stub
}
@Override
public void onCreate(SQLiteDatabase db) {
//創(chuàng)建數(shù)據(jù)表
db.execSQL(sql);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
}
}
MainActivity.java
package com.android.xiong.conentprovidertesta;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
public class MySqlite extends SQLiteOpenHelper {
static final String sql = "create table user_info(id int,name varchar(30),age int)";
public MySqlite(Context context, String name, CursorFactory factory,
int version) {
super(context, name, factory, version);
// TODO Auto-generated constructor stub
}
@Override
public void onCreate(SQLiteDatabase db) {
//創(chuàng)建數(shù)據(jù)表
db.execSQL(sql);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
}
}
activity_main.xml
<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"
android:orientation="vertical"
tools:context=".MainActivity" >
<TextView
android:id="@+id/txt1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="添加信息"
android:textSize="20dp" />
<EditText
android:id="@+id/ed1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="添加name" />
<EditText
android:id="@+id/ed2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="添加age"
android:inputType="number" />
<Button
android:id="@+id/bt1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="提交數(shù)據(jù)" />
<ListView
android:id="@+id/lists"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<TextView
android:id="@+id/item_txt1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/item_txt2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
B程序
UserInfo.java
package com.android.xiong.contentprovidertestb;
//向外部程序提供一個(gè)工具類(lèi)
public class UserInfo {
// 獲取ContentProvider的“域名”
public static final String AUTOR = "com.android.xiong.ConentProviderTestA.firstContentProvider";
//定義一個(gè)靜態(tài)內(nèi)部類(lèi),提供ContentProvider可操作的列
public static final class User {
public static final String ID="id";
public static final String NAME="name";
public static final String AGE="age";
//定義該content提供服務(wù)的一個(gè)Uri
public static final String uri="content://"+AUTOR+"/userinfo";
public static final String uriall="content://"+AUTOR+"/userinfoall";
}
}
MainActivity.java
package com.android.xiong.contentprovidertestb;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.Activity;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.ScrollView;
import android.widget.SimpleAdapter;
import android.widget.Toast;
public class MainActivity extends Activity {
private Button bt1, bt2, bt3, bt4;
private EditText ed1, ed2;
private ListView list1;
private ScrollView sc1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt1 = (Button) findViewById(R.id.bt1);
bt2 = (Button) findViewById(R.id.bt2);
bt3 = (Button) findViewById(R.id.bt3);
bt4 = (Button) findViewById(R.id.bt4);
ed1 = (EditText) findViewById(R.id.ed1);
ed2 = (EditText) findViewById(R.id.ed2);
list1 = (ListView) findViewById(R.id.list);
// 顯示所有數(shù)據(jù)
list1.setAdapter(adapter(0));
sc1 = (ScrollView) findViewById(R.id.scr1);
// 向添加ContentProviderA應(yīng)用的數(shù)據(jù)
bt1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String eds1 = ed1.getText().toString();
String eds2 = ed2.getText().toString();
ContentValues content = new ContentValues();
if (!eds1.equals("") && !eds2.equals("")) {
content.put(UserInfo.User.NAME, eds1);
content.put(UserInfo.User.AGE, eds2);
MainActivity.this.getContentResolver().insert(
Uri.parse(UserInfo.User.uri), content);
Toast.makeText(MainActivity.this, "數(shù)據(jù)插入成功",
Toast.LENGTH_LONG).show();
// 刷新ListView界面
list1.setAdapter(adapter(0));
} else {
Toast.makeText(MainActivity.this, "name和age不能為空",
Toast.LENGTH_LONG).show();
}
}
});
// 根據(jù)條件刪除ContentProviderA應(yīng)用的數(shù)據(jù)
bt2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String eds1 = ed1.getText().toString();
String eds2 = ed2.getText().toString();
if (!eds1.equals("") || !eds2.equals("")) {
HashMap<String, String[]> wheres = wheres(eds1, eds2);
String sql = wheres.get("sql")[0];
String[] selectags = wheres.get("selectages");
MainActivity.this.getContentResolver().delete(
Uri.parse(UserInfo.User.uri), sql, selectags);
} else {
Toast.makeText(MainActivity.this, "請(qǐng)輸入刪除條件",
Toast.LENGTH_LONG).show();
}
// 刷新ListView界面
list1.setAdapter(adapter(0));
}
});
// 修改數(shù)據(jù)
bt3.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String eds1 = ed1.getText().toString();
String eds2 = ed2.getText().toString();
ContentValues values = new ContentValues();
// 根據(jù)條件將列修改為xiong,23
values.put(UserInfo.User.NAME, "xiong");
values.put(UserInfo.User.AGE, "23");
if (!eds1.equals("") || !eds2.equals("")) {
HashMap<String, String[]> wheres = wheres(eds1, eds2);
String sql = wheres.get("sql")[0];
String[] selectags = wheres.get("selectages");
int i=MainActivity.this.getContentResolver().update(
Uri.parse(UserInfo.User.uri), values, sql,
selectags);
} else {
Toast.makeText(MainActivity.this, "請(qǐng)輸入刪除條件",
Toast.LENGTH_LONG).show();
}
// 刷新ListView界面
list1.setAdapter(adapter(0));
}
});
// 根據(jù)條件查詢ContentProviderA應(yīng)用的數(shù)據(jù)
bt4.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (!ed1.getText().toString().equals("")
|| !ed2.getText().toString().equals(""))
list1.setAdapter(adapter(1));
else
list1.setAdapter(adapter(0));
}
});
}
// 用來(lái)判別條件
public HashMap<String, String[]> wheres(String eds1, String eds2) {
HashMap<String, String[]> where = new HashMap<String, String[]>();
if (!eds1.equals("") && !eds2.equals("")) {
String[] sql = { UserInfo.User.NAME + "=? and " + UserInfo.User.AGE
+ " =?" };
String[] selectages = { eds1, eds2 };
where.put("sql", sql);
where.put("selectages", selectages);
}
if (!eds1.equals("") && eds2.equals("")) {
String[] sql = { UserInfo.User.NAME + "=? " };
String[] selectages = { eds1 };
where.put("sql", sql);
where.put("selectages", selectages);
}
if (eds1.equals("") && !eds2.equals("")) {
String[] sql = { UserInfo.User.AGE + " =?" };
String[] selectages = { eds2 };
where.put("sql", sql);
where.put("selectages", selectages);
}
return where;
}
// 用來(lái)顯示數(shù)據(jù)
public SimpleAdapter adapter(int i) {
Cursor cs = MainActivity.this.getContentResolver().query(
Uri.parse(UserInfo.User.uriall), null, null, null, null);
String eds1 = ed1.getText().toString();
String eds2 = ed2.getText().toString();
if (i == 1) {
if (!eds1.equals("") || !eds2.equals("")) {
HashMap<String, String[]> wheres = wheres(eds1, eds2);
String sql = wheres.get("sql")[0];
String[] selectags = wheres.get("selectages");
cs = MainActivity.this.getContentResolver().query(
Uri.parse(UserInfo.User.uri), null, sql, selectags,
null);
}
}
List<Map<String, Object>> lists = new ArrayList<Map<String, Object>>();
while (cs.moveToNext()) {
Map<String, Object> map = new HashMap<String, Object>();
map.put("name", cs.getString(0));
map.put("age", cs.getString(1));
lists.add(map);
}
SimpleAdapter simepl = new SimpleAdapter(MainActivity.this, lists,
R.layout.item, new String[] { "name", "age" }, new int[] {
R.id.item_txt1, R.id.item_txt2 });
return simepl;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
activity.xml
<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"
android:orientation="vertical"
tools:context=".MainActivity" >
<ScrollView
android:id="@+id/scr1"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<Button
android:id="@+id/bt1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="添加" />
<Button
android:id="@+id/bt2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="刪除" />
<Button
android:id="@+id/bt3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="更改" />
<Button
android:id="@+id/bt4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="查詢" />
<EditText
android:id="@+id/ed1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="輸入name條件進(jìn)行增刪改查" />
<EditText
android:id="@+id/ed2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="輸age條件進(jìn)行增刪改查" />
</LinearLayout>
</ScrollView>
<ListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<TextView
android:id="@+id/item_txt1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/item_txt2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
監(jiān)聽(tīng)ContentProvider數(shù)據(jù)改變
當(dāng)程序A在執(zhí)行insert、update、delete時(shí),通過(guò)getContext().getContentResolver().notifyChange(uri, null)方法來(lái)告訴所有注冊(cè)在該Uri的監(jiān)聽(tīng)者數(shù)據(jù)發(fā)生改變
//刪除數(shù)據(jù)
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int number = 0;
if (uriMatcher.match(uri) == 1) {
// 根據(jù)條件刪除數(shù)據(jù),并獲取刪除的行數(shù)
number = mysqlite.getReadableDatabase().delete("user_info",
selection, selectionArgs);
}
// 通知數(shù)據(jù)已經(jīng)改變
getContext().getContentResolver().notifyChange(uri, null);
return number;
}
在B程序通過(guò)registerContentObserver(Uri uri,boolean notifyForDescendents, ContentObserver observer)方法來(lái)監(jiān)聽(tīng)A程序的數(shù)據(jù)改變
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 為uri的數(shù)據(jù)改變注冊(cè)監(jiān)聽(tīng)器
getContentResolver().registerContentObserver(
Uri.parse("content://com.android.xiong.ConentProviderTestA.firstContentProvider/userinfo"), true,
new SmsObserver(new Handler()));
}
registerContentObserver中第三個(gè)參數(shù)為監(jiān)聽(tīng)實(shí)例 ,需要通過(guò)繼承ContentObserver類(lèi),并重寫(xiě)onChange(booleab selfChange)方法,該方法在監(jiān)聽(tīng)Uri的ContentProvider的數(shù)據(jù)發(fā)生改變時(shí)觸發(fā)該方法
// 提供方自定義的ContentOberver監(jiān)聽(tīng)器
private final class Observer extends ContentObserver {
public SmsObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange, Uri uri) {
// 查詢發(fā)送郵箱中的短息(處于正在發(fā)送狀態(tài)的短信放在發(fā)送箱)
Cursor cursor = getContentResolver().query(
Uri.parse("content://com.android.xiong.ConentProviderTestA.firstContentProvider/userinfo"), null, null, null, null);
}
}
}
- Android 中自定義ContentProvider與ContentObserver的使用簡(jiǎn)單實(shí)例
- Android 中ContentProvider的實(shí)例詳解
- Android ContentProvider實(shí)現(xiàn)獲取手機(jī)聯(lián)系人功能
- Android數(shù)據(jù)持久化之ContentProvider機(jī)制詳解
- Android中ContentProvider和ContentResolver詳解
- Android開(kāi)發(fā)教程之ContentProvider數(shù)據(jù)存儲(chǔ)
- android基礎(chǔ)總結(jié)篇之八:創(chuàng)建及調(diào)用自己的ContentProvider
- Android學(xué)習(xí)筆記之ContentProvider和Uri詳解
- Android7.0中關(guān)于ContentProvider組件詳解
相關(guān)文章
Android 異步獲取網(wǎng)絡(luò)圖片并處理導(dǎo)致內(nèi)存溢出問(wèn)題解決方法
Android異步獲取網(wǎng)絡(luò)圖片并處理圖片Out Of Memory內(nèi)存溢出如何解決呢?本文介紹了操作步驟,感興趣的朋友可以了解下或許對(duì)你有所幫助2013-02-02
android連續(xù)拖動(dòng)導(dǎo)致掛起的解決方法
本文給大家分享的是在安卓的項(xiàng)目開(kāi)發(fā)中遇到連續(xù)拖動(dòng)對(duì)象,導(dǎo)致掛起的問(wèn)題的解決方法,也是經(jīng)過(guò)很多網(wǎng)友的提示,最終才找到解決方法,這里記錄一下,分享給大家。2015-05-05
Android檢測(cè)IBeacon熱點(diǎn)的方法
這篇文章主要介紹了Android檢測(cè)IBeacon熱點(diǎn)的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-10-10
Android設(shè)計(jì)模式之Builder模式解析
這篇文章主要為大家詳細(xì)介紹了Android設(shè)計(jì)模式之Builder模式解析的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10
Android無(wú)需申請(qǐng)權(quán)限撥打電話的兩種方式
android 打電話有兩種實(shí)現(xiàn)方式,第一種方法撥打電話跳轉(zhuǎn)到撥號(hào)界面,第二種方法,撥打電話直接進(jìn)行撥打,下面逐一給大家介紹這兩種方式,需要的朋友參考下吧2016-12-12
SurfaceView播放視頻發(fā)送彈幕并實(shí)現(xiàn)滾動(dòng)歌詞
這篇文章主要為大家詳細(xì)介紹了SurfaceView播放視頻發(fā)送彈幕并實(shí)現(xiàn)滾動(dòng)歌詞,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-11-11

