首页 > 其他分享 >【Android学习】四大组件

【Android学习】四大组件

时间:2024-10-24 11:45:28浏览次数:8  
标签:Service 广播 Intent Activity 组件 四大 Android intent public

目录

 一、Activity:用户界面的核心

二、Service:后台处理任务

三、BroadcastReceiver:处理广播消息

四、ContentProvider:应用间共享数据

 一、Activity:用户界面的核心

Activity 是 Android 应用的核心组成部分之一,主要负责展示用户界面,响应用户的交互操作。每个 Activity 通常对应一个独立的屏幕,用户可以在多个 Activity 之间进行切换。

1.功能

  • 作为应用的 UI 界面。
  • 处理用户交互,响应用户的点击、输入等操作。
  • 管理 Activity 的生命周期,控制界面的启动、暂停、销毁等状态。

2.生命周期

2.1生命周期方法

  • onCreate():Activity 被创建时调用,通常用于进行初始化操作,比如设置布局、初始化 UI 元素、绑定数据等。
  • onStart():Activity 正在启动,并即将变为可见状态,但此时还没有获取焦点。
  • onResume():Activity 开始与用户交互,并成为用户当前操作的界面。
  • onPause():Activity 正在停止与用户交互,通常用户切换到另一个 Activity 时会调用,需在此释放一些非必要的资源。
  • onStop():Activity 不再可见,进入后台,通常此时应释放所有资源,以防止内存泄露。
  • onRestart():Activity 从不可见状态重新进入可见状态(从后台切回前台)时调用。
  • onDestroy():Activity 被销毁时调用,进行清理工作,释放所有资源。

 2.2生命周期流程图

3.启动模式

3.1 标准模式 (standard)
  • 默认模式,每次启动一个 Activity,都会创建一个新的实例。
  • 应用场景:一般用于不需要重复检查 Activity 实例的普通页面。
3.2 单顶模式 (singleTop)
  • 如果任务栈的顶部已经存在该 Activity 的实例,则不会重新创建实例,而是复用栈顶的实例。
  • 应用场景:常用于详情页面、设置页面等多次打开,但不希望重复创建实例的场景。
3.3 单任务模式 (singleTask)
  • 在任务栈中只会存在一个实例,如果任务栈中已经存在该 Activity,则复用此实例,并清除其上的所有 Activity。
  • 应用场景:用于需要保证某个 Activity 在任务栈中始终唯一的场景,如主页面、导航页面。
3.4 单实例模式 (singleInstance)
  • 在整个系统中只会存在一个该 Activity 的实例,无论是哪个应用启动此 Activity,都会复用同一个实例。
  • 应用场景:用于特殊应用场景,比如独占全局的 Activity,例如系统的拨号界面等。

4. Activity之间的通信

Activity 之间的通信主要通过 Intent 实现,Intent 是 Android 中用来启动组件(如 Activity、Service)和传递数据的重要机制。

4.1 启动另一个 Activity

Intent intent = new Intent(MainActivity.this, SecondActivity.class);
startActivity(intent);  // 启动 SecondActivity

4.2 启动并传递数据

Intent intent = new Intent(MainActivity.this, SecondActivity.class);
intent.putExtra("key", "value");
startActivity(intent);

在 SecondActivity 中接收数据:

String value = getIntent().getStringExtra("key");

4.3 返回结果

有时我们希望启动一个 Activity,并从中获取返回结果。可以使用 startActivityForResult() 来启动,并在 onActivityResult() 中接收返回的数据。

启动并期待返回结果:

Intent intent = new Intent(MainActivity.this, SecondActivity.class);
startActivityForResult(intent, REQUEST_CODE);

在 SecondActivity 中返回结果:

Intent intent = new Intent();
intent.putExtra("result", "value");
setResult(RESULT_OK, intent);
finish();

在 MainActivity 中接收返回结果:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_CODE && resultCode == RESULT_OK) {
        String result = data.getStringExtra("result");
        // 处理结果
    }
}

5. Activity的UI管理

Activity 是 UI 展示的核心,主要通过 XML 布局文件和代码相结合的方式管理界面。每个 Activity 通常对应一个布局文件,布局文件中定义了 UI 组件的位置和样式,代码中处理这些组件的行为。

5.1 设置布局

在 onCreate() 方法中通过 setContentView() 设置布局:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);  // 设置对应的布局文件
}

5.2 访问 UI 元素

通过 findViewById() 访问布局中的 UI 组件:

Button button = findViewById(R.id.myButton);
button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // 按钮点击事件
    }
});

6.注意事项

  • 管理好 Activity 的生命周期,确保资源的合理分配与回收,避免内存泄漏。
  • 注意横竖屏切换时生命周期的变化,需要妥善处理。

二、Service:后台处理任务

Service 是 Android 的后台组件,用于在不需要用户界面交互的情况下执行长时间运行的任务,例如音乐播放、下载文件等。Service 是在后台运行的,不会直接与用户交互。

1.功能

  • 执行后台操作,如网络请求、播放音频、同步数据等。
  • 可以与 Activity 进行交互,但没有用户界面。

2. Service的分类

Android 中 Service 分为三种主要类型,每种类型适合不同的应用场景。

2.1 普通服务(Started Service)

Started Service 是通过调用 startService() 方法启动的。服务一旦启动,即使启动它的 Activity 被销毁,服务仍然可以在后台继续运行,直到调用 stopSelf() 或 stopService() 来停止服务。

  • 启动方式:startService() 或 Context.startForegroundService()
  • 停止方式:调用 stopSelf() 或 stopService()。
  • 典型场景:如音乐播放、文件下载等需要持续运行的任务。
Intent intent = new Intent(this, MyService.class);
startService(intent);  // 启动服务

2.2 绑定服务(Bound Service)

Bound Service 允许其他组件通过绑定的方式与服务交互。通过 bindService() 方法启动并绑定服务,组件可以与服务进行通信。服务在所有绑定的客户端解绑后会自动销毁。

  • 启动方式:bindService()
  • 停止方式:当所有绑定的客户端解绑后,服务会自动销毁。
  • 典型场景:如客户端与服务端的交互,或者需要与应用频繁交互的任务。
Intent intent = new Intent(this, MyService.class);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);  // 绑定服务

2.3 前台服务(Foreground Service)

Foreground Service 是一种特殊的 Started Service,它会在通知栏显示一个通知,以提高优先级,避免系统在资源紧张时优先关闭它。

  • 启动方式:Context.startForegroundService(),并在服务中调用 startForeground() 方法显示通知。
  • 典型场景:如音乐播放器在后台播放音乐、导航应用持续提供GPS导航等。
Intent intent = new Intent(this, MyService.class);
startForegroundService(intent);  // 启动前台服务

在 Service 中调用 startForeground():

Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
    .setContentTitle("Foreground Service")
    .setContentText("Running in the background")
    .setSmallIcon(R.drawable.ic_service)
    .build();
startForeground(1, notification);  // 显示前台服务的通知

3. Service的生命周期

Service 的生命周期方法与 Activity 类似,但其核心不同点在于 Service 是后台运行,不涉及用户交互。

3.1 Started Service的生命周期

onCreate():服务创建时调用,仅调用一次,通常用于初始化服务资源。

onStartCommand():每次通过 startService() 启动服务时调用,执行具体任务的逻辑。返回值决定了系统在服务终止后的行为。

  • START_STICKY:服务终止后会自动重启,适用于需要持续运行的服务(如音乐播放、下载服务)。
  • START_NOT_STICKY:服务终止后不会自动重启,适用于不需要持续运行的短期任务。
  • START_REDELIVER_INTENT:服务终止后会自动重启,并重新传递最后一个 Intent,适用于需要继续处理上次未完成任务的情况。

onDestroy():服务被销毁时调用,用于清理资源。

3.2 Bound Service的生命周期

onCreate():服务创建时调用。

onBind():服务被绑定时调用,返回一个 IBinder 实例,用于客户端与服务通信。

onUnbind():当所有客户端解绑时调用。

onDestroy():服务销毁时调用。

3. Service与线程

Service 本身运行在主线程中,任何长时间的操作(如网络请求、文件下载)应在另一个线程如果直接在 Service 中执行耗时任务,可能会阻塞 UI 线程,导致应用无响应(ANR)。因此,开发者通常使用线程池、Handler 或者 IntentService 来处理异步任务。

3.1 使用线程池 (ThreadPoolExecutor) 来处理异步任务

线程池 是一种高效的异步任务处理方式,可以管理多个并发任务。通过创建线程池,开发者可以限制同时执行的任务数量,并优化性能。

public class MyService extends Service {

    private ExecutorService executorService;

    @Override
    public void onCreate() {
        super.onCreate();
        // 创建线程池
        executorService = Executors.newFixedThreadPool(3);  // 设置最多3个并发线程
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // 向线程池提交任务
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                // 在后台执行耗时任务,比如文件下载
                performLongRunningTask();
            }
        });
        return START_STICKY;
    }

    private void performLongRunningTask() {
        // 模拟长时间操作
        try {
            Thread.sleep(5000);  // 模拟耗时任务
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (executorService != null) {
            executorService.shutdown();  // 关闭线程池
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;  // 如果不是 Bound Service 返回null
    }
}

3.2 使用 HandlerThread 和 Handler 来处理异步任务

HandlerThread 是一个带有 Looper 的线程,用于处理与 Handler 的消息通信。它特别适合在后台执行异步任务,并且提供了消息调度的能力。

public class MyService extends Service {

    private HandlerThread handlerThread;
    private Handler handler;

    @Override
    public void onCreate() {
        super.onCreate();
        // 创建一个HandlerThread
        handlerThread = new HandlerThread("MyServiceThread");
        handlerThread.start();
        // 使用HandlerThread的Looper创建Handler
        handler = new Handler(handlerThread.getLooper());
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // 向Handler发送任务
        handler.post(new Runnable() {
            @Override
            public void run() {
                // 在后台线程中执行任务
                performLongRunningTask();
            }
        });
        return START_STICKY;
    }

    private void performLongRunningTask() {
        // 模拟长时间操作
        try {
            Thread.sleep(5000);  // 模拟耗时任务
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        handlerThread.quit();  // 退出HandlerThread
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;  // 如果不是 Bound Service 返回null
    }
}

3.3 使用 IntentService 处理异步任务

IntentService 是 Service 的一个子类,它专门用于处理异步请求,并且是自带一个工作线程来处理耗时任务。任务处理完毕后,IntentService 会自动停止。

public class MyIntentService extends IntentService {

    public MyIntentService() {
        super("MyIntentService");
    }

    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        // 处理任务的逻辑
        performLongRunningTask();
    }

    private void performLongRunningTask() {
        // 模拟长时间操作
        try {
            Thread.sleep(5000);  // 模拟耗时任务
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

启动 IntentService:

Intent intent = new Intent(this, MyIntentService.class);
startService(intent);

4. 注意事项

  • 在服务中执行长时间运行的任务时,应该考虑资源管理,避免占用过多电量或内存。
  • 一般情况下,Foreground Service 优先级最高,普通 Service优先级较低,容易被系统回收。如果需要后台运行的 Service 在用户看不见时不被系统杀死,可以使用Foreground Service,显示一个持续的通知。

三、BroadcastReceiver:处理广播消息

BroadcastReceiver 是 Android 中用于接收系统或应用发送的广播消息的组件。广播机制是 Android 中用于跨应用或跨进程通信的方式,应用可以通过广播发送和接收消息。

1. 功能

  • 接收系统广播,如电量低、网络状态变化等。
  • 接收应用内广播,用于不同模块之间的消息传递。

 2. BroadcastReceiver的工作原理

当某个事件发生时,系统或应用会通过发送一个 Intent 来广播该事件。所有注册了相关广播事件的BroadcastReceiver都可以接收到这个广播,并在广播到达时执行预定义的任务。

基本工作流程如下:

  1. 广播发送方:通过sendBroadcast()、sendOrderedBroadcast()或sendStickyBroadcast()方法发送广播。
  2. 广播接收方:通过注册的BroadcastReceiver接收相应的广播。
  3. 处理逻辑:在BroadcastReceiver的onReceive()方法中,处理接收到的广播消息。

3. BroadcastReceiver的注册方式

3.1 静态注册

静态注册的 BroadcastReceiver 是在AndroidManifest.xml中声明的,通常用于接收设备启动、安装应用、网络变化等系统级广播,即使应用未启动,仍然可以接收到广播。

<receiver android:name=".MyBroadcastReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
    </intent-filter>
</receiver>

3.2 动态注册

动态注册的BroadcastReceiver是在代码中通过registerReceiver()方法进行的,适用于应用在运行期间才需要监听的事件。

public class MainActivity extends AppCompatActivity {
    private MyBroadcastReceiver myReceiver;

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

        myReceiver = new MyBroadcastReceiver();
        IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
        registerReceiver(myReceiver, filter);  // 动态注册广播接收器
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(myReceiver);  // 动态注册的广播接收器需及时解除
    }
}

4. BroadcastReceiver的生命周期

BroadcastReceiver的生命周期很短,通常在广播到来时会触发onReceive()方法,处理完成后即终止。广播接收器并不需要一直运行。

  • onReceive():当广播到达时调用,可以根据广播的内容执行相应的操作。

5. 广播的收发

Android 提供了多种广播收发形式,分别适合不同的应用场景。广播通常通过Intent进行传递,接收者可以注册特定的广播接收器(BroadcastReceiver)来监听广播事件。

5.1 标准广播(Normal Broadcast)

标准广播是通过sendBroadcast()方法发送的。它是并发执行的,所有匹配的BroadcastReceiver同时接收广播,不保证接收顺序。

发送标准广播:

Intent intent = new Intent("com.example.CUSTOM_BROADCAST");
sendBroadcast(intent);  // 发送标准广播

接收标准广播:通过动态或静态方式注册广播接收器来接收广播。

  • 动态注册:
public class MyBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // 处理广播
        Toast.makeText(context, "Received broadcast!", Toast.LENGTH_SHORT).show();
    }
}

public class MainActivity extends AppCompatActivity {
    private MyBroadcastReceiver myReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        myReceiver = new MyBroadcastReceiver();
        IntentFilter filter = new IntentFilter("com.example.CUSTOM_BROADCAST");
        registerReceiver(myReceiver, filter);  // 动态注册广播接收器
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(myReceiver);  // 动态注册的广播需要解除注册
    }
}
  • 静态注册:
<receiver android:name=".MyBroadcastReceiver">
    <intent-filter>
        <action android:name="com.example.CUSTOM_BROADCAST"/>
    </intent-filter>
</receiver>

5.2 有序广播(Ordered Broadcast)

有序广播是通过sendOrderedBroadcast()方法发送的,它允许多个接收器按优先级顺序接收广播。高优先级的接收器可以截断广播或修改广播数据,广播按照优先级从高到低传递。

发送有序广播:

Intent intent = new Intent("com.example.CUSTOM_ORDERED_BROADCAST");
sendOrderedBroadcast(intent, null);  // 发送有序广播

接收有序广播:接收有序广播的BroadcastReceiver可以通过setResultData()等方法修改广播数据,并决定是否继续将广播传递给下一个接收器。

public class MyOrderedBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String resultData = getResultData();  // 获取前一个接收器设置的结果数据
        setResultData("Modified by receiver!");  // 修改广播内容
        Toast.makeText(context, "Ordered broadcast received", Toast.LENGTH_SHORT).show();
    }
}

通过priority属性设置广播接收器的优先级,值越高优先级越高。

<receiver android:name=".MyOrderedBroadcastReceiver">
    <intent-filter>
        <action android:name="com.example.CUSTOM_ORDERED_BROADCAST"/>
        <priority android:value="100"/>
    </intent-filter>
</receiver>

5.3 静态广播

静态广播是通过在AndroidManifest.xml文件中声明广播接收器实现的。静态注册的广播接收器可以在应用未启动的情况下接收广播,常用于监听设备启动、电池状态等系统广播。

<receiver android:name=".BootReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
    </intent-filter>
</receiver>

BOOT_COMPLETED 是设备启动完成后系统发送的广播,静态注册的接收器可以在设备重启后自动执行操作。

 6. 本地广播(LocalBroadcast)

在Android中,也可以使用LocalBroadcastManager发送本地广播。相比于全局广播,本地广播只在应用内部传递,效率更高,并且不会泄露数据给其他应用,安全性更好。

使用本地广播: 

1.注册本地广播接收器:

LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this);
IntentFilter filter = new IntentFilter("com.example.LOCAL_BROADCAST");
localBroadcastManager.registerReceiver(myReceiver, filter);

2.发送本地广播:

Intent localIntent = new Intent("com.example.LOCAL_BROADCAST");
LocalBroadcastManager.getInstance(this).sendBroadcast(localIntent);

3.解除注册: 

LocalBroadcastManager.getInstance(this).unregisterReceiver(myReceiver);

7. 监听系统广播

Android 系统会在特定的事件发生时发送系统广播,应用程序可以通过注册广播接收器来监听这些事件。

7.1 监听网络变更广播

ConnectivityManager.CONNECTIVITY_ACTION是网络连接状态变化时系统发送的广播。当设备从离线变为在线或网络状态发生变化时,应用可以接收此广播并执行相应操作。

定义一个网络广播的接收:

public class NetworkChangeReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = cm.getActiveNetworkInfo();
        
        if (networkInfo != null && networkInfo.isConnected()) {
            Toast.makeText(context, "Network Connected", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(context, "Network Disconnected", Toast.LENGTH_SHORT).show();
        }
    }
}

 动态注册广播接收器:

@Override
protected void onStart() {
    super.onStart();
    
    // 创建广播接收器
    NetworkChangeReceiver networkChangeReceiver = new NetworkChangeReceiver();
    IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
     // 注册接收器
    registerReceiver(networkChangeReceiver, filter);
}

@Override
protected void onStop() {
    super.onStop();
     // 注销接收器
    unregisterReceiver(networkChangeReceiver);
}

7.2监听分钟到达广播

ACTION_TIME_TICK是系统每分钟发送一次的广播,常用于在应用中处理与时间相关的功能,比如更新 UI 上的时间显示。

定义一个分钟广播的接收器:

public class TimeTickReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "Minute passed", Toast.LENGTH_SHORT).show();
    }
}

 由于ACTION_TIME_TICK是频繁触发的广播,在Android 8.0及之后,静态注册无法接收此类广播。必须使用动态注册的方式。

@Override
protected void onStart() {
    super.onStart();
    
    TimeTickReceiver timeTickReceiver = new TimeTickReceiver();
    IntentFilter filter = new IntentFilter(Intent.ACTION_TIME_TICK);
    registerReceiver(timeTickReceiver, filter);
}

@Override
protected void onStop() {
    super.onStop();
    unregisterReceiver(timeTickReceiver);
}

7.3 监听系统闹钟广播

AlarmManager可以设置定时任务,定时到达后系统会发送广播进行唤醒。通过设置闹钟,我们可以使用AlarmManager来调度任务,并通过BroadcastReceiver监听定时任务触发的广播。

定义一个闹钟广播的接收器:

public class AlarmReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // 处理闹钟到达事件
        Toast.makeText(context, "Alarm received!", Toast.LENGTH_SHORT).show();
    }
}

 设置定时器:

// 从系统服务中获取闹钟管理器
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
// 创建一个广播事件的意图
Intent intent = new Intent(this, AlarmReceiver.class);
// 创建一个用于广播的延迟意图
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
// 设置一个5秒后触发的闹钟
long triggerTime = System.currentTimeMillis() + 5000;
alarmManager.setExact(AlarmManager.RTC_WAKEUP, triggerTime, pendingIntent);

 静态注册广播接收器:

<receiver android:name=".AlarmReceiver"/>

7.4 监听开机启动广播

BOOT_COMPLETED是设备启动后系统发送的广播,用于执行设备重启后的任务(如启动服务、初始化数据等)。需要注意,接收此广播必须在 AndroidManifest.xml 中静态注册,并且应用需要声明权限。

定义一个分钟广播的接收器:

public class BootReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
            // 处理设备启动完成后的操作
            Toast.makeText(context, "Device booted", Toast.LENGTH_SHORT).show();
        }
    }
}

静态注册广播接收器:

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

<receiver android:name=".BootReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
    </intent-filter>
</receiver>

8. 权限与安全性

某些广播,尤其是系统广播,需要在AndroidManifest.xml中声明权限。此外,广播的安全性也很重要。如果广播包含敏感信息或需要保护,应该避免使用全局广播。相反,使用本地广播或通过限制广播权限来保护广播内容。

四、ContentProvider:应用间共享数据

ContentProvider 是 Android 提供的用于跨应用共享数据的组件。通过 ContentProvider,一个应用可以提供数据供其他应用访问,并控制数据的权限和访问方式。系统内置了很多 ContentProvider,比如访问联系人、媒体文件等。

1. 功能

  • 在应用间共享数据,提供标准的接口供其他应用访问。
  • 支持 CRUD(增删改查)操作,允许其他应用按需读取、更新、删除数据。

 2. ContentProvider的结构

ContentProvider提供了操作数据的基本接口,主要包括以下方法:

  • onCreate():初始化数据库,通常在这个方法中你会创建或打开SQLite 数据库。
  • query():返回一个Cursor对象,供查询数据使用。
  • insert():插入新的数据,返回新插入行的URI。
  • update():更新已有数据,根据条件返回更新的行数。
  • delete():删除数据,根据条件删除并返回受影响的行数。
  • getType():返回MIME类型,表示该URI对应的是单条数据还是多条数据。

3. ContentProvider的注册方式

ContentProvider必须在AndroidManifest.xml中静态注册。系统在需要的时候会自动初始化该ContentProvider。

<provider
    android:name=".MyContentProvider"
    android:authorities="com.example.provider"
    android:exported="true" />
  • android:authorities:定义该ContentProvider的授权名,其他应用通过这个名称访问它。
  • android:exported:如果设置为true,表示允许其他应用访问;设置为false时,只能供本应用访问。

4. 访问ContentProvider的数据

应用要访问ContentProvider提供的数据,需要通过ContentResolver来执行增删改查操作。

  • query():从内容提供器中检索数据。
  • insert():向内容提供器中插入新的数据行。
  • update():修改内容提供器中的现有数据。
  • delete():从内容提供器中删除数据。

5. ContentProvider中的URI机制

在ContentProvider中,数据是通过URI来定位的。每个ContentProvider都有一个唯一的 URI,它由以下几个部分组成:

content://<authority>/<path>/<id>
  • content://:URI 的协议部分,固定为content://。
  • <authority>:表示该 ContentProvider 的授权名,通常是应用的包名。
  • <path>:表示数据的路径,通常是表名。
  • <id>:可选项,指定要操作的数据的ID。

在操作数据时,不同的URI可以用于标识特定的数据集或单条数据,区分全表查询和单行查询。

6. 常见的系统 ContentProvider

Android系统自带了一些常见的ContentProvider,开发者可以通过这些ContentProvider访问系统级数据。

6.1 通讯录(ContactsProvider)

  • URI:content://contacts/
  • 用途:访问设备中的联系人信息。
Cursor cursor = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);

6.2 媒体库(MediaStore)

  • URI:content://media/external/
  • 用途:访问设备中的音频、视频、图片等媒体文件。
Cursor cursor = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, null, null, null);

6.3 日历(CalendarProvider)

  • URI:content://com.android.calendar/
  • 用途:访问设备中的日历事件和日程。
Cursor cursor = getContentResolver().query(CalendarContract.Events.CONTENT_URI, null, null, null, null);

7. 安全性与权限控制

由于ContentProvider可能涉及多个应用的数据共享,安全性问题非常重要。为了保证数据的安全,Android提供了以下方式来保护ContentProvider。

7.1 声明权限:

可以通过声明权限来控制谁能够访问ContentProvider。在AndroidManifest.xml中,你可以通过android:permission属性来限制对 ContentProvider 的访问。

<provider
    android:name=".MyContentProvider"
    android:authorities="com.example.provider"
    android:permission="com.example.permission.ACCESS_PROVIDER" />

7.2 自定义权限:

开发者可以在AndroidManifest.xml中定义自定义权限: 

<permission android:name="com.example.permission.ACCESS_PROVIDER" android:protectionLevel="normal" />

 

标签:Service,广播,Intent,Activity,组件,四大,Android,intent,public
From: https://blog.csdn.net/m0_75208773/article/details/143154875

相关文章

  • Android MVVM
    AndroidMVVM介绍MVVM(Model-View-ViewModel)是Android开发中常用的一种架构模式。它将应用程序的逻辑分离为三个主要部分:Model(模型)、View(视图)和ViewModel(视图模型),从而使代码更清晰、更易于维护。1.Model(模型)Model代表应用程序的数据和业务逻辑。它负责处理数据的获取、存储和......
  • Android 应用自启动
    Android应用自启动监听系统广播(BroadcastReceiver):通过接收系统的BOOT_COMPLETED广播,可以在设备启动后自动启动应用或服务。你需要在AndroidManifest.xml中注册一个BroadcastReceiver,并监听BOOT_COMPLETED广播。<receiverandroid:name=".MySelfStartingBroadcastReceiver"......
  • 如何将rust日志输出到android终端
    本博客所有文章除特别声明外,均采用CCBY-NC-SA4.0许可协议。转载请注明来自唯你背景在Rust中,使用println!打印日志时,输出实际上是发送到标准输出(stdout),而AndroidLogcat专门用于处理和显示应用程序的日志信息,此环境下标准输出实现被重新定义。这意味着Rust日志输出不......
  • 熟悉架构框架:TOGAF的四大核心架构
    摘要:TOGAF(TheOpenGroupArchitectureFramework)是全球广泛应用的企业架构框架,帮助企业在数字化转型中实现业务和技术目标的统一。本文将带你深入了解TOGAF的四大核心架构:业务架构、应用架构、数据架构和技术架构,帮助你快速上手这一强大的工具。正文:引言在当今数字化转型......
  • 054 非单文件组件
    ......
  • FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库LD
    ijkplayer是一款由B站研发的移动端国产播放器,它基于FFmpeg3.4版本,同时兼容Android和iOS两大移动操作系统。ijkplayer的源码托管地址为https://github.com/bilibili/ijkplayer,截止2024年9月15日,ijkplayer获得3.24万星标数,以及0.81万个分支数,而这还是ijkplayer停止更新6年之后的数据......
  • Android之Manifest.xml文件的标签+属性
    Manifest.xml文件结构目录<?xmlversion="1.0"encoding="utf-8"?><manifest><uses-permission/><permission/><permission-tree/><permission-group/><instrumentation/>&......
  • React 类组件的生命周期
    React类组件的生命周期可以分成三个阶段:挂载(Mounting)阶段:当组件实例被创建并插入DOM中时,会调用的方法。更新(Updating)阶段:当组件的props或state发生变化时会调用的方法。卸载(Unmounting)阶段:当组件从DOM中移除时会调用的方法。以下是每个阶段典型的生命......
  • FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
    ijkplayer是一款由B站研发的移动端国产播放器,它基于FFmpeg3.4版本,同时兼容Android和iOS两大移动操作系统。ijkplayer的源码托管地址为https://github.com/bilibili/ijkplayer,截止2024年9月15日,ijkplayer获得3.24万星标数,以及0.81万个分支数,而这还是ijkplayer停止更新6年之后的数据......
  • 如何从 Android 设备远程访问 PC 文件?
    方法1.如何使用AnyViewer在Android上访问PC文件步骤1:下载AnyViewerPC版和Android版AnyViewer。您需要Android版本6.0及以上,然后在PC和Android设备上启动。步骤2:创建AnyViewer帐户并使用它登录您的设备(WindowsPC和Android手机)。步骤3:导航到And......