Android(4、ContentProvider内容提供者)

ContentProvider

➢ContentProvider为App存取内部数据提供统- -的外部接口,让不同的应用之间得以共享
数据。
A应用

ContentProvider是Android中的一个组件,用于在应用程序之间共享数据。它提供了一种标准化的方式来访问和操作应用程序的数据,可以实现数据的增删改查、数据权限管理和数据共享等功能。

使用ContentProvider需要以下几个步骤:

  1. 创建ContentProvider类:创建一个继承自ContentProvider的类,用于定义数据的增删改查操作。需要实现以下几个方法:

    • onCreate():在ContentProvider创建时调用,用于进行初始化操作。
    • query():用于查询数据。
    • insert():用于插入数据。
    • update():用于更新数据。
    • delete():用于删除数据。
    • getType():用于返回数据的MIME类型。
    public class MyContentProvider extends ContentProvider {
        // ...
    
        @Override
        public boolean onCreate() {
            // 初始化操作
            return true;
        }
    
        @Nullable
        @Override
        public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
            // 查询数据
            // 返回Cursor对象
            return cursor;
        }
    
        @Nullable
        @Override
        public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
            // 插入数据
            // 返回新插入数据的Uri
            return newUri;
        }
    
        @Override
        public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
            // 更新数据
            // 返回受影响的行数
            return count;
        }
    
        @Override
        public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
            // 删除数据
            // 返回受影响的行数
            return count;
        }
    
        @Nullable
        @Override
        public String getType(@NonNull Uri uri) {
            // 返回数据的MIME类型
            return mimeType;
        }
    }
    
  2. 注册ContentProvider:在AndroidManifest.xml文件中注册ContentProvider,将其与一个唯一的authority关联起来。

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.myapp">
    
        <application>
            <!-- ... -->
    
            <provider
                android:name=".MyContentProvider"
                android:authorities="com.example.myapp.provider"
                android:exported="false" />
        </application>
    
    </manifest>
    

    这里的com.example.myapp.provider是ContentProvider的authority,用于唯一标识该ContentProvider。

  3. 访问ContentProvider:通过ContentResolver类来访问ContentProvider。ContentResolver提供了一系列方法,用于进行数据的增删改查操作。

    • query():查询数据。
    • insert():插入数据。
    • update():更新数据。
    • delete():删除数据。
    Uri uri = Uri.parse("content://com.example.myapp.provider/users");
    
    // 查询数据
    Cursor cursor = getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);
    
    // 插入数据
    Uri newUri = getContentResolver().insert(uri, values);
    
    // 更新数据
    int count = getContentResolver().update(uri, values, selection, selectionArgs);
    
    // 删除数据
    int count = getContentResolver().delete(uri, selection, selectionArgs);
    

    这里的content://com.example.myapp.provider/users是ContentProvider的URI,用于指定要访问的数据。

以上就是使用ContentProvider的基本步骤。通过创建ContentProvider类、注册ContentProvider和使用ContentResolver来访问ContentProvider,可以实现数据的增删改查操作。同时,ContentProvider还提供了一些高级特性,如数据权限管理和数据共享等,可以根据实际需求进行使用。

总结:
ContentProvider是Android中的一个组件,用于在应用程序之间共享数据。使用ContentProvider需要创建ContentProvider类、注册ContentProvider和使用ContentResolver来访问ContentProvider。通过实现ContentProvider类的方法,可以实现数据的增删改查操作。同时,ContentProvider还提供了一些高级特性,如数据权限管理和数据共享等,可以根据实际需求进行使用。


运行时动态申请权限

➢Android系统为了防止某些App滥用权限,从6.0开始引入 了运行时权限管理机制,允许A
pp在运行过程中动态检查是否拥有某项权限,- -旦发现缺少某种必需的权限,则系统会
自动弹出小窗提示用户去开启该权限。


在Android中,有一些敏感权限需要在运行时动态申请,例如访问相机、读取联系人、获取位置等。以下是一些关于在运行时动态申请权限的笔记:

  1. 在AndroidManifest.xml文件中声明所需的权限。例如,如果您的应用需要访问相机,您需要在清单文件中添加以下权限声明:
<uses-permission android:name="android.permission.CAMERA" />
  1. 检查应用是否已被授予所需的权限。您可以使用ContextCompat.checkSelfPermission()方法来检查应用是否已被授予特定的权限。例如,检查相机权限是否已被授予:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
    // 相机权限已被授予
} else {
    // 相机权限未被授予,需要动态申请权限
}
  1. 动态申请权限。如果权限未被授予,您需要使用ActivityCompat.requestPermissions()方法来请求权限。此方法将显示一个系统对话框,向用户解释为什么需要该权限,并询问用户是否授予权限。例如,请求相机权限:
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, CAMERA_PERMISSION_REQUEST_CODE);
  1. 处理权限请求结果。当用户响应权限请求时,系统将调用onRequestPermissionsResult()方法,并传递权限请求结果。您需要在此方法中处理权限请求结果。例如,检查相机权限请求的结果:
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    if (requestCode == CAMERA_PERMISSION_REQUEST_CODE) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // 用户授予了相机权限
        } else {
            // 用户拒绝了相机权限
        }
    }
}
  1. 处理权限被拒绝的情况。如果用户拒绝了权限请求,您可以向用户解释为什么需要该权限,并提供一个适当的操作,例如打开应用设置页面让用户手动授予权限。例如,打开应用设置页面:
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivityForResult(intent, APP_SETTINGS_REQUEST_CODE);
  1. onActivityResult()方法中处理从应用设置页面返回的结果。当用户在应用设置页面授予或拒绝权限时,系统将调用onActivityResult()方法,并传递结果。您可以在此方法中处理用户的操作结果。

这些是在运行时动态申请权限的基本步骤。请注意,不同的权限可能需要不同的处理方式,具体取决于您的应用需求。您可以根据需要进行适当的调整和扩展。


动态申请权限的步骤

➢检查App是否开启了指定权限
●调用ContextCompat的checkSelfPermission方法。
➢请求系统弹窗,以便用户选择是否开启权限
●调用ActivityCompat的requestPermissions方法, 即可命令系统自动弹出权限申请窗口。
➢判断用户的权限选择结果
●重写活动页面的权限请求回调方法onRequestPermissionsResult,在该方法内部处理用户的权限选择结果。


运行时动态申请权限Lazy模式

运行时动态申请权限Lazy模式是一种简化动态申请权限流程的方式,它可以让您在不需要处理权限请求结果的情况下,直接使用需要的权限。

实现Lazy模式的基本步骤如下:

  1. 在您的Activity中,定义一个PermissionRequester类。这个类将负责处理权限请求和权限请求结果。例如:
public class MainActivity extends AppCompatActivity {

    private PermissionRequester mPermissionRequester;
    
    // ...
    
    private void initPermission() {
        mPermissionRequester = new PermissionRequester(this);
        mPermissionRequester.request(Manifest.permission.CAMERA);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        mPermissionRequester.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
    
    // ...
}
  1. PermissionRequester类中,定义一个request()方法,用于请求权限。在这个方法中,检查应用是否已被授予所需的权限。如果已被授予,直接调用回调方法通知调用者。如果未被授予,动态申请权限。例如:
public class PermissionRequester {

    private Activity mActivity;

    public PermissionRequester(Activity activity) {
        mActivity = activity;
    }

    public void request(String permission, final OnPermissionGrantedListener listener) {
        if (ContextCompat.checkSelfPermission(mActivity, permission) == PackageManager.PERMISSION_GRANTED) {
            // 权限已被授予,直接回调通知调用者
            listener.onPermissionGranted();
        } else {
            // 权限未被授予,动态申请权限
            ActivityCompat.requestPermissions(mActivity, new String[]{permission}, new OnPermissionRequestResultListener() {
                @Override
                public void onPermissionRequestResult(boolean granted) {
                    if (granted) {
                        // 权限已被授予,回调通知调用者
                        listener.onPermissionGranted();
                    } else {
                        // 权限未被授予,回调通知调用者
                        listener.onPermissionDenied();
                    }
                }
            });
        }
    }

    public interface OnPermissionGrantedListener {
        void onPermissionGranted();

        void onPermissionDenied();
    }
}
  1. 在您的Activity中,调用PermissionRequester类的request()方法来请求权限,并传递一个回调接口。例如:
private void initPermission() {
    mPermissionRequester = new PermissionRequester(this);
    mPermissionRequester.request(Manifest.permission.CAMERA, new PermissionRequester.OnPermissionGrantedListener() {
        @Override
        public void onPermissionGranted() {
            // 相机权限已被授予,可以直接使用相机
        }

        @Override
        public void onPermissionDenied() {
            // 用户拒绝了相机权限,需要向用户解释为什么需要该权限,并提供一个适当的操作,例如打开应用设置页面让用户手动授予权限
        }
    });
}

这些是实现运行时动态申请权限Lazy模式的基本步骤。请注意,不同的权限可能需要不同的处理方式,具体取决于您的应用需求。您可以根据需要进行适当的调整和扩展。


运行时动态申请权限Hungry模式

运行时动态申请权限Hungry模式是一种在需要权限的时候立即请求权限,并在请求结果返回后处理权限请求结果的方式。

实现Hungry模式的基本步骤如下:

  1. 在您的Activity中,定义一个PermissionRequester类。这个类将负责处理权限请求和权限请求结果。例如:
public class MainActivity extends AppCompatActivity {

    private PermissionRequester mPermissionRequester;
    
    // ...
    
    private void initPermission() {
        mPermissionRequester = new PermissionRequester(this);
        mPermissionRequester.request(Manifest.permission.CAMERA, new PermissionRequester.OnPermissionRequestResultListener() {
            @Override
            public void onPermissionRequestResult(boolean granted) {
                if (granted) {
                    // 权限已被授予,可以直接使用相机
                } else {
                    // 用户拒绝了相机权限,需要向用户解释为什么需要该权限,并提供一个适当的操作,例如打开应用设置页面让用户手动授予权限
                }
            }
        });
    }
    
    // ...
}
  1. PermissionRequester类中,定义一个request()方法,用于请求权限。在这个方法中,检查应用是否已被授予所需的权限。如果已被授予,直接调用回调方法通知调用者。如果未被授予,动态申请权限并在回调方法中处理权限请求结果。例如:
public class PermissionRequester {

    private Activity mActivity;

    public PermissionRequester(Activity activity) {
        mActivity = activity;
    }

    public void request(String permission, final OnPermissionRequestResultListener listener) {
        if (ContextCompat.checkSelfPermission(mActivity, permission) == PackageManager.PERMISSION_GRANTED) {
            // 权限已被授予,直接回调通知调用者
            listener.onPermissionRequestResult(true);
        } else {
            // 权限未被授予,动态申请权限
            ActivityCompat.requestPermissions(mActivity, new String[]{permission}, new OnPermissionRequestResultListener() {
                @Override
                public void onPermissionRequestResult(boolean granted) {
                    // 回调通知调用者
                    listener.onPermissionRequestResult(granted);
                }
            });
        }
    }

    public interface OnPermissionRequestResultListener {
        void onPermissionRequestResult(boolean granted);
    }
}
  1. 在您的Activity中,调用PermissionRequester类的request()方法来请求权限,并传递一个回调接口。在回调接口的方法中处理权限请求结果。例如:
private void initPermission() {
    mPermissionRequester = new PermissionRequester(this);
    mPermissionRequester.request(Manifest.permission.CAMERA, new PermissionRequester.OnPermissionRequestResultListener() {
        @Override
        public void onPermissionRequestResult(boolean granted) {
            if (granted) {
                // 权限已被授予,可以直接使用相机
            } else {
                // 用户拒绝了相机权限,需要向用户解释为什么需要该权限,并提供一个适当的操作,例如打开应用设置页面让用户手动授予权限
            }
        }
    });
}

这些是实现运行时动态申请权限Hungry模式的基本步骤。请注意,不同的权限可能需要不同的处理方式,具体取决于您的应用需求。您可以根据需要进行适当的调整和扩展。


利用ContentObserver监听短信

要利用ContentObserver监听短信通知,可以按照以下步骤进行操作:

  1. 创建一个继承自ContentObserver的类,用于监听短信通知的变化。在这个类中,重写onChange()方法来处理短信通知的变化。例如:
public class SmsContentObserver extends ContentObserver {
    private Context mContext;

    public SmsContentObserver(Context context) {
        super(null);
        mContext = context;
    }

    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);
        // 处理短信通知的变化
    }
}
  1. 在需要监听短信通知的地方,注册ContentObserver。例如,在Activity的onCreate()方法中注册ContentObserver:
private SmsContentObserver mSmsContentObserver;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mSmsContentObserver = new SmsContentObserver(this);
    getContentResolver().registerContentObserver(Telephony.Sms.CONTENT_URI, true, mSmsContentObserver);
}
  1. 在不需要监听短信通知的地方,记得取消注册ContentObserver。例如,在Activity的onDestroy()方法中取消注册:
@Override
protected void onDestroy() {
    super.onDestroy();
    getContentResolver().unregisterContentObserver(mSmsContentObserver);
}

通过以上步骤,您可以利用ContentObserver监听短信通知的变化。在onChange()方法中,您可以处理短信通知的变化,例如提取短信内容、发送通知等。请注意,您需要获取相应的权限(如READ_SMS)才能监听短信通知。

notifyForDescendentsContentObserver的一个方法,用于指定是否监听指定URI的所有子URI。当设置为true时,如果指定的URI有任何子URI发生变化,ContentObserver会收到通知;当设置为false时,只有指定的URI本身发生变化时,ContentObserver才会收到通知。

使用notifyForDescendents方法时,需要在注册ContentObserver时指定notifyForDescendents参数。例如:

getContentResolver().registerContentObserver(uri, true, contentObserver);

其中,uri是要监听的URI,true表示监听所有子URI的变化,contentObserver是继承自ContentObserver的观察者对象。

如果您只想监听指定URI本身的变化,而不关心其子URI的变化,可以将notifyForDescendents参数设置为false

getContentResolver().registerContentObserver(uri, false, contentObserver);

ContentObserveronChange方法中,可以根据需要处理收到的通知。例如,可以提取变化的数据、更新界面等操作。

请注意,notifyForDescendents方法在不同的Android版本中可能会有不同的行为,请根据您的需求和目标设备选择适当的设置。

跳转相册选图片发送彩信

要实现从相册选择图片并发送彩信,您可以按照以下步骤进行操作:

  1. 在AndroidManifest.xml文件中添加相应的权限:
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
  1. 在您的Activity中添加一个按钮,用于触发选择图片的操作:
<Button
    android:id="@+id/choose_image_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="选择图片" />
  1. 在Activity中,为按钮添加点击事件,并在事件处理方法中打开相册:
private static final int REQUEST_CODE_PICK_IMAGE = 1;

Button chooseImageButton;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    chooseImageButton = findViewById(R.id.choose_image_button);
    chooseImageButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            openGallery();
        }
    });
}

private void openGallery() {
    Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(intent, REQUEST_CODE_PICK_IMAGE);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == REQUEST_CODE_PICK_IMAGE && resultCode == RESULT_OK && data != null) {
        Uri imageUri = data.getData();
        sendMms(imageUri);
    }
}
  1. 在Activity中添加一个发送彩信的方法,该方法将选择的图片Uri作为参数:
private void sendMms(Uri imageUri) {
    Intent intent = new Intent(Intent.ACTION_SEND);
    intent.putExtra(Intent.EXTRA_STREAM, imageUri);
    intent.setType("image/*");
    startActivity(intent);
}

请注意,上述代码中的REQUEST_CODE_PICK_IMAGE是一个用于标识打开相册请求的常量,您可以根据需要自定义该常量的值。

通过以上步骤,您可以实现从相册选择图片并发送彩信的功能。当用户选择了图片后,会调用onActivityResult()方法,其中可以获取到选择的图片Uri,然后调用sendMms()方法发送彩信。请注意,您需要获取相应的权限(如SEND_SMS和READ_EXTERNAL_STORAGE)才能发送彩信和读取外部存储中的图片。

通过MediaStore查询图片

要使用MediaStore查询图片的详细信息,您可以按照以下步骤进行操作:

  1. 在AndroidManifest.xml文件中添加相应的权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
  1. 在Activity中引入以下包:
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
  1. 在Activity的onCreate()方法中调用查询图片详细信息的方法:
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    queryImageDetails();
}
  1. 在Activity中编写查询图片详细信息的方法:
private void queryImageDetails() {
    Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
    String[] projection = {
            MediaStore.Images.Media._ID,
            MediaStore.Images.Media.DISPLAY_NAME,
            MediaStore.Images.Media.SIZE,
            MediaStore.Images.Media.DATE_ADDED
    };

    Cursor cursor = getContentResolver().query(uri, projection, null, null, null);

    if (cursor != null) {
        while (cursor.moveToNext()) {
            long id = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media._ID));
            String name = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME));
            long size = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media.SIZE));
            long dateAdded = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media.DATE_ADDED));

            Log.d(TAG, "ID: " + id);
            Log.d(TAG, "Name: " + name);
            Log.d(TAG, "Size: " + size);
            Log.d(TAG, "Date Added: " + dateAdded);
        }

        cursor.close();
    }
}

在上述代码中,我们使用MediaStore.Images.Media.EXTERNAL_CONTENT_URI作为查询的URI,该URI用于查询外部存储中的图片。我们还定义了一个投影数组,包含要查询的列,例如图片的ID、显示名称、大小和添加日期。

然后,我们使用getContentResolver().query()方法执行查询,并遍历查询结果。在循环中,我们提取每个图片的详细信息,例如ID、名称、大小和添加日期,并将其打印到日志中。

请注意,您可以根据需要调整投影数组和查询条件,以获取您所需的图片详细信息。

通过以上步骤,您可以使用MediaStore查询图片的详细信息。


借助FileProvider发送彩信

要使用FileProvider发送彩信,首先需要进行以下几个步骤:

  1. 在AndroidManifest.xml文件中,添加FileProvider的配置。在<application>标签内添加以下代码:
<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="your.package.name.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>

your.package.name替换为您的应用程序的包名。

  1. 在res/xml文件夹中创建一个名为file_paths.xml的文件,并添加以下代码:
<paths>
    <external-path name="external_files" path="."/>
</paths>

这将允许您访问应用的外部文件目录。

  1. 在您要发送的彩信方法中,创建一个File对象,以便发送的文件。
File file = new File(getExternalFilesDir(null), "your_file_name.extension");

your_file_name.extension替换为您要发送的文件的名称和扩展名。

  1. 使用FileProvider获取文件的Uri。
Uri fileUri = FileProvider.getUriForFile(this, "your.package.name.fileprovider", file);

your.package.name替换为您的应用程序的包名。

  1. 创建一个Intent来发送彩信。
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_STREAM, fileUri);
intent.setType("image/*"); // 根据您要发送的文件类型进行设置
intent.setPackage("com.android.mms"); // 设置彩信应用的包名
startActivity(intent);

请注意,上面的示例代码假设您要发送的是图像文件。如果要发送其他类型的文件,请相应地更改setType()方法的参数。

这样,您就可以使用FileProvider发送彩信了。确保您的应用程序具有适当的权限,并且彩信应用程序已安装在用户的设备上。


安卓应用安装

Environment.getExternalStoragePublicDirectory()是一个Android方法,用于获取外部存储器上的公共目录路径。外部存储器通常是指SD卡或者其他可移动存储设备。

该方法的语法如下:

File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_NAME);

其中,DIRECTORY_NAME是一个参数,用于指定要获取的公共目录类型。常见的目录类型包括:

  • DIRECTORY_DOCUMENTS:文档目录,用于存储用户文档文件。
  • DIRECTORY_DOWNLOADS:下载目录,用于存储下载的文件。
  • DIRECTORY_PICTURES:图片目录,用于存储用户拍摄的照片。
  • DIRECTORY_DCIM:相机目录,用于存储相机拍摄的照片和视频。

例如,要获取外部存储器上的下载目录路径,可以使用以下代码:

File downloadDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);

需要注意的是,使用Environment.getExternalStoragePublicDirectory()方法需要在AndroidManifest.xml文件中添加适当的权限声明:

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

此外,从Android Q (10)开始,对外部存储器的访问权限有所变化。在Android Q及更高版本中,应用程序无法直接访问外部存储器上的公共目录,而是需要使用MediaStore API或者Storage Access Framework来进行访问。

  • 36
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值