Android 四大组件

Android 四大组件

Activity :负责用户交互
Broadcast Intent Receiver :广播,负责组件之间的通讯的纽带
Service :服务,运行在应用后台,在不影响界面正常使用的情况下在后台处理相关业务
ContentProvider :内容提供者,负责数据存储以及共享

Intent 详细内容

Intent 主要负责系统中组件之间的消息传递的介质,可以通过配置其组件名、动作、数据以及类型等等特性来完成目标组件的精确查找。常见的用法

启动 Activity : startActivity startActivityForResult
发广播: sendBroadcast
启动服务: startService bindService

组件名 (ClassName/ComponentName)

Intent it = new Intent();
// 组件名对象
ComponentName cn = new ComponentName(MainActivity.this, Activity01.class);
it.setComponent(cn); // 设置组件名
startActivity(it);

可以配置目标组件的包名以及类名来完成精确的配置
ComponentName cn = new ComponentName("com.xykj.filemanager","com.xykj.filemanager.MainActivity");

注意:用包名和类名配置时,如果要访问其他应用的组件,那么对方的组件必须有入口的声明

<activity
android:name=".MainActivity"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
或者
<activity android:name=".WelcomeActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

组件名也可以直接使用 setClassName 方式简写

it.setClassName("com.xykj.filemanager","com.xykj.filemanager.MainActivity");

Intent 动作 ( 行为 )

Action 表示的是 Intent 的行为方式,不同的 Action 可以表示完成不同的功能:查看内容、删除、搜索等等可以描述对应组件能做的事情(相当于是用功能名称
标榜特性)

声明 action ,在 manifest 中注册组件时通过 <intent-filter> 标签来声明
<activity android:name="com.xykj.activity.Activity02">
<intent-filter>
<action android:name="abc123"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
使用端
Intent i2 = new Intent(); //Intent i2 = new Intent("abc123")
i2.setAction("abc123");
startActivity(i2);

Category

描述 action 的启动方式,常用有

桌面快捷图标的启动页
<category android:name="android.intent.category.LAUNCHER" />
默认方式
<category android:name="android.intent.category.DEFAULT" />

Intent 的数据 (Data) 以及类型 (Type)

处理 Action 的行为时一般在声明是可以配置需要处理的数据类型,然后使用端传递数据时配合相应的类型找目标

声明
<activity android:name="com.xykj.activity.Activity02"
android:label=" 秘密基地 ">
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<data android:mimeType="image/*"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<data 标签配置的是接收的数据的条件,数据都是 Uri 形式
<intent-filter>
<!-- 查看功能 -->
<action android:name="android.intent.action.VIEW"/>
<data android:mimeType="image/*" android:scheme="http|https" android:host="abc.com" android:path="/aa"/>
</intent-filter>
mimeType 源数据类型 scheme 表示数据 Uri 的前缀 host 表示 Uri 的唯一标识 path 子路径
使用端
Intent shareIntent = new Intent(Intent.ACTION_SEND);
// 配置数据和类型
shareIntent.setDataAndType(Uri.parse("/mnt/sdcard/media/pic.jpg"), "image/jpeg");
// 查找满足条件的目标,将目标显示出来
Intent target = Intent.createChooser(shareIntent, " 发送到 ");
if (target != null) {
startActivity(target);
}

被启动 Activity 中可以通过 Intent 的 getData 方法获取传过来的数据

Uri uri = it.getData();

序列化对象中有其他序列化属性时的处理方式

以 Bitmap 类型为例

写:
// 序列化的方法 ( 将对象写到流中 )
@Override
public void writeToParcel(Parcel dest, int flags) {
...
// 将 parcelable 对象写到流中
dest.writeParcelable(drawableIcon,flags);
}

读:
protected FileItem(Parcel in) {

// 需要使用对应类的类加载器
drawableIcon = in.readParcelable(Bitmap.class.getClassLoader());
}

基于应用包名启动对应应用

PackageManager pm = context.getPackageManager();
Intent it = pm.getLaunchIntentForPackage("com.xykj.filemanager");
context.startActivity(it);

广播接收器

声明
public class MyReceiver extends BroadcastReceiver {
// 接收到关注的消息时触发
@Override

public void onReceive(Context context, Intent intent) {
Log.e("m_tag"," 收到消息: "+intent.getAction());
Toast.makeText(context," 收到消息 :"+intent.getAction(),Toast.LENGTH_LONG).show();
}
}

注册:第一种注册方式是在 manifest 中注册,特性是常驻后台

<!--  静态注册,安装应用之后接收器常驻后台接收广播 -->
<receiver android:name="com.xykj.activity.MyReceiver">
<intent-filter>
<action android:name="helloabc"/>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
</intent-filter>
</receiver>

第二种注册,在 java 中使用 registReceiver 以及 unRegistReceiver 来注册和取消注册,特性灵活,占用资源低,优先级高

receiver = new ActReceiver();
// 添加关注的 Action
IntentFilter filter = new IntentFilter();
filter.addAction("helloabc");
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
// 注册广播
registerReceiver(receiver,filter);
取消注册
unregisterReceiver(receiver);

本地广播
如果不需要将广播信息发到系统中可以使用 v4 包中的 LocalBroadcastManager 来管理广播
注册:

// 本地广播
localReceiver = new ActReceiver();
IntentFilter f1 = new IntentFilter();
f1.addAction("aaabbb");
f1.addAction("helloabc");
LocalBroadcastManager.getInstance(this).registerReceiver(localReceiver,f1);

取消注册:

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

发广播:

Intent it2= new Intent("aaabbb");
LocalBroadcastManager.getInstance(this).sendBroadcast(it2);

服务

Service 运行在系统后台的组件,有独立的生命周期,不可见的后台 Context , Service 一般不能主动运行,一般由某个 Context 对象来启动,启动方式有
startService 、 bindService
1 、定义服务,继承 Service

public class MusicService extends Service {
@Override
public IBinder onBind(Intent intent) {
return null;
}
// 当第一次启动服务时,服务创建成功时触发
@Override
public void onCreate() {
super.onCreate();
Log.e("m_tag","===onCreate===");
}
// 当启动端使用 startService 时触发
// 启动端和服务的通讯入口
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("m_tag","===onStartCommand===");
return super.onStartCommand(intent, flags, startId);
}
// 销毁服务时触发
@Override
public void onDestroy() {
super.onDestroy();
Log.e("m_tag","===onDestroy===");
}
}

2 、在 manifest 中注册服务

<service android:name=".MusicService"
android:exported="false"
android:enabled="true">
<intent-filter>
<action android:name="abc123"/>
</intent-filter>
</service>
android:exported 属性表示是否运行其他应用隐式启动该服务
android:enabled 属性表示否是可以被系统实例化

3 、使用服务

Intent it3 = new Intent(MainActivity.this,MusicService.class);
startService(it3); // 启动服务
// 停止服务
stopService(it3);

onStartCommand 的返回值

START_STICKY :如果 Service 被 kill 掉了,系统保留 Service 运行状态,但是不保留 Intent 数据,当系统重新恢复了资源,那么尝试重新创建 Service ,
创建后会调用 onStartCommand ,但是 intent 为 null
START_NOT_STICKY :如果 Service 被 kill 了,系统不会重新启动服务
START_REDELIVER_INTENT :当 Service 被 kill 之后,系统恢复资源情况之后会重新启动服务,重传 Intent
START_STICKY_COMPATIBILITY :针对 START_STICKY 的兼容,但是不保证被 kill 之后一定能重启

通知

通知的管理需要用到通知管理器

// 获取通知管理器
nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

显示:

Notification notification;
Intent it = new Intent(this,Activity02.class);
//(Context 对象, Intent 的 id , Intent 对象,对 Intent 的更新方式 )
//FLAG_UPDATE_CURRENT 表示不销毁原来的 PendingIntent ,直接替换其中的 Intent 内容
//FLAG_CANCEL_CURRENT 表示取消当前的 PendingIntent ,重新创建新的 PendingIntent 对象
PendingIntent pIntent = PendingIntent.getActivity(this,1,it,PendingIntent.FLAG_UPDATE_CURRENT);
if(Build.VERSION.SDK_INT>=16){
Notification.Builder builder = new Notification.Builder(this);
// 显示在状态栏上的小图标
builder.setSmallIcon(R.drawable.noti_icon);
// 添加状态栏上提示的文本 ( 显示一段时间就自动消失 )
builder.setTicker(ticker);
// 下拉看到的内容标题和文本
builder.setContentTitle(contentTitle);
builder.setContentText(contentText);
// 通知时间
builder.setWhen(System.currentTimeMillis());
// 如果点击了内容部分,跳转到 Activity02 中
builder.setContentIntent(pIntent);
// 创建通知
notification = builder.build();
}else{
notification = new Notification(R.drawable.noti_icon,ticker,System.currentTimeMillis());
notification.contentIntent = pIntent;
}
// 自动取消 ( 当通知被点击了,那么系统会移除该通知 )
notification.flags = Notification.FLAG_AUTO_CANCEL;
// 显示通知
nm.notify(123456,notification);

隐藏通知
/

/ 隐藏通知
nm.cancel(123456);
nm.cancelAll(); 隐藏该应用下的所有通知

通知的 flags ,配置隐藏方式

notification.flags = Notification.FLAG_AUTO_CANCEL;
FLAG_AUTO_CANCEL :表示自动隐藏,当通知内容被点击之后执行了 Intent 动作,自动隐藏
FLAG_NO_CLEAR :不会被系统的 “ 清理 ” 按钮清除掉(下拉通知之后右上角的清理按钮)
FLAG_ONGOING_EVENT :将通知分配到 “ 正在运行中 ” 的组里面

通知的 notification.defaults ,可以设置闪灯、声音、震动等提醒方式

notification.defaults=Notification.DEFAULT_SOUND;
DEFAULT_SOUND 表示声音
DEFAULT_VIBRATE 表示震动
DEFAULT_LIGHTS 表示闪灯
DEFAULT_ALL 所有 ( 声音、震动、闪灯 )

自定义通知内容显示
1 、定义布局,如 :notification_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/n_icon"
android:layout_width="60dp"
android:layout_height="match_parent"
android:src="@mipmap/ic_launcher" />
<TextView
android:id="@+id/n_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_toRightOf="@id/n_icon"
android:text="ABC"
android:textColor="#FFFF0000"
android:textSize="20sp" />
<TextView
android:id="@+id/n_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@id/n_icon"
android:layout_alignLeft="@id/n_title"
android:text="ABC"
android:textColor="#FFffffff"
android:textSize="18sp" />
<ImageView
android:id="@+id/n_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/video_product_op_close"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"/>
</RelativeLayout>

2 、创建 RemoteViews

// 创建一个远程视图管理,
RemoteViews contentView = new RemoteViews(getApplication().getPackageName(),R.layout.notification_layout);
contentView.setTextViewText(R.id.n_title,contentTitle);
contentView.setTextViewText(R.id.n_content,contentText); // 设置文本框中显示的文本内容
contentView.setImageViewResource(R.id.n_icon,R.drawable.noti_icon); // 设置图片视图
// 设置自定义布局中的点击监听
// 关闭的 Intent
Intent closeIntent = new Intent(this,MusicService.class);
closeIntent.putExtra("opt",1);
PendingIntent closePending = PendingIntent.getService(this,2,closeIntent,PendingIntent.FLAG_UPDATE_CURRENT);
contentView.setOnClickPendingIntent(R.id.n_close,closePending);

3 、将 RemoteViews 设置到通知的内部布局上, 4.2 以上版本用 Builder 的

builder.setContent(contentView) 来设置
Notification.Builder builder = new Notification.Builder(this);
// 显示在状态栏上的小图标
builder.setSmallIcon(R.drawable.noti_icon);
// 添加状态栏上提示的文本 ( 显示一段时间就自动消失 )
builder.setTicker(ticker);
builder.setContent(contentView);
// 如果点击了内容部分,跳转到 Activity02 中
builder.setContentIntent(pIntent);
// 创建通知
notification = builder.build();
低版本
notification.contentView = contentView;

bindService 方式启动服务

1 、需要在 Service 的 onBind 方法中返回绑定成功的 Binder 对象

public class MusicService extends Service {
// 服务被绑定 ( 到某个 Context 上 ) 时触发
@Override
public IBinder onBind(Intent intent) {
Log.e("m_tag","==onBind===");
return new MyBinder();
}
class MyBinder extends Binder{
public void play(){
Log.e("m_tag","==play===");
}
public MusicService getService(){
return MusicService.this;
}
}
// 被解除绑定时触发
@Override
public boolean onUnbind(Intent intent) {
Log.e("m_tag","==onUnbind===");
return true;
}
// 被重新绑定时触发
// 当 startService 之后,服务运行,然后 bindService ,中途 unBindService ,此时服务还没有死掉再 bindService 时触发该方法
@Override
public void onRebind(Intent intent) {
super.onRebind(intent);
Log.e("m_tag","==onRebind===");
}
// 当第一次启动服务时,服务创建成功时触发
@Override
public void onCreate() {
super.onCreate();
Log.e("m_tag","===onCreate===");
}
// 销毁服务时触发
@Override
public void onDestroy() {
super.onDestroy();
Log.e("m_tag","===onDestroy===");
}
}

2 、绑定端

// 服务连接器
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 绑定成功
MusicService.MyBinder binder = (MusicService.MyBinder) service;
Log.e("m_tag"," 绑定成功 ");
}
@Override
public void onServiceDisconnected(ComponentName name) {
// 当绑定了服务,但是服务意外终止就触发该方法
}
};
绑定
Intent it5 = new Intent(MainActivity.this,MusicService.class);
// 绑定服务, Context.BIND_AUTO_CREATE 表示当绑定的服务还未创建则创建服务对象
bindService(it5,conn,Context.BIND_AUTO_CREATE);

解除绑定

unbindService(conn);

注意:服务在运行中如果涉及到 bindService 的那么在停止服务之前必须 unbindService 才可以停止, bindService 相当于给绑定者 (Context) 和服务之间建立了
Binder 这样的通讯通道, startService 相当于可以直接用 Intent 来通讯

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值