从Service的启动方式上,可以将Service分为Started Service和Bound Service。在使用Service时,要想系统能够找到此自定义Service,无论哪种类型,都需要在AndroidManifest.xml中声明:
<service android:name=".MyService">
一:StartService方式启动服务
Started Service相对比较简单,通过context.startService(Intent serviceIntent)启动Service,context.stopService(Intent serviceIntent)停止此Service。
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.servicetest"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name=".MyService"> </service> </application> </manifest>
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:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.example.servicetest.MainActivity"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="启动服务" android:id="@+id/btn_StartService" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="停止服务" android:id="@+id/btn_StopService" /> </LinearLayout>
MainActivity:
package com.example.servicetest; import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private Button startService; private Button stopService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); startService=(Button)findViewById(R.id.btn_StartService); stopService=(Button) findViewById(R.id.btn_StopService); startService.setOnClickListener(this); stopService.setOnClickListener(this); } @Override public void onClick(View view) { switch (view.getId()){ case R.id.btn_StartService: //启动服务 Intent intentStart=new Intent(MainActivity.this,MyService.class); startService(intentStart); break; case R.id.btn_StopService: //停止服务 Intent intentStop=new Intent(MainActivity.this,MyService.class); stopService(intentStop); break; } } }
MyService:
package com.example.servicetest; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.support.annotation.Nullable; import android.util.Log; import java.text.SimpleDateFormat; import java.util.Date; /** * Created by xch on 2016/9/5. */ public class MyService extends Service{ private boolean flag=true; @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); Log.i("tag","服务被创建!"); } @Override public void onDestroy() { super.onDestroy(); Log.i("tag","服务被销毁!"); new MyThread().setFlagFalse(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { new MyThread().start(); return super.onStartCommand(intent, flags, startId); } class MyThread extends Thread{ public void setFlagFalse(){ flag=false; } @Override public void run() { super.run(); while (flag){ //每隔一秒钟打印当前时间一次 //设置时间打印格式 SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//24小时制 Date date=new Date(); String time=sdf.format(date); Log.i("date",time); try { //沉睡1秒 Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } }
二. BoundService方式启动服务
bindService启动流程: context.bindService() ——> onCreate() ——> onBind() ——> Service running ——> onUnbind() ——> onDestroy() ——> Service stop
MainActivity:
package com.example.servicetest2; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private Button bindService,unBindService; private Intent intent; private MyServiceConn conn=new MyServiceConn(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bindService=(Button)findViewById(R.id.btn_BindService); unBindService=(Button)findViewById(R.id.btn_UnBindService); bindService.setOnClickListener(this); unBindService.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()){ case R.id.btn_BindService: intent=new Intent(MainActivity.this,MyService.class); bindService(intent,conn, Context.BIND_AUTO_CREATE); break; case R.id.btn_UnBindService: intent=new Intent(MainActivity.this,MyService.class); unbindService(conn); break; } } private class MyServiceConn implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder service) { //在服务绑定成功的时候执行 } @Override public void onServiceDisconnected(ComponentName name) { //当服务所在的进程被杀死,或崩溃的时候执行 } } }
MyService:
package com.example.servicetest2; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.support.annotation.Nullable; import android.util.Log; import java.text.SimpleDateFormat; import java.util.Date; /** * Created by xch on 2016/9/7. */ public class MyService extends Service { private boolean flag=true; private MyThread thread=new MyThread(); @Nullable @Override public IBinder onBind(Intent intent) { thread.start(); return null; } @Override public void onCreate() { Log.i("service","服务被创建!"); super.onCreate(); } @Override public void onDestroy() { super.onDestroy(); Log.i("service","服务被销毁!"); thread.setFlagFalse(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { return super.onStartCommand(intent, flags, startId); } class MyThread extends Thread{ public void setFlagFalse(){ flag=false; } @Override public void run() { super.run(); while (flag){ Date date=new Date(); SimpleDateFormat sdf=new SimpleDateFormat("yyyy-mm-dd HH:mm:ss"); Log.i("date",sdf.format(date)); try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } }
三.Service与Activity之间通讯
BoundService可以实现,但是startService没有这个特点。这里需要注意的是,利用bindService启动的Service无法获取这个Service对象,所以这里需要在Service中将对象返回,既然有返回就需要接收。so,看代码:
MyService:
package com.example.servicetest2; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.support.annotation.Nullable; import android.util.Log; import java.text.SimpleDateFormat; import java.util.Date; /** * Created by xch on 2016/9/7. */ public class MyService extends Service { private boolean flag=true; private MyThread thread; private String format="yyyy-mm-dd HH:mm:ss"; //更改系统时间的输出格式 public void setFormat(String format){ this.format=format; } public void changeFormat(String format){ if(thread!=null){ //调用方法,更改时间输出格式 setFormat(format); } } @Nullable @Override public IBinder onBind(Intent intent) { thread.start(); //将代理类返回回去 return new ServiceBinder(); } @Override public void onCreate() { Log.i("service","服务被创建!"); thread=new MyThread(); super.onCreate(); } @Override public void onDestroy() { super.onDestroy(); Log.i("service","服务被销毁!"); thread.setFlagFalse(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { return super.onStartCommand(intent, flags, startId); } class MyThread extends Thread{ public void setFlagFalse(){ flag=false; } @Override public void run() { super.run(); while (flag){ Date date=new Date(); SimpleDateFormat sdf=new SimpleDateFormat(format); Log.i("date",sdf.format(date)); try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } /** * 当前服务的代理类,即可使用changeFormat()方法 * 需要通过IBinder将这个代理类返回回去,即onBinder()方法 */ public class ServiceBinder extends Binder{ public void changeServiceBinder(String format){ if(thread!=null){ changeFormat(format); } } } }
这里需要在service中定义一个代理类,并利用onBinder()方法返回去。
MainActivity:
package com.example.servicetest2; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private Button bindService,unBindService,changeFormat; private Intent intent; private MyServiceConn conn=new MyServiceConn(); //接收到的service对象 private MyService.ServiceBinder serviceBinder; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bindService=(Button)findViewById(R.id.btn_BindService); unBindService=(Button)findViewById(R.id.btn_UnBindService); changeFormat=(Button)findViewById(R.id.btn_changeFormat); bindService.setOnClickListener(this); unBindService.setOnClickListener(this); changeFormat.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()){ case R.id.btn_BindService: intent=new Intent(MainActivity.this,MyService.class); bindService(intent,conn, Context.BIND_AUTO_CREATE); break; case R.id.btn_UnBindService: intent=new Intent(MainActivity.this,MyService.class); unbindService(conn); break; case R.id.btn_changeFormat: serviceBinder.changeServiceBinder("HH:mm:ss"); break; } } private class MyServiceConn implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder service) { //在服务绑定成功的时候执行,同时接收到了IBinder对象(类型为代理类对象,因为onBinder方法返回了代理类对象) serviceBinder= (MyService.ServiceBinder) service; } @Override public void onServiceDisconnected(ComponentName name) { //当服务所在的进程被杀死,或崩溃的时候执行 } } }
这里实现了ServiceConnection接口的自定义类需要实现如上两个方法,其中onServiceConnected(ComponentName name, IBinder service)方法能获取onBinder()返回的service对象。
结果: