应用B访问应用A的数据库(两种方式):
1.Android下有Linux系统,用Linux系统的chmod命令把文件改成可访问(修改权限),应用B可直接访问应用A的数据库。
2.ContentProvider:在应用A中建一个中间联系人,应用B访问中间联系人,中间联系人去访问应用A的数据库(ContentProvider给其他应用提供一个本应用的数据访问接口).
ContentProvider内容提供者(只针对于数据库)
内容提供者(ContentProvider)把数据进行封装然后提供出来,其他应用可以通过内容解析者(ContentResolver)来访问。
ContentResolver内容解析者
内容解析者,该类提供了和ContentProvider(内容提供者)中同名同参的增、删、改、查的方法,通过URI采用对应的方法来操作ContentProvider提供的数据。
案例:访问Android系统中短信的数据库(打印出所有字段名)
1.在.xml中创建一个按钮
<Button
android:text="访问sms"
android:id="@+id/btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"></Button>
2.在后台获取按钮的点击事件
1)创建ContentResolver()内容解析者对象:获取–getContentResolver()
2)创建URI(URI:查询的数据库的名)Uri u = Uri.parse(“短信数据库的名(固定的):content://sms”);
3)contentResolver .query(URI:u, String[] projection(查询哪些字段):null, 查询条件:null, 条件的值:null,排序的条件:null);查询短信数据库的方法(null:查询所有字段,也可以new一个数组类型的字段–知道字段)
4)
//返回索引位置的数据
query.getString(0);
图解:
//让游标往下移动一行
query.moveToNext();
图解:一般写循环,返回true就继续走执行里面的方法体,返回false跳出循环。
//按照索引的方式返回字段下的内容
query.getColumnName(0);
图解:
//根据字段名称返回当前的字段索引
query.getColumnIndex("");
图解:
注:使用mysql创建数据库时,每一个表的每一个字段都得写字段的类型,但Android下的数据库中不管存的什么类型,在数据库中都是string类型。
//返回索引位置的数据
query.getString(0);
//返回字段的个数
query.getColumnCount();
//让游标往下移动一行
query.moveToNext();
//移动到具体的哪一行,容易索引越界,容易抛异常报错
query.move(2);
//把该表所有字段的名称以数组类型返回
query.getColumnNames();
//按照索引的方式返回字段下的内容
query.getColumnName(0);
//根据字段名称返回当前的字段索引
query.getColumnIndex("");
//是不是第一行,布尔类型
query.isFirst();
4)通过返回的结果集query,列出短信内容(遍历一下查了多少条短信)
String[] columnNames = query.getColumnNames();把该表所有字段的名称以数组类型返回
for循环–遍历字段:
for (int i=0;i<columnNames.length;i++){
Log.i("shit",columnNames[i]);
}
3.安全权限
1)在AndroidManifest.xml中(不用通过用户)
<uses-permission android:name="android.permission.READ_SMS"></uses-permission>
2)动态加载/动态申请 (代码是固定的)(Android6.0以后)
判断当前APP是否有权限:ContextCompat.checkSelfPermission(MainActivity.this, 和上面AndroidManifest.xml中对应上面是啥权限这里就是啥:Manifest.permission.READ_SMS) ;返回值是int
同意:PackageManager.PERMISSION_GRANTED代表用户同意(0)
不同意:PackageManager.PERMISSION_DENIED(-1){
动态申请权限:ActivityCompat.requestPermissions(MainActivity.this,数组类型的权限:new String[]{动态申请参数:Manifest.permission.READ_SMS},请求码:填啥都行只要是int类型就行100);
}
int checkSelf= ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_SMS) == PackageManager.PERMISSION_DENIED);
if (checkSelf ==PackageManager.PERMISSION_DENIED){
ActivityCompat.requestPermissions(MainActivity.this,new String[]{
Manifest.permission.READ_SMS},100);
}
//也可以写成
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_SMS) == PackageManager.PERMISSION_DENIED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{
Manifest.permission.READ_SMS}, 100);
}
3)使用动态申请权限会触发:onRequestPermissionsResult方法:判断用户是不是点击同意还是点击拒绝
requestCode等于自定义的请求码----权限就是读取信息的权限
@NonNull String[] permissions权限会通过数组类型传过来
@NonNull int[] grantResults结果码通过数组传过来
4)危险权限
效果图:同时打印出所有列的列名
MainActivity.java代码:
package com.example.myapplication;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.content.ContentResolver;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.