[学习笔记]Android中Service通信
来源:互联网 发布:ubuntu 16.04 u盘制作 编辑:程序博客网 时间:2024/06/05 06:30
以下内容纯粹为本人学习笔记【记录】之用,所听课程(Q群群友百度网盘提供)为极客学院一位老师所讲(老师大名我尚未知晓),如有侵权请告知。在此特别感谢这位老师录制的视频资料。
1、启动Service并传递数据
MainAvtivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener { private EditText etData; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); etData = (EditText) findViewById(R.id.etData); //创建监听器 findViewById(R.id.btnStartSvc).setOnClickListener(this); findViewById(R.id.btnStopSvc).setOnClickListener(this); } @Override public void onClick(View view) { switch (view.getId()) { case R.id.btnStartSvc: Intent i = new Intent(this, MyService.class); i.putExtra("data", etData.getText().toString());//将数据快递过来 startService(i); break; case R.id.btnStopSvc: stopService(new Intent(this, MyService.class)); break; } }}
MyService.java
public class MyService extends Service { private boolean running =false; private String data = "这是默认信息!!form Service"; public MyService() { } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. throw new UnsupportedOperationException("Not yet implemented"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { //Service接收数据 data = intent.getStringExtra("data"); return super.onStartCommand(intent, flags, startId); } @Override public void onCreate() { super.onCreate(); running = true; new Thread(){ @Override public void run() { super.run(); while (running) { System.out.println(data); try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); } @Override public void onDestroy() { super.onDestroy(); running =false; }}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.keen.connectservice.MainActivity"> <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="默认信息 from AndroidDev" android:id="@+id/etData"/> <Button android:text="启动服务" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/btnStartSvc" /> <Button android:text="停止服务" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/btnStopSvc" /></LinearLayout>
效果
2、绑定Service进行通信
布局文件添加两个按钮,分别用于绑定和解除服务
<Button android:text="绑定服务" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/btnBindSvc" /> <Button android:text="解除绑定服务" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/btnUnBindSvc" />
同时MainActivity添加对应的监听事件
findViewById(R.id.btnBindSvc).setOnClickListener(this); findViewById(R.id.btnUnBindSvc).setOnClickListener(this);
并添加对应的点击事件
case R.id.btnBindSvc: bindService(new Intent(this, MyService.class), this, Context.BIND_AUTO_CREATE); break; case R.id.btnUnBindSvc: unbindService(this); break;
以及重载两个办法,让MainActivity实现ServiceConnected
@Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { } @Override public void onServiceDisconnected(ComponentName componentName) { }
再添加一个同步数据的按钮,即输入文本框里的数据同步到Service
<Button android:text="同步数据" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/btnSyncData" />
当然同时也添加监听事件和点击事件:
findViewById(R.id.btnSyncData).setOnClickListener(this);
点击事件里如何实现同步数据操作?Service提供了一个办法,通过IBinder对象来实现Activity和Service两个基本组件之间的连接(如何连接的?MainActivity中的onServiceConnected()中的参数IBinder iBinder即可访问到MyService中onBind()的返回值,即Binder实例)。
在MyService.java创建一个公开类,且继承自系统(os)的Binder,并将onBind()修改,代码如下:
@Override public IBinder onBind(Intent intent) { return new Binder(); } public class Binder extends android.os.Binder { }
在类内部写方法
public class Binder extends android.os.Binder { public void setData(String data) { //通过这里的方法即可修改Service中data的值 MyService.this.data = data; } }
此时在Service外部,即Activity里即可操作。首先定义一个Binder对象
private MyService.Binder binder = null;
之后在onServiceConnected()
@Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { binder = (MyService.Binder) service;//强制转化类型 }
添加同步按钮的点击事件方法
case R.id.btnSyncData: if (binder!=null) { binder.setData(etData.getText().toString());//数据来自etData } break;
通过这种方式,直接办法调用把数据传给Service,即通过binder进行通信。相比通过startService()方式通信更加方便高效。
如何监听服务的内部状态?如Service发生了改变时,如何通知给外界代码。实例:Servicie内部信息呈现到外界。
修改MyService的循环代码
new Thread(){ @Override public void run() { super.run(); int i = 0; while (running) { i++; System.out.println(i+ ":" +data);//除了在控制输出外,如何呈现到Activity的TextView里 try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start();
除了在控制输出外,如何呈现到Activity的TextView里。
创建一个TextView
<TextView android:text="TextView" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/tvOut" />
MainActivity声明一个tvout
private TextView tvout;//定义/声明
tvOut = (TextView) findViewById(R.id.tvOut);
接下来的操作是:如何通知外界,即回调
MyService写一个Callback回调接口、callback变量、setCallback方法、getCallback方法
private Callback callback = null;//变量赋值为null public void setCallback(Callback callback) { this.callback = callback; } public Callback getCallback() { return callback; } public static interface Callback { void onDataChange(String data); }
修改循环语句如
while (running) { i++; String str = i+ ":" +data; System.out.println(str);//除了在控制输出外,如何呈现到Activity的TextView里 if (callback!=null) { callback.onDataChange(str);//传出str } try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } }
服务外界如何添加事件的绑定?在MyService中Binder类写一个办法:
public MyService getService() { return MyService.this; }
此时外界(Activity)就可以访问到(Service)。
修改MainActivity
@Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) {// binder = (MyService.Binder) service;//强制类型转换 binder.getService().setCallback(new MyService.Callback() { @Override public void onDataChange(String data) { } }); }
因为在Android中有 一个安全机制,UI线程是不允许其他辅线程来直接修改UI线程的资源。因此,定义Handle,并重写handleMessage()方法。
private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); } };
再次修改MainActivity中onDataChange()方法
public void onDataChange(String data) { Message msg = new Message();//创建 Bundle b = new Bundle(); b.putString("data", data); msg.setData(b);//附加数据 handler.sendMessage(msg);//传递数据 }
获取到msg之后,在handleMessage()获取到字符串,并填入tvOut.setText()中,这样就能呈现到tvOut文本框中了。
@Override public void handleMessage(Message msg) { super.handleMessage(msg); tvOut.setText(msg.getData().getString("data")); }
点击[绑定服务],效果:
源码完整部分
MainActivity
public class MainActivity extends AppCompatActivity implements View.OnClickListener, ServiceConnection { private EditText etData; private MyService.Binder binder =null; private TextView tvOut;//定义/声明 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); etData = (EditText) findViewById(R.id.etData); tvOut = (TextView) findViewById(R.id.tvOut); //创建监听器 findViewById(R.id.btnStartSvc).setOnClickListener(this); findViewById(R.id.btnSyncData).setOnClickListener(this); findViewById(R.id.btnBindSvc).setOnClickListener(this); findViewById(R.id.btnUnBindSvc).setOnClickListener(this); findViewById(R.id.btnStopSvc).setOnClickListener(this); } @Override public void onClick(View view) { switch (view.getId()) { case R.id.btnStartSvc: Intent i = new Intent(this, MyService.class); i.putExtra("data", etData.getText().toString());//将数据快递过来 startService(i); break; case R.id.btnSyncData: if (binder!=null) { binder.setData(etData.getText().toString());//数据来自etData } break; case R.id.btnBindSvc: bindService(new Intent(this, MyService.class), this, Context.BIND_AUTO_CREATE); break; case R.id.btnUnBindSvc: unbindService(this); break; case R.id.btnStopSvc: stopService(new Intent(this, MyService.class)); break; } } @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { binder = (MyService.Binder) service;//强制类型转换 binder.getService().setCallback(new MyService.Callback() { @Override public void onDataChange(String data) { Message msg = new Message();//创建 Bundle b = new Bundle(); b.putString("data", data); msg.setData(b);//附加数据 handler.sendMessage(msg);//传递数据 } }); } @Override public void onServiceDisconnected(ComponentName componentName) { } private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); tvOut.setText(msg.getData().getString("data")); } };}
MyService
public class MyService extends Service { private boolean running =false; private String data = "这是默认信息!!form Service"; public MyService() { } @Override public IBinder onBind(Intent intent) { return new Binder(); } public class Binder extends android.os.Binder { public void setData(String data) { //通过这里的方法即可修改Service中data的值 MyService.this.data = data; } public MyService getService() { return MyService.this; } } @Override public int onStartCommand(Intent intent, int flags, int startId) { //Service接收数据 data = intent.getStringExtra("data"); return super.onStartCommand(intent, flags, startId); } @Override public void onCreate() { super.onCreate(); running = true; new Thread(){ @Override public void run() { super.run(); int i = 0; while (running) { i++; String str = i+ ":" +data; System.out.println(str);//除了在控制输出外,如何呈现到Activity的TextView里 if (callback!=null) { callback.onDataChange(str);//传出str } try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); } @Override public void onDestroy() { super.onDestroy(); running =false; } private Callback callback = null;//变量赋值为null public void setCallback(Callback callback) { this.callback = callback; } public Callback getCallback() { return callback; } public static interface Callback { void onDataChange(String data); }}
activity_main
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.keen.connectservice.MainActivity"> <TextView android:text="TextView" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/tvOut" /> <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="默认信息 from AndroidDev" android:id="@+id/etData"/> <Button android:text="启动服务" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/btnStartSvc" /> <Button android:text="同步数据" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/btnSyncData" /> <Button android:text="绑定服务" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/btnBindSvc" /> <Button android:text="解除绑定服务" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/btnUnBindSvc" /> <Button android:text="停止服务" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/btnStopSvc" /></LinearLayout>
- [学习笔记]Android中Service通信
- Android学习笔记-service进程间通信(一)
- Android学习笔记-service进程间通信(二)
- Android Service学习笔记
- Android Service学习笔记
- Android Service学习笔记
- android service 学习笔记
- Android学习笔记 - Service
- Android学习笔记-Service
- android Service学习笔记
- Android Service学习笔记
- Service与Activity之间通信(学习笔记)
- Android笔记 Activity和Service的通信
- Android基础知识--8.Android中Service通信
- Android中Service学习
- [Android学习笔记] Service 学习
- Android学习之Service生命周期及其通信
- Android Service学习笔记--声明Service
- 弦截法求根
- API接口规范
- IOS 倒计时 按钮
- Jsp的九大内置对象和四个作用域
- Android安全开发之安全使用HTTPS
- [学习笔记]Android中Service通信
- 关于关于判断JS对象是否拥有某属性
- document.documentElement和document.body的区别
- esp8266与mosquitto的mqtt的ssl通讯实现(三)-mosquitto配置
- addEventListener中this指向
- 在几个学生的成绩中找出不及格的学生并输出他的成绩(用指针指向一个二维数组)
- 最短路径之Dijkstra算法
- 数字图像处理_matlab
- 5个范例告诉你什么是自适应网页设计