Android跨程序共享数据

作者: 黑衣侠客

一、前言

在我们日常使用手机时,不难发现,通常一些App会获取联系人信息、请求发送短信等,那么我们将这些操作叫做:数据共享,那么为什么要将我们程序中的数据共享给其他程序呢?当然,这个是分情况而定的,例如,我们的账号和密码是不能分享给其他程序的,不过,一些可以让其他程序二次开发的基础数据还是可以共享的。例如:电话本、短信、多媒体库等。而这些跨程序共享,使用的技术就是内容提供器

二、内容提供器

1.简介:

内容提供器(Content Provider)主要用于在不同的应用程序之间实现数据共享功能,它提供了一套完整的机制,允许一个程序访问另一个程序中的数据,同时还能保证被访问数据的安全性。目前,使用内容提供器是Android实现跨程序共享数据的标准方式。内容提供器可以选择只对哪一部分数据进行共享,从而保证我们程序中的隐私数据不会有泄漏的风险。

三、Android权限机制

Android现在将所有的权限分为两类,一类是普通权限,一类是危险权限

普通权限指的是那些不会直接威胁到用户的安全和隐私权限,对于这部分权限,系统会自动帮我们进行授权。
危险权限表示那些可能触及用户隐私,或者对设备安全造成影响的权限,如获取设备联系人信息、定位设备的地理位置等,对于这部分权限的申请,必须要由用户手动点击授权才可以,否则,程序无法使用这些功能。

Android中所有危险权限:

权限组名

权限名

CALENDAR

READ_CALENDAR、WRITE_CALENDAR

CAMERA

CAMERA

CONTACTS

READ_CONTACTS、WRITE_CONTACTS、GET_ACCOUNTS

LOCATION

ACCESS_FINE_LOCATION、ACCESS_COARSE_LOCATION

MICROPHONE

RECORD_AUDIO

PHONE

READ_PHONE_STATE、CALL_PHONE、READ_CALL_LOG、WRITE_CALL_LOG、ADD_VOICEMAIL、USE_SIP、PROCESS_OUTGOING_CALLS

SENSORS

BODY_SENSORS

SMS

SEND_SMS、RECEIVE_SMS、READ_SMS、RECEIVE_WAP_PUSH、RECEIVE_MMS

STORAGE

READ_EXTERNAL_STORAGE、WRITE_EXTERNAL_STORAGE

注意:

表格中每个危险权限都属于一个权限组,我们在进行运行时权限处理时使用的是权限名,但是用户一旦同意授权了,那么该权限所对应的权限组中所有的其他权限也会同时被授权。

四、拨打电话程序

下面我们将调用拨打电话的权限,来做一个拨打电话的程序:

权限声明:

<uses-permission android:name="android.permission.CALL_PHONE" />

activity_main:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <EditText
        android:id="@+id/edit_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入您将要拨打的号码"/>
    <Button
        android:id="@+id/button1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="拨号"
        android:textColor="#ffffff"
        android:textSize="18sp"
        android:background="#54BEF1"/>
</LinearLayout>

MainActivity.java

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    private EditText editText;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        editText = findViewById(R.id.edit_text);
        Button button = findViewById(R.id.button1);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.CALL_PHONE)!=
                PackageManager.PERMISSION_GRANTED){
                    ActivityCompat.requestPermissions(MainActivity.this,new String[] {Manifest.permission.CALL_PHONE},1);
                }else{
                    String str = editText.getText().toString();
                    call(str);
                }
            }
        });
    }
    private void call(String string){
        try{
            Intent intent = new Intent(Intent.ACTION_CALL);
            intent.setData(Uri.parse("tel:"+string));
            startActivity(intent);
        }catch(SecurityException e){
            e.printStackTrace();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch(requestCode){
            case 1:
                if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
                    String str = editText.getText().toString();
                    call(str);
                }else{
                    Toast.makeText(this, "You denied the Permission!!!", Toast.LENGTH_SHORT).show();
                }
        }
    }
}
第一步,就是要先判断用户是不是已经给过我们授权了,借助的是ContextCompat.checkSelfPermission()方法。checkSelfPermission()方法接收两个参数,第一个参数是Context,第二个参数是具体的权限名,比如,打电话的权限名就是Manifest.permission.CALL_PHONE,然后我们使用方法的返回值和PackageManager.PERMISSION_GRANTED做比较,相等就表示已授权,不等则没有授权。如果已经授权了,直接去执行拨打电话的逻辑操作就可以了,如果没有授权的话,就调用requestPermission()方法接收三个参数,第一个Activity实例(MainActivity.this),第二个参数是一个String数组,我们把要申请的权限名放在数组中即可,第三个参数是请求码,只要是唯一值就可以了,这里传入了1。调用完了requestPermission()方法之后,系统会弹出一个权限申请的对话框,然后用户可以选择同意或拒绝我们的权限申请,不论哪种结果,最终都会回调到onRequestPermissionsResult()方法中,而授权的结果则会封装在grantResults参数中,这里我们只需判断一下最后的授权结果,如果用户同意的话就调用call()方法来拨打电话,如果拒绝授权的话,我们只能放弃拨打操作,并弹出一条失败提示。