本帖最后由 allen927 于 2015-12-8 08:55 编辑
同样的课程、老师、就业,更好的学习环境,更低的学习成本! android基础Day08(绑定服务)
《 如果感觉今天的知识点都会了,可以直接做作业,来进行检测》
•(了解)为什么需要绑定服务 绑定服务就是为了和服务进行通讯 可以调用服务里面的方法
•(掌握)绑定服务调用服务方法的流程
•(掌握)绑定服务抽取接口
接口的抽取:有什么样的行为,就抽取什么样的方法。
•(掌握)绑定本地服务 案例
总结
代码
1 订阅接口 /** * 接口 *@author apple * */ public interface IStudentListener {
//根据学号查询学生的姓名 publicString queryNameById(int id);
}
2 服务 public class MyService extends Service {
privateString[] names = new String[]{"张学友","刘德华","黎明","郭富城"};
//增强版IBinder(真实的对象) private MyBinder ibinder = new MyBinder(); @Override public IBinder onBind(Intent intent) { return ibinder; } //创建一个增强版的IBinder类 private class MyBinder extends Binder implementsIStudentListener{
@Override publicString queryNameById(int id) { //id只能是1 到4 if(id<= 0 || id > names.length){ return"苍姐姐"; }else{ returnnames[id-1]; } }
} }
3 客户端 public class MainActivity extends Activity{
privateEditText et_id; privateButton bt_query; privateTextView tv_name; privateMyServiceConnection conn; privateIStudentListener iStudentListener;
@Override protectedvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
et_id= (EditText) findViewById(R.id.et_id); bt_query= (Button) findViewById(R.id.bt_query); tv_name= (TextView) findViewById(R.id.tv_name);
//绑定服务 conn = new MyServiceConnection(); bindService(new Intent(this,MyService.class), conn,BIND_AUTO_CREATE); }
privateclass MyServiceConnection implements ServiceConnection{
//绑定成功 @Override public void onServiceConnected(ComponentName name, IBinderservice) { bt_query.setEnabled(true); //把IBinder对象转化成接口对象 iStudentListener = (IStudentListener) service; }
@Override publicvoid onServiceDisconnected(ComponentName name) {
}
}
publicvoid query(View v){ //绑定服务(为什么服务的绑定需要时间) StringidStr = et_id.getText().toString().trim(); if(TextUtils.isEmpty(idStr)){ Toast.makeText(this,"姐姐 学号不能为空", 0).show(); }else{ intid = Integer.parseInt(idStr); //调用接口对象的方法(就是调用真实对象的方法) String name = iStudentListener.queryNameById(id); tv_name.setText(name); } }
@Override protectedvoid onDestroy() { super.onDestroy(); unbindService(conn); } }
•(掌握)远程服务aidl aidl:android interface definelanguage 安卓接口定义语言。 他是一种新的语言。 这样的语言他可以被编译器自动编译为java语言。 作用:aidl 为了解决进程间通讯,定义了两个应用程序之间的通讯规则。 他和接口非常的相似,我们可以先定义接口,再把接口修改为aidl .java --> .aidl aidl语言有自己的语法: 1 它可以识别java里面的基本数据类型 2 它无法识别访问修饰符 public private 3 它无法识别domain 如果要让aidl识别domain 1 class Student implementsParcelable 2 写一个Student.aidl文件 package cn.itcast.domain; parcelable Student;
aidl 自动生成.java文件后,我们使用什么? Stub asInterface(IBinder) IStudent 底层其实走的是代理机制。
aidl 就是一个合同 一式两份 写完aidl之后,把aidl所有的内容带包一起复制到客户端
•(掌握)绑定远程服务 案例 总结
实现 服务器 定义接口 .java 修改为.aidl 删除public修饰符 /** * 远程的服务(在其他应用程序里面的服务) *@author apple * */ public class MyService extends Service {
privateString[] names = new String[]{"张学友","刘德华","黎明","郭富城"};
privateMyBinder ibinder = new MyBinder();
@Override publicIBinder onBind(Intent intent) { returnibinder; }
//增强版的IBinder privateclass MyBinder extends Stub{
@Override publicString queryNameById(int id) throws RemoteException { //id只能是1 到4 if(id<= 0 || id > names.length){ return"苍姐姐"; }else{ returnnames[id-1]; } }
}
}
客户端 从服务器端把aidl文件带包一起复制过来 public class MainActivity extends Activity{
privateEditText et_id; privateTextView tv_name; privateMyServiceConnection conn; privateIStudentListener iStudentListener;
@Override protectedvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
et_id= (EditText) findViewById(R.id.et_id); tv_name= (TextView) findViewById(R.id.tv_name); //绑定服务 Intentservice = new Intent(); service.setAction("cn.itcast.action.studentquerysystem.server"); conn= new MyServiceConnection(); bindService(service,conn, BIND_AUTO_CREATE); }
@Override protectedvoid onDestroy() { super.onDestroy(); unbindService(conn); }
privateclass MyServiceConnection implements ServiceConnection{
//绑定的服务是一个 远程的服务 aidl语言 传递过来的对象 :代理对象 代理对象不能直接使用 //需要使用Stub里面的一个方法 asInterface()把代理对象转化成真实对象 再使用 @Override public void onServiceConnected(ComponentName name,IBinder service) { //把代理对象转化成真实对象 iStudentListener = Stub.asInterface(service); }
@Override publicvoid onServiceDisconnected(ComponentName name) {
}
}
publicvoid query(View v){ StringidStr = et_id.getText().toString().trim(); if(TextUtils.isEmpty(idStr)){ Toast.makeText(this,"姐姐 学号不能为空", 0).show(); }else{ intid = Integer.parseInt(idStr); //调用接口对象的方法(就是调用真实对象的方法) try{ Stringname = iStudentListener.queryNameById(id); tv_name.setText(name); }catch (RemoteException e) { e.printStackTrace(); Toast.makeText(this,"服务器端出现了错误",0).show(); } } }
}
•(掌握)绑定远程服务(服务返回对象) 实现 服务器:
public classStudent implementsParcelable { public int id; public String name; public int age; public Student() { super(); } public Student(int id, String name, int age) { super(); this.id = id; this.name = name; this.age = age; } @Override public int describeContents() { return 0; } //把属性写入到Parcel对象 @Override public void writeToParcel(Parceldest, intflags) { dest.writeInt(id); dest.writeString(name); dest.writeInt(age); } public static finalParcelable.Creator<Student> CREATOR = newParcelable.Creator<Student>() { public StudentcreateFromParcel(Parcel in) { return new Student(in); } public Student[] newArray(int size) { return new Student[size]; } }; private Student(Parcel in) { id = in.readInt(); name = in.readString(); age = in.readInt(); } } Student.aidl IStudent.aidl
•(掌握)服务综合案例-音乐播放器
使用服务来播放音乐。 播放:放歌 暂停:暂停播放 点击暂停按钮:变为继续 停止:停止播放 准备: 1 MainActivity 2MyService
单箭头:方法的调用 双箭头:监听回调 椭圆:状态 public class MainActivity extends Activity{
privateEditText et_path; privateServiceConnection conn; privateIMusic iMusic;
@Override protectedvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
et_path= (EditText) findViewById(R.id.et_path);
//绑定服务 Intentservice = new Intent(this,MyService.class); conn= new MyServiceConnection(); bindService(service,conn, BIND_AUTO_CREATE); }
@Override protectedvoid onDestroy() { super.onDestroy(); unbindService(conn); }
privateclass MyServiceConnection implements ServiceConnection{
@Override publicvoid onServiceConnected(ComponentName name, IBinder service) { iMusic= (IMusic) service; }
@Override publicvoid onServiceDisconnected(ComponentName name) {
}
}
//播放 publicvoid play(View v){ //获取要播放的歌曲路径 Stringpath = et_path.getText().toString().trim(); if(TextUtils.isEmpty(path)){ Toast.makeText(this,"路径为空",0).show(); }else{ iMusic.play(path); } }
//暂停 继续 publicvoid pause(View v){ Buttonbt = (Button) v; Stringtext = bt.getText().toString(); if("暂停".equals(text)){ iMusic.pause(); bt.setText("继续"); }elseif("继续".equals(text)){ iMusic.moveon(); bt.setText("暂停"); } }
//停止 publicvoid stop(View v){ iMusic.stop(); }
}
接口的抽取 public interface IMusic { //播放 path 歌曲的路径 public void play(String path); //暂停 public void pause(); //继续 public void moveon(); //停止 public void stop(); }
public class MyService extends Service {
privateMyBinder ibinder = new MyBinder(); @Override publicIBinder onBind(Intent intent) { returnibinder; }
privateclass MyBinder extends Binder implements IMusic{
private MediaPlayer mp;
@Override publicvoid play(String path) { try{ mp= new MediaPlayer(); mp.reset();//重置 mp.setDataSource(path);//设置播放的资源 mp.prepare();//准备 mp.start();//播放 }catch (Exception e) { //TODO Auto-generated catch block e.printStackTrace(); }
}
@Override publicvoid pause() { mp.pause();//暂停播放 }
@Override publicvoid moveon() { mp.start();//继续 }
@Override publicvoid stop() { mp.stop();//停止播放 }
}
}
•(掌握)服务后台音乐播放器界面显示-notification
//用户按下任意的键 该方法都会调用 @Override publicboolean onKeyDown(int keyCode, KeyEvent event) { if(keyCode== KeyEvent.KEYCODE_BACK){ //按下的就是后退键 //弹出提示框 AlertDialog.Builderbuilder = new AlertDialog.Builder(this); builder.setTitle("提示信息"); builder.setMessage("是否退出音乐播放器"); builder.setPositiveButton("退出", new OnClickListener() {
@Override publicvoid onClick(DialogInterface dialog, int which) { //关闭当前的Activity finish(); } }); builder.setNegativeButton("取消", null); builder.setNeutralButton("隐藏", new OnClickListener() {
@Override publicvoid onClick(DialogInterface dialog, int which) { //把当前的MainActivity放置在后台 moveTaskToBack(true); } }); AlertDialogdialog = builder.create(); dialog.show(); } returnsuper.onKeyDown(keyCode, event); }
•(掌握)服务注册广播接受者 Activity里面注册广播接收者 服务里面注册广播接收者
1 在服务里面写一个class MyReceiver extendsBroadcastReceiver { onReceive(){ } }
2 注册 onCreate() { registerReceiver(receiver,filter); }
3 取消注册 onDestory(){ unRegisterReceiver(receiver); }
public class MyService extends Service {
privateMyReceiver receiver;
@Override publicvoid onCreate() { super.onCreate();
receiver= new MyReceiver(); IntentFilterfilter = new IntentFilter(); filter.addAction(""); registerReceiver(receiver,filter); }
@Override publicvoid onDestroy() { super.onDestroy(); unregisterReceiver(receiver); }
@Override publicIBinder onBind(Intent intent) { returnnull; }
privateclass MyReceiver extends BroadcastReceiver{
@Override publicvoid onReceive(Context context, Intent intent) { //执行什么操作 }
}
}
•(掌握)知识点补充 1 服务里面不能直接执行耗时的操作 Service 和 Activity有什么区别:一个有界面 一个没有界面 2 如果要执行耗时的操作,开始子线程(android也提供了一个类IntentService对Service、Thread、Handler线程进行了封装:一般会出现在笔试题中) 3 服务如何和Activity进行通讯:在服务里面发出广播。 activity要和服务进行通信: 1 绑定服务 调用服务里面的方法 2 在Activity里面发送广告给服务里面的广播接收者 服务和Activity进行通讯 1 发送广播
4 如果你希望服务处理完成事情后自动停止,可以在服务里面调用stopSelf();(这样的情况只针对于startService()启动的服务)
面试题 1 请说说intent和intentfilter有什么区别? intent:意图 是用来串联3大组件:Activity Service BroadcastReceiver 组成: action 动作 data 数据 category 类别 type 数据的类型 extra 携带的额外参数 component 组件 flag 标记 new_task 在activity的外部启动activity
IntentFilter java registerReceiver(receiver,filter); 解析清单文件的时候:intent-filter节点
例子: MainActivity要去激活OtherAcivity startActivity(new Intent(this,OtherActivity.class));
当你发起激活操作的时候,其实是向操作系统发出了一个指令,操作系统去帮你查找OtherActivity ,如果有就使用ActivityManager把OtherActivity启动, 如果没有找到 报一个notfoundActivityException . 1 该应用里面根本没有OtherActivity 2 OtherActivity没有在清单中配置
例子: IntentFilter对象是何时被解析? 应用程序安装的时候,android系统会使用Pull解析解析清单文件 并且把数据进行了面向对象的封装。 手机里面是不是会有很多的应用,很多的应用也就是很多的包。很多的应用是很多的用户。很多的应用是很多的进程。
android还设计了一个类来管理所有的应用。 PackageManager
2 aidl: 进程间通讯 java里面是不支持的。 api: IBinder 实现类 Binder java linux kernel (内核)驱动
他是android 工程师添加的。进程间通讯。ipc c 代码
作业
用服务来完成的下载器。 Activity和service在两个应用里面。
设计: 1 界面 注意:此图是Activity和Service在同一应用里面的处理方式
下载资源
|