activity
startActivity开启界面,finish关闭界面
l使用startActivityForResult(Intent intent, int requestCode) 方法打开Activity
l重写onActivityResult(int requestCode, int resultCode, Intent data) 方法
l新Activity中调用setResult(int resultCode, Intent data) 设置返回数据之后,关闭Activity,第一个Activity就会调用onActivityResult方法
requestCode,请求码:用于区别是哪个操作启动的意图,哪个Activity返回的数据
resultCode,结果码,用于区别是哪个Activity返回的数据
显示意图:
//创建一个Intent对象,并传递当前对象(Context对象)和要跳转的Activity类字节码
Intent intent = new Intent(this, SecondActivity.class);
//启动第二个Activity
startActivity(intent);
显示意图的其他形式
l 类名形式,灵活,可扩展性强
intent.setClassName(this, "cn.itcast.activity.NewActivity");
这个可以是不同应用,只要知道其activity的全路径名即可
2 包名类名形式,可启动其他程序中的Activity
intent.setClassName("cn.itcast.downloader", "cn.itcast.downloader.MainActivity");
注意这里第一个参数是应用程序的包名
3 最后一种:使用组件名,这种方式不常用
具体做法:
先实例化componentName("包名","带包的类名")
然后设置intent.setComponent()
componentName 直译的话就是组件的名字的意思,如果我们写的一个类当作成一个组件,那么这个componentName就是用来封装我们写的这些类的位置.
隐式意图:
//创建一个Intent对象
Intent intent = new Intent();
//设置Action
intent.setAction("android.intent.action.VIEW");
//设置category
intent.addCategory("android.intent.category.BROWSABLE");
//设置参数
intent.setData(Uri.parse("http://www.itheima.com"));
//启动Activity
startActivity(intent);
Intent除了可以激活组件(启动Activity等),还可以通过封装的Bundle对象来携带数据。
广播接收者
接收:对于系统发送的广播,定义好广播接收者之后,接收到直接调用oncreate方法。
在src目录下新建一个SDCardUnmountedReceiver类继承BroadcastReceiver类,覆写onReceive方法,
当接收到匹配广播之后就会执行onReceive方法
必须定义action
注册一个广播接收者有两种方式。
静态注册:在AndroidManifest.xml中注册广播
清单文件中声明<receiver>,需要在其中配置<intent-filter>指定接收广播的动作(action),在AndroidManifest.xml文件中添加如下配置:
动态注册:在Java代码中注册
registerReceiver(new SDCardUnmountedReceiver(), intentFilter);
3.2版本以上出于安全问题:从未启动过的广播接收程序,默认是接收不到广播的,必须有一个界面,然后通过界面启动一次这个程序。
在4.0之后 谷歌为了安全考虑 要求广播接收者生效 在第一次安装应用的时候要求必须有界面
(2)在设置页面有一个强行停止的选项 如果用户点击想强行停止 广播接收者不会在生效
广播接收者的生命周期是非常短暂的,在接收到广播的时候创建,onReceive()方法结束之后销毁
abortBroadcast();终止广播
abortBroadcast();
发送自定义广播(系统发送了很多广播,我们只需要定义广播接收者接受,也可以自定义发送广播)
无序广播不可以被拦截,如果被拦截的话会报错:
BroadcastReceiver trying to return result during a non-ordered broadcast
所有接收无序广播的广播接收者在此广播被发送时均能接收到此广播,并且是同时接收到
无序广播使用sendBroadcast方法来发送
//定义一个意图
Intent intent = new Intent();
//设置Action
intent.setAction("com.itheima.broadcast");
//绑定数据
intent.putExtra("data", "我是无序广播数据");
//发送无序广播
sendBroadcast(intent);
发送广播时,通过intent.setFlags(intent.flag_include_stopped_pakeages),包含从未启动过的程序,这样设置,可以让从未启动的接收者也收到广播
前面的接收者可以将数据通过setResultExtras(Bundle)方法存放进结果对象,
然后传给下一个接收者,下一个接收者通过代码:Bundle bundle = getResultExtras(true))可以获取上一个接收者存入在结果对象中的数据。
* 第一个参数 Intent类型:意图
* 第二个参数 String类型 receiverPermission,接收器需要的权限
* 第三个参数BroadcastReceiver类型,自己定义的接收器作为最终接收器,不需要注册
* 第四个参数Handler类型,用于执行接收器的回调,如果为null则在主线程中执行
* 第五个参数int类型,结果代码的初始码
* 第六个参数初始化参数
* 第七个参数Bundle类型,额外的数据
*/
sendOrderedBroadcast(intent, null, null,
null, RESULT_OK, "1万元钱", null);
开启Service,在其他组件中调用startService方法
startService(intent);(在activity中可以直接调用)
会执行onstartCommand(生命周期方法)(onStart()以过期的方法),如果发现service还没有,就会先创建执行oncreate
onCreate只会执行一次,服务一旦被创建出来,就不会再执行onCreate方法,以后再去开启服务只会执行onStartCommand。
l 停止Service,调用stopService方法
setForegound(true)(直接在service里调用),为了避免服务被杀死,我们可以指定这个服务为前台进程。
服务在执行生命周期方法时,也是一个前台进程。广播接收者也一样,在执行生命周期方法onReceive时,也是一个前台进程
会执行onDestory()(生命周期方法)
//得到手机电话相关的管理服务类
// getSystemService获取系统服务的方法,传入WIFI_service,获取的是wifi网络服务
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
被开启的service通过其他组件调用 startService()被创建。这种service可以无限地运行下去,必须调用stopSelf()方法或者其他组件调用stopService()方法来停止它。当service被停止时,系统会销毁它。
尽管一个被开启的service是通过调用 stopSelf() 或 stopService()来停止的,没有一个对应的回调函数与之对应,即没有onStop()回调方法。所以,当调用了停止的方法,除非这个service和客户组件绑定,否则系统将会直接销毁它,onDestory()方法会被调用,并且是这个时候唯一会被调用的回调方法。
start方式开启服务的生命周期
(1)第一次点击开启服务 会执行生命周期的 onCreate方法 和 onStart方法
(2)第二次在开始点击按钮 生命周期只会执行onstart方法
(3)服务一旦被开启 服务就会在后台长期运行 直到用户来到设置页面停止服务
(4)可以调用stopService方法把服务个停止掉
被绑定的service是当其他组件(一个客户)调用bindService()来创建的。客户可以通过一个IBinder接口和service进行通信。客户可以通过 unbindService()方法来关闭这种连接。一个service可以同时和多个客户绑定,当多个客户都解除绑定之后,系统会销毁service。
(1)第一次开启服务的时候 会调用生命周期的 onCreate方法和onBin方法
(2)第二次在调用无反应
(3)不求同时生但求同时死
(4)在设置页面里面看不见这个服务 他类似是一个隐形的服务
(5)bindservice只能解绑一次 不能多次解绑 如果多次解绑会报异常
(6)当onbind方法返回为null的时候 onServiceConnected方法不会调用
为什么要引入bindService
目的 为了可以调用服务里面方法
# 6 绑定服务调用服务里(方法)的过程
总结(1)在服务的内部定义一个中间人对象(IBinder)
(2)在定义中间人内部定义一个方法可以间接调用到服务里面的方法
(3)在onBind方法里面把我们定义的中间人对象给返回
(4)在Activity中调用服务里面的方法 首先通过bindservice的方式获取到我们定义的中间人对象
(5)通过中间人就可以调用到服务里面的方法
# 7 绑定服务抽取接口
接口:可以隐藏代码内部的细节 让程序员暴露自己想暴露的方法
总结(1)定义接口 把想暴露的方法都定义在接口里面
(2)在我们定义的中间人对象 实现我们定义的接口
(3)在获取中间人对象的时候 不一样
# 10 远程服务aidl的写法
远程服务: 运行在其他应用里面的服务
本地服务: 运行在自己应用里面的服务
IPC: 进程间通信
aidl:Android Interface Definition Language Android接口定义语言
专门用来解决进程间通信的问题
要求2个应用aidl文件所在包名相同 就说明2个aidl文件是同一个
aidl的写法 不用的地方
(1)把我们定义的接口Iservice.java变成 aidl文件
(2)把pulic 给去掉
(3)我们定义的中间人对象 直接继承Stub
(4)获取中间人对象的时候 是通过Stub Stub.asInterface(service);获取中间人对象