android 学习随笔二十一(内容提供者 )
一、内容提供者
* 应用的数据库是不允许其他应用访问的
* 内容提供者的作用就是让别的应用访问到你的私有数据
* 自定义内容提供者,继承ContentProvider类,重写增删改查方法,在方法中写增删改查数据库的代码,举例增方法
@Override
public Uri insert(Uri uri, ContentValues values) {
db.insert("person", null, values);
return uri;
}
* 在清单文件中定义内容提供者的标签,注意必须要有authorities属性,这是内容提供者的主机名,功能类似地址
<provider android:name="com.itheima.contentprovider.PersonProvider"
android:authorities="com.itheima.person"
android:exported="true"
></provider>
通过UriMatcher um = new UriMatcher(UriMatcher.NO_MATCH)指定表
um.addURI("com.itheima.people", "person/#", 3);//content://com.itheima.people/person/10,#匹配任何数字,通常作为WHERE条件使用
vnd.android.cursor.dir/ 多条数据
vnd.android.cursor.item/ 单条数据
package com.itheima.mycontentprovider.db; import java.io.Serializable; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteOpenHelper; import android.os.Parcelable; public class MyOpenHelper extends SQLiteOpenHelper { public MyOpenHelper(Context context) { super(context, "people.db", null, 2); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("create table person(_id integer primary key autoincrement, name char(10), phone char(20), money integer(10))"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("create table handsome(_id integer primary key autoincrement, name char(10), phone char(20))"); } }
package com.itheima.mycontentprovider; import com.itheima.mycontentprovider.db.MyOpenHelper; 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; public class PersonProvider extends ContentProvider { private SQLiteDatabase db; //创建uri匹配器 UriMatcher um = new UriMatcher(UriMatcher.NO_MATCH); { //添加匹配规则 //arg0:主机名 //arg1:路径 //arg2:匹配码 um.addURI("com.itheima.people", "person", 1);//content://com.itheima.people/person um.addURI("com.itheima.people", "handsome", 2);//content://com.itheima.people/handsome um.addURI("com.itheima.people", "person/#", 3);//content://com.itheima.people/person/10 } //内容提供者创建时调用 @Override public boolean onCreate() { MyOpenHelper oh = new MyOpenHelper(getContext()); db = oh.getWritableDatabase(); return false; } //values:其他应用要插的数据 @Override public Uri insert(Uri uri, ContentValues values) { if(um.match(uri) == 1){ db.insert("person", null, values); //数据库改变了,内容提供者发出通知 //arg0:通知发到哪个uri上,注册在这个uri上的内容观察者都可以收到通知 getContext().getContentResolver().notifyChange(uri, null); } else if(um.match(uri) == 2){ db.insert("handsome", null, values); getContext().getContentResolver().notifyChange(uri, null); } else{ throw new IllegalArgumentException("uri传错啦傻逼"); } return uri; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { int i = 0; if(um.match(uri) == 1){ i = db.delete("person", selection, selectionArgs); } else if(um.match(uri) == 2){ i = db.delete("handsome", selection, selectionArgs); } else{ throw new IllegalArgumentException("uri又传错啦傻逼"); } return i; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { int i = db.update("person", values, selection, selectionArgs); return i; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { Cursor cursor = null; if(um.match(uri) == 1){ cursor = db.query("person", projection, selection, selectionArgs, null, null, sortOrder, null); } else if(um.match(uri) == 2){ cursor = db.query("handsome", projection, selection, selectionArgs, null, null, sortOrder, null); } else if(um.match(uri) == 3){ //取出uri末尾携带的数字 long id = ContentUris.parseId(uri); cursor = db.query("person", projection, "_id = ?", new String[]{"" + id}, null, null, sortOrder, null); } return cursor; } //返回通过指定uri获取的数据的mimetype @Override public String getType(Uri uri) { if(um.match(uri) == 1){ return "vnd.android.cursor.dir/person"; } else if(um.match(uri) == 2){ return "vnd.android.cursor.dir/handsome"; } else if(um.match(uri) == 3){ return "vnd.android.cursor.item/person"; } return null; } }
package com.itheima.mycontentprovider; import android.os.Bundle; import android.app.Activity; import android.view.Menu; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @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; } }
package com.itheima.mycontentprovider; import com.itheima.mycontentprovider.db.MyOpenHelper; import android.test.AndroidTestCase; public class Test extends AndroidTestCase { public void test(){ MyOpenHelper oh = new MyOpenHelper(getContext()); oh.getWritableDatabase(); } }
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.itheima.mycontentprovider" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" /> <instrumentation android:name="android.test.InstrumentationTestRunner" android:targetPackage="com.itheima.mycontentprovider"></instrumentation> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <uses-library android:name="android.test.runner"/> <activity android:name="com.itheima.mycontentprovider.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> <provider android:name="com.itheima.mycontentprovider.PersonProvider" android:authorities="com.itheima.people" android:exported="true" > </provider> </application> </manifest>
* 创建一个其他应用,访问自定义的内容提供者,实现对数据库的插入操作
public void click(View v){
//得到内容分解器对象
ContentResolver cr = getContentResolver();
ContentValues cv = new ContentValues();
cv.put("name", "小方");
cv.put("phone", 138856);
cv.put("money", 3000);
//url:内容提供者的主机名
cr.insert(Uri.parse("content://com.itheima.person"), cv);
}
package com.itheima.other; import android.net.Uri; import android.os.Bundle; import android.app.Activity; import android.content.ContentResolver; import android.content.ContentValues; import android.database.Cursor; import android.view.Menu; import android.view.View; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void insert(View v){ //通过内容提供者把数据插入01数据库 //1.获取contentResolver ContentResolver resolver = getContentResolver(); //2.访问内容提供者,插入数据 ContentValues values = new ContentValues(); values.put("name", "流氓润"); values.put("phone", 138992); values.put("money", 14000); //arg0:指定内容提供者的主机名 resolver.insert(Uri.parse("content://com.itheima.people/person"), values); values.clear(); values.put("name", "侃哥"); values.put("phone", 15999); //arg0:指定内容提供者的主机名 resolver.insert(Uri.parse("content://com.itheima.people/handsome"), values); } public void delete(View v){ ContentResolver resolver = getContentResolver(); int i = resolver.delete(Uri.parse("content://com.itheima.people"), "name = ?", new String[]{"凤姐"}); System.out.println(i); } public void update(View v){ ContentResolver resolver = getContentResolver(); ContentValues values = new ContentValues(); values.put("money", 16001); int i = resolver.update(Uri.parse("content://com.itheima.people"), values, "name = ?", new String[]{"春晓"}); System.out.println(i); } public void query(View v){ ContentResolver resolver = getContentResolver(); Cursor cursor = resolver.query(Uri.parse("content://com.itheima.people/person"), null, null, null, null); while(cursor.moveToNext()){ String name = cursor.getString(1); String phone = cursor.getString(2); String money = cursor.getString(3); System.out.println(name + ";" + phone + ";" + money); } } public void queryOne(View v){ ContentResolver resolver = getContentResolver(); Cursor cursor = resolver.query(Uri.parse("content://com.itheima.people/person/4"), null, null, null, null); if(cursor.moveToNext()){ String name = cursor.getString(1); String phone = cursor.getString(2); String money = cursor.getString(3); System.out.println(name + ";" + phone + ";" + money); } } }
UriMatcher
* 用于判断一条uri跟指定的多条uri中的哪条匹配
* 添加匹配规则
//指定多条uri
um.addURI("com.itheima.person", "person", PERSON_CODE);
um.addURI("com.itheima.person", "company", COMPANY_CODE);
//#号可以代表任意数字
um.addURI("com.itheima.person", "person/#", QUERY_ONE_PERSON_CODE);
* 通过Uri匹配器可以实现操作不同的表
@Override
public Uri insert(Uri uri, ContentValues values) {
if(um.match(uri) == PERSON_CODE){
db.insert("person", null, values);
}
else if(um.match(uri) == COMPANY_CODE){
db.insert("company", null, values);
}
else{
throw new IllegalArgumentException();
}
return uri;
}
* 如果路径中带有数字,把数字提取出来的api
int id = (int) ContentUris.parseId(uri);
二、获取系统短信
短信数据库
* 只需要关注sms表
* 只需要关注4个字段
* body:短信内容
* address:短信的发件人或收件人号码(跟你聊天那哥们的号码)
* date:短信时间
* type:1为收到,2为发送
###读取系统短信,首先查询源码获得短信数据库内容提供者的主机名和路径,然后访问内容提供者(掌握)
ContentResolver cr = getContentResolver();
Cursor c = cr.query(Uri.parse("content://sms"), new String[]{"body", "date", "address", "type"}, null, null, null);
while(c.moveToNext()){
String body = c.getString(0);
String date = c.getString(1);
String address = c.getString(2);
String type = c.getString(3);
System.out.println(body+";" + date + ";" + address + ";" + type);
}
package com.itheima.getsms; import android.net.Uri; import android.os.Bundle; import android.app.Activity; import android.content.ContentResolver; import android.database.Cursor; import android.view.Menu; import android.view.View; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void click1(View v){ ContentResolver resolver = getContentResolver(); Cursor cursor = resolver.query(Uri.parse("content://sms"), new String[]{"address", "date", "type", "body"}, null, null, null); while(cursor.moveToNext()){ String address = cursor.getString(0); long date = cursor.getLong(1); int type = cursor.getInt(2); String body = cursor.getString(3); System.out.println(address + ";" + date + ";" + type + ";" + body); } } }
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.itheima.getsms" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" /> <uses-permission android:name="android.permission.READ_SMS"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.itheima.getsms.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> </application> </manifest>
三、插入系统短信
插入系统短信
ContentResolver cr = getContentResolver();
ContentValues cv = new ContentValues();
cv.put("body", "您尾号为XXXX的招行储蓄卡收到转账1,000,000人民币");
cv.put("address", 95555);
cv.put("type", 1);
cv.put("date", System.currentTimeMillis());
cr.insert(Uri.parse("content://sms"), cv);
* 插入查询系统短信需要注册权限
package com.itheima.insertsms; import android.net.Uri; import android.os.Bundle; import android.app.Activity; import android.content.ContentResolver; import android.content.ContentValues; import android.view.Menu; import android.view.View; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void click(View v){ Thread t = new Thread(){ @Override public void run() { try { sleep(7000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } ContentResolver resolver = getContentResolver(); ContentValues values = new ContentValues(); values.put("address", 95555); values.put("date", System.currentTimeMillis()); values.put("type", 1); values.put("body", "您尾号为XXXX的招行储蓄卡收到转账1,000,000"); resolver.insert(Uri.parse("content://sms"), values); } }; t.start(); } }
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.itheima.insertsms" android:versionCode="1" android:versionName="1.0" > <uses-permission android:name="android.permission.WRITE_SMS"/> <uses-permission android:name="android.permission.READ_SMS"/> <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.itheima.insertsms.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> </application> </manifest>
四、联系人数据库
* raw\_contacts表:
* contact_id:联系人id
* data表:联系人的具体信息,一个信息占一行
* data1:信息的具体内容
* raw\_contact_id:联系人id,描述信息属于哪个联系人
* mimetype_id:描述信息是属于什么类型
* mimetypes表:通过mimetype_id到该表查看具体类型
五、读取联系人
* 先查询raw\_contacts表拿到联系人id
Cursor cursor = cr.query(Uri.parse("content://com.android.contacts/raw_contacts"), new String[]{"contact_id"}, null, null, null);
* 然后拿着联系人id去data表查询属于该联系人的信息
Cursor c = cr.query(Uri.parse("content://com.android.contacts/data"), new String[]{"data1", "mimetype"}, "raw_contact_id = ?", new String[]{contactId}, null);
* 得到data1字段的值,就是联系人的信息,通过mimetype判断是什么类型的信息
while(c.moveToNext()){
String data1 = c.getString(0);
String mimetype = c.getString(1);
if("vnd.android.cursor.item/email_v2".equals(mimetype)){
contact.setEmail(data1);
}
else if("vnd.android.cursor.item/name".equals(mimetype)){
contact.setName(data1);
}
else if("vnd.android.cursor.item/phone_v2".equals(mimetype)){
contact.setPhone(data1);
}
}
package com.itheima.getcontacts.domain; public class Contact { private String name; private String phone; private String email; 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; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @Override public String toString() { return "Contact [name=" + name + ", phone=" + phone + ", email=" + email + "]"; } }
package com.itheima.getcontacts; import com.itheima.getcontacts.domain.Contact; import android.net.Uri; import android.os.Bundle; import android.app.Activity; import android.content.ContentResolver; import android.database.Cursor; import android.view.Menu; import android.view.View; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void click(View v){ ContentResolver resolver = getContentResolver(); Cursor cursor = resolver.query(Uri.parse("content://com.android.contacts/raw_contacts"), new String[]{"contact_id"}, null, null, null); while(cursor.moveToNext()){ String contactId = cursor.getString(0); //使用联系人id作为where条件去查询data表,查询出属于该联系人的信息 Cursor cursorData = resolver.query(Uri.parse("content://com.android.contacts/data"), new String[]{"data1", "mimetype"}, "raw_contact_id = ?", new String[]{contactId}, null); // Cursor cursorData = resolver.query(Uri.parse("content://com.android.contacts/data"), null, "raw_contact_id = ?", // new String[]{contactId}, null); // int count = cursorData.getColumnCount(); // for (int i = 0; i < count; i++) { // System.out.println(cursorData.getColumnName(i)); // } Contact contact = new Contact(); while(cursorData.moveToNext()){ String data1 = cursorData.getString(0); String mimetype = cursorData.getString(1); // System.out.println(data1 + ";" + mimetype); if("vnd.android.cursor.item/email_v2".equals(mimetype)){ contact.setEmail(data1); } else if("vnd.android.cursor.item/phone_v2".equals(mimetype)){ contact.setPhone(data1); } else if("vnd.android.cursor.item/name".equals(mimetype)){ contact.setName(data1); } } System.out.println(contact.toString()); } } }
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.itheima.getcontacts" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" /> <uses-permission android:name="android.permission.READ_CONTACTS"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.itheima.getcontacts.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> </application> </manifest>
六、插入联系人
* 先查询raw\_contacts表,确定新的联系人的id应该是多少
* 把确定的联系人id插入raw\_contacts表
cv.put("contact_id", _id);
cr.insert(Uri.parse("content://com.android.contacts/raw_contacts"), cv);
* 在data表插入数据
* 插3个字段:data1、mimetype、raw\_contact_id
cv = new ContentValues();
cv.put("data1", "赵六");
cv.put("mimetype", "vnd.android.cursor.item/name");
cv.put("raw_contact_id", _id);
cr.insert(Uri.parse("content://com.android.contacts/data"), cv);
cv = new ContentValues();
cv.put("data1", "1596874");
cv.put("mimetype", "vnd.android.cursor.item/phone_v2");
cv.put("raw_contact_id", _id);
cr.insert(Uri.parse("content://com.android.contacts/data"), cv);
package com.itheima.insertcontact; import android.net.Uri; import android.os.Bundle; import android.app.Activity; import android.content.ContentResolver; import android.content.ContentValues; import android.database.Cursor; import android.view.Menu; import android.view.View; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void click(View v){ ContentResolver resolver = getContentResolver(); //先查询最新的联系人的主键,主键+1,就是要插入的联系人id Cursor cursor = resolver.query(Uri.parse("content://com.android.contacts/raw_contacts"), new String[]{"_id"}, null, null, null); int _id = 0; if(cursor.moveToLast()){ _id = cursor.getInt(0); } _id++; //插入联系人id ContentValues values = new ContentValues(); values.put("contact_id", _id); resolver.insert(Uri.parse("content://com.android.contacts/raw_contacts"), values); //把具体联系人信息插入data表 values.clear(); values.put("data1", "剪刀手坤哥"); values.put("mimetype", "vnd.android.cursor.item/name"); values.put("raw_contact_id", _id); resolver.insert(Uri.parse("content://com.android.contacts/data"), values); values.clear(); values.put("data1", "8899667"); values.put("mimetype", "vnd.android.cursor.item/phone_v2"); values.put("raw_contact_id", _id); resolver.insert(Uri.parse("content://com.android.contacts/data"), values); } }
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.itheima.insertcontact" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" /> <uses-permission android:name="android.permission.READ_CONTACTS"/> <uses-permission android:name="android.permission.WRITE_CONTACTS"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.itheima.insertcontact.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> </application> </manifest>
七、内容观察者
* 当数据库数据改变时,内容提供者会发出通知,在内容提供者的uri上注册一个内容观察者,就可以收到数据改变的通知
cr.registerContentObserver(Uri.parse("content://sms"), true, new MyObserver(new Handler()));
class MyObserver extends ContentObserver{
public MyObserver(Handler handler) {
super(handler);
// TODO Auto-generated constructor stub
}
//内容观察者收到数据库发生改变的通知时,会调用此方法
@Override
public void onChange(boolean selfChange) {
}
}
package com.itheima.contentobserver; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.app.Activity; import android.content.ContentResolver; import android.database.ContentObserver; import android.view.Menu; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //注册内容观察者,观察者就生效了,可以接受内容提供者发出的通知 ContentResolver resolver = getContentResolver(); //arg0:指定接收哪个内容提供者发出的通知 resolver.registerContentObserver(Uri.parse("content://sms"), true, //如果为true,以这个uri作为开头的uri上的数据改变了,该内容观察者都会收到通知 new MyObserver(new Handler())); } class MyObserver extends ContentObserver{ public MyObserver(Handler handler) { super(handler); // TODO Auto-generated constructor stub } @Override public void onChange(boolean selfChange) { // TODO Auto-generated method stub super.onChange(selfChange); System.out.println("短信数据库改变"); } } }
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.itheima.contentobserver" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.itheima.contentobserver.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> </application> </manifest>
在内容提供者中发通知的代码
ContentResolver cr = getContext().getContentResolver();
//发出通知,所有注册在这个uri上的内容观察者都可以收到通知
cr.notifyChange(uri, null);
接收一内容提供者发送的通知
package com.itheima.receivenotify; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.app.Activity; import android.database.ContentObserver; import android.view.Menu; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //注册内容观察者接收01发送的通知 getContentResolver().registerContentObserver(Uri.parse("content://com.itheima.people"), true, new ContentObserver(new Handler()) { @Override public void onChange(boolean selfChange) { // TODO Auto-generated method stub super.onChange(selfChange); System.out.println("01数据库改变"); } }); } }
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.itheima.receivenotify" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.itheima.receivenotify.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> </application> </manifest>
------------------------------------------