安卓基础_13

1 创建一个私有的数据库
[1]定义一个类继承sqliteOpenHelper

1.public class MyOpenHelper extends SQLiteOpenHelper {
2.
3. /**
4. *
5. * @param context
6. * name : 数据库的名称
7. * Factory: 游标工厂 默认null
8. * version :数据库的版本 版本从1开始
9. */
10. public MyOpenHelper(Context context) {
11. super(context, “Account.db”, null, 1);
12. }
13.
14. /**
15. * Called when the database is created for the first time
16. * 当数据库第一次创建的时候调用 那么这个方法特别适合做表结构的初始化
17. */
18. @Override
19. public void onCreate(SQLiteDatabase db) {
20.
21. db.execSQL(“create table info(_id integer primary key autoincrement,name varchar(20),money varchar(20))”);
22. db.execSQL(“insert into info(name,money) values(?,?)”, new String[]{“张三”,”5000”});
23. db.execSQL(“insert into info(name,money) values(?,?)”, new String[]{“李四”,”3000”});
24.
25. }
26.
27. @Override
28. public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
29.
30. }
31.
32.}

[2]查询数据库里面的数据

1.public class MainActivity extends Activity {
2.
3. @Override
4. protected void onCreate(Bundle savedInstanceState) {
5. super.onCreate(savedInstanceState);
6. setContentView(R.layout.activity_main);
7.
8. MyOpenHelper myOpenHelper = new MyOpenHelper(getApplicationContext());
9. //获取一个可读的数据库 或者 是可写的数据库
10. SQLiteDatabase db = myOpenHelper.getReadableDatabase(); //只有获取到了这个对象才可以操作数据库(crud)
11.
12. //把数据库的数据查询出来
13. Cursor cursor = db.query(“info”, null, null,null, null, null, null);
14. if (cursor!=null && cursor.getCount()>0) {
15. while(cursor.moveToNext()){
16. //把name和money取出来
17. String name = cursor.getString(1);
18. String money = cursor.getString(2);
19. System.out.println(“name:”+name+”—-“+money);
20.
21. }
22. }
23.
24. }
25.
26.
27.}

[3] 文件权限

[7]修改数据库文件的权限 chmod

  chmod 777 Account.db

2 为什么需要内容提供者

内容提供者可以把应用私有的数据暴露出来.给其他应用程序使用 

3 内容提供者工作的原理’

[1]如何定义内容提供者

定义一个类继承ContentProvider

1.public class AccountProvider extends ContentProvider {
2.
3. @Override
4. public boolean onCreate() {
5. return false;
6. }
7.
8. @Override
9. public Cursor query(Uri uri, String[] projection, String selection,
10. String[] selectionArgs, String sortOrder) {
11. return null;
12. }
13.
14. @Override
15. public String getType(Uri uri) {
16. return null;
17. }
18.
19. @Override
20. public Uri insert(Uri uri, ContentValues values) {
21. return null;
22. }
23.
24. @Override
25. public int delete(Uri uri, String selection, String[] selectionArgs) {
26. return 0;
27. }
28.
29. @Override
30. public int update(Uri uri, ContentValues values, String selection,
31. String[] selectionArgs) {
32. return 0;
33. }
34.
35.}

[2]只要是通过内容提供者暴露出来的数据 ,其他应用都是使用内容解析者去访问

[3]如果验证内容提供这写的没有问题 通过查看如下日志

07-10 02:42:49.944: I/ActivityThread(9308): Pub com.itheima.db: com.itheima.db.AccountProvider

内容提供者实现步骤

[1]定义内容提供者

[2]定义一个路径的匹配器

  1. private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);

    [3]写一个静态代码块 添加匹配规则 规则可以是一条也可以是多条

  2. static{

  3. /**
    • URI: 统一资源标识符 content://com.itheima.db/query
    • authority 就是你刚刚在清单文件定义的
  4. *
  5. */

    1. sURIMatcher.addURI(“com.itheima.db”, “query”, QUERYSUCESS);

  6. }
  7. [4]暴露你想暴露的方法 crud

    [5]其他应用程序通过内容解析者来操作数据库

4 暴露增加 修改 删除 查询方法都暴露出来

增加的方法

1.@Override
2. public Uri insert(Uri uri, ContentValues values) {
3. int code = sURIMatcher.match(uri);
4. if (code == INSERTSUCESS) {
5. //说明路径匹配成功
6. SQLiteDatabase db = myOpenHelper.getReadableDatabase();
7. //对数据库进行增加一条记录
8. long insert = db.insert(“info”, null, values);
9. Uri uri2 = Uri.parse(“com.itheima.haha.insert/”+insert);
10. return uri2;
11.
12. }else {
13. //说明路径匹配失败
14. throw new IllegalArgumentException(“哥们 路径不正确,请检查路径”);
15. }
16.
17.
18. }

修改的方法

1.@Override
2. public int update(Uri uri, ContentValues values, String selection,
3. String[] selectionArgs) {
4.
5. int code = sURIMatcher.match(uri);
6. if (code == UPDATESUCESS) {
7. //说明路径匹配成功
8. SQLiteDatabase db = myOpenHelper.getReadableDatabase();
9. int update = db.update(“info”, values, selection, selectionArgs);
10. return update;
11.
12. }else {
13. //说明路径匹配失败
14. throw new IllegalArgumentException(“爷们 路径不正确,请检查路径”);
15. }
16. }

删除的逻辑

1.@Override
2. public int delete(Uri uri, String selection, String[] selectionArgs) {
3. int code = sURIMatcher.match(uri);
4. if (code == DELETESUCESS) {
5. //说明路径匹配成功
6. SQLiteDatabase db = myOpenHelper.getReadableDatabase();
7. int delete = db.delete(“info”, selection, selectionArgs);
8. return delete;
9.
10. }else {
11. //说明路径匹配失败
12. throw new IllegalArgumentException(“爷们 路径不正确,请检查路径”);
13. }
14. }

查询的代码

1.@Override
2. public Cursor query(Uri uri, String[] projection, String selection,
3. String[] selectionArgs, String sortOrder) {
4. //通过这个方法对数据库进行查询的操作
5. int code = sURIMatcher.match(uri);
6. if (code == QUERYSUCESS ) {
7. //说明路径匹配成功
8. SQLiteDatabase db = myOpenHelper.getReadableDatabase();
9. //对数据库进行查询操作
10. Cursor cursor = db.query(“info”, projection, selection, selectionArgs, null, null, sortOrder);
11. return cursor;
12.
13. }else {
14. //说明路径匹配失败
15. throw new IllegalArgumentException(“哥们 路径不正确,请检查路径”);
16.
17. }
18.
19.
20. }

5 短信的备份

1.
2. try {
3. // [0]获取xml序列化器
4. XmlSerializer serializer = Xml.newSerializer();
5. // [1]设置序列化器的参数
6. File file = new File(Environment.getExternalStorageDirectory()
7. .getPath(), “smsbackup.xml”);
8. FileOutputStream fos = new FileOutputStream(file);
9. serializer.setOutput(fos, “utf-8”);
10. // [2]生产xml文件的头
11. serializer.startDocument(“utf-8”, true);
12. // [3]生产xml的根标签
13. serializer.startTag(null, “smss”);
14.
15. // [4]先把短信的数据取出来,由于短信的数据库 系统已经通过内容提供者暴露出来 所以我们可以直接通过内容解析者去操作数据库
16. Uri uri = Uri.parse(“content://sms/”);
17. Cursor cursor = getContentResolver().query(uri,
18. new String[] { “address”, “date”, “body” }, null, null,
19. null);
20. while (cursor.moveToNext()) {
21. String address = cursor.getString(0);
22. String date = cursor.getString(1);
23. String body = cursor.getString(2);
24.
25. // [4]生产xml的sms标签
26. serializer.startTag(null, “sms”);
27. // [5]生成address标签
28. serializer.startTag(null, “address”);
29. serializer.text(address);
30. serializer.endTag(null, “address”);
31.
32. // [6]生成date标签
33. serializer.startTag(null, “date”);
34. serializer.text(date);
35. serializer.endTag(null, “date”);
36.
37. // [6]生成body标签
38. serializer.startTag(null, “body”);
39. serializer.text(body);
40. serializer.endTag(null, “body”);
41. serializer.endTag(null, “sms”);
42. }
43.
44. serializer.endTag(null, “smss”);
45. serializer.endDocument();
46.
47. } catch (Exception e) {
48. e.printStackTrace();
49. }
50.
51.

6 虚拟短信的做法

1.
2. //[1]由于短信的数据库系统已经通过内容提供者暴露出来 所以可以直接通过内容解析者去操作数据库
3. Uri uri = Uri.parse(“content://sms/”);
4. //[2]准备要插入的内容
5. ContentValues values = new ContentValues();
6. values.put(“address”, “9555”);
7. values.put(“body”, “您的银行卡余额为0.00元”);
8. values.put(“date”, System.currentTimeMillis());
9. //[3]通过内容解析者往短信数据库里面插入一条数据
10. getContentResolver().insert(uri, values);
11.
12.

7.查询联系人案例

[1]data表 data1列存的是所有联系人的信息

[2]raw_contacts 表里面的contact_id列用来区分一共有几条联系人

[3]mimetype表 _id值用来区分数据的类型

查询联系人的步骤

[1]先查询raw_contacts表的 contact_id字段 进而知道系统一共有几条联系人 

[2]在查询data表 ,查询这个表的data1列和mimetype列 

调试小技巧:如果报无效的列  


1)你查询的列名写错了 

2)想你查询的表中根本就没有这列 

3)查询所有列名字的方法 

1.Cursor dataCursor = getContentResolver().query(dataUri, null, null,null, null);
2. String[] columnNames = dataCursor.getColumnNames();
3. for (String s : columnNames) {
4. System.out.println(“s:>>>>>”+s);
5. }

查询联系人代码实现

1.
2.
3. @Override
4. protected void onCreate(Bundle savedInstanceState) {
5. super.onCreate(savedInstanceState);
6. setContentView(R.layout.activity_main);
7.
8.
9. //[1]由于联系人的数据库系统已经通过内容提供者暴露出来 所以我们可以直接通过内容解析者操作联系人数据库
10. Uri uri = Uri.parse(“content://com.android.contacts/raw_contacts”);
11. Uri dataUri = Uri.parse(“content://com.android.contacts/data”);
12. //[2]现在想查询raw_contacts表里面的contact_id列
13. Cursor cursor = getContentResolver().query(uri, new String[]{“contact_id”}, null, null, null);
14. while(cursor.moveToNext()){
15. String contact_id = cursor.getString(0);
16. System.out.println(“contact_id:”+contact_id);
17.
18. //[3]在查询data表 data表里面的data1列和mimetype_id列
19.
20. Cursor dataCursor = getContentResolver().query(dataUri, new String[]{“data1”,”mimetype”}, “raw_contact_id=?”, new String[]{contact_id}, null);
21. while(dataCursor.moveToNext()){
22. String data1 = dataCursor.getString(0);
23. String mimetype = dataCursor.getString(1);
24. //[4]通过mimetype来区分data1的数据类型
25. if (“vnd.android.cursor.item/email_v2”.equals(mimetype)) {
26. System.out.println(“邮箱:”+data1);
27. }else if (“vnd.android.cursor.item/phone_v2”.equals(mimetype)) {
28. System.out.println(“电话:”+data1);
29. }else if (“vnd.android.cursor.item/name”.equals(mimetype)) {
30. System.out.println(“姓名:”+data1);
31. }
32.
33. }
34.
35. }
36.
37. }
38.
39.

8 使用内容解析者往联系人数据库里面插入联系人

插入的步骤

[1]先往raw_contact表里面插入一条数据 告诉系统有一条新的联系人

[2]在往data表里面插入数据

1.
2. // [1]获取name email phone
3. String name = et_name.getText().toString().trim();
4. String email = et_email.getText().toString().trim();
5. String phone = et_phone.getText().toString().trim();
6. // [2]把name email phone 插入到联系人的数据库中
7. Uri uri = Uri.parse(“content://com.android.contacts/raw_contacts”);
8. Uri dataUri = Uri.parse(“content://com.android.contacts/data”);
9.
10. // [2.1]插入数据之前 先查询一下这个表一共有几行数据
11. Cursor cursor = getContentResolver().query(uri, null, null, null, null);
12. int count = cursor.getCount(); // 获取表中的行数
13. int contact_id = count + 1; // 联系人的id值
14. ContentValues values = new ContentValues();
15. values.put(“contact_id”, contact_id);
16. // [2.2]往raw_contact表里面插入联系人的id
17. getContentResolver().insert(uri, values);
18. // [2.3]往data表里面插入数据
19. ContentValues nameValues = new ContentValues();
20. nameValues.put(“data1”, name); // 把name的数据插入到data1列
21. nameValues.put(“raw_contact_id”, contact_id); // 告诉系统新插入的数据属于哪个联系人
22. nameValues.put(“mimetype”, “vnd.android.cursor.item/name”);
23. getContentResolver().insert(dataUri, nameValues);
24.
25. // [2.4]把phone 插入到数据库
26. ContentValues phoneValues = new ContentValues();
27. phoneValues.put(“data1”, phone); // 把name的数据插入到data1列
28. phoneValues.put(“raw_contact_id”, contact_id); // 告诉系统新插入的数据属于哪个联系人
29. phoneValues.put(“mimetype”, “vnd.android.cursor.item/phone_v2”);
30. getContentResolver().insert(dataUri, phoneValues);
31.
32. // [2.5]把email的数据插入到数据库
33. ContentValues emailValues = new ContentValues();
34. emailValues.put(“data1”, email); // 把name的数据插入到data1列
35. emailValues.put(“raw_contact_id”, contact_id); // 告诉系统新插入的数据属于哪个联系人
36. emailValues.put(“mimetype”, “vnd.android.cursor.item/email_v2”);
37. getContentResolver().insert(dataUri, emailValues);
38.
39.

9 内容观察者

[1]通过内容解析者去注册内容观察者

1.Uri uri = Uri.parse(“content://com.itheima.db/”); // content://com.itheima.db/query
2. //[1]注册一个内容观察者 第二个参数 如果是false uri必须的一个完整的(确切的uri)
3. getContentResolver().registerContentObserver(uri, true, new MyContentObserver(new Handler()));

[2]定义内容观察者

1.//[2]定义内容观察者
2. private class MyContentObserver extends ContentObserver{
3.
4. public MyContentObserver(Handler handler) {
5. super(handler);
6. }
7.
8. @Override
9. public void onChange(boolean selfChange) {
10. System.out.println(“哈哈 数据库被人操作了 “);
11. super.onChange(selfChange);
12. }
13.
14. }

[3]内容观察者 想要接收到通知 必须的有人发消息

1.getContext().getContentResolver().notifyChange(uri, null);

10 内容观察者的应用场景

[1]使用内容观察者实现短信的监听器

1.public class MainActivity extends Activity {
2.
3. @Override
4. protected void onCreate(Bundle savedInstanceState) {
5. super.onCreate(savedInstanceState);
6. setContentView(R.layout.activity_main);
7.
8. //[1]注册内容观察者
9. Uri uri = Uri.parse(“content://sms/”);
10. getContentResolver().registerContentObserver(uri, true, new MyContentOvserver(new Handler()));
11. }
12.
13.
14. //[2]定义内容观察者
15. private class MyContentOvserver extends ContentObserver{
16.
17. public MyContentOvserver(Handler handler) {
18. super(handler);
19. }
20. @Override
21. public void onChange(boolean selfChange) {
22. System.out.println(“短信 的数据库发生了改变”);
23. //就把最后一条短信取出来就可以了
24. Uri uri = Uri.parse(“content://sms/”);
25. Cursor cursor = getContentResolver().query(uri,new String[] { “address”, “date”, “body” }, null, null,null);
26. cursor.moveToFirst();
27. String address = cursor.getString(0);//获取地址
28. String date = cursor.getString(1); //获取时间
29. String body = cursor.getString(2); //获取内容
30. System.out.println(“address:”+address+”—-“+body);
31.
32. super.onChange(selfChange);
33. }
34. }
35.
36.}

11 今日总结

 [1]定义内容提供者    了解

 [2]短信备份案例  掌握 

 [3]使用内容解析者往短信的数据库里面插入短信 (虚假短信)  掌握 

 [4]查询联系人  掌握

     data表  data1列存的是所有联系人的信息 

     raw_contacts 表  contact_id列 区分一共有几条联系人 

 [5]使用内容解析者往联系人数据库插入联系人  掌握 

 [6]内容观察者  了解 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
安卓JNI中,__FUNCTION__是一个预定义的宏,它可以返回当前函数的名称。它通常用于在调试或日志输出中显示当前函数的名称。在引用中,__FUNCTION__被用于显示正在执行的函数名称为AndroidRuntime::startVm。这个函数是用来启动虚拟机的,并且它的执行流程与sigchain_dummy不同,因此不会调用到sigchain_dummy这里。在引用中,__FUNCTION__没有被直接使用,但是在初始化操作的过程中,可能会使用其它函数来回调Java函数,并且使用__FUNCTION__来记录相关的日志信息。因此,__FUNCTION__主要是用来在日志或调试中标识当前函数的名称。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [安卓高版本c/c++调用java,通过JNI_CreateJavaVM/JNI_GetCreatedJavaVMs创建虚拟机实例](https://blog.csdn.net/zs787055144/article/details/131322208)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [JNI_OnLoad和JNI_OnUnload](https://blog.csdn.net/zhao007z5/article/details/80064818)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值