Android笔记(十七) Android中的Service 定义和用途 Service的分类 定义Service的步骤 Service的启动方式 Service的生命周期 Service中的数据传递
Service是Android的四大组件之一,一直在后台运行,没有用户界面。Service组件通常用于为其他组件提供后台服务或者监控其他组件的运行状态,例如播放音乐、记录地理位置,监听用户操作等等。它的优先级要高于Activity。它运行在主线程中,所以不能一用它来做一些耗时的请求或者操作。
Service的分类
1. 本地服务(Local Service):主要用于程序内部
2. 远程服务(Remote Service):用于Android系统内部的应用程序之间
定义Service的步骤
开发Service和定义一个Activity一样,只需两个步骤
1. 定义一个继承Service的子类
2. 在AndroidManiFest.xml中注册该Service
Service的启动方式
startService方式启动
MainActivity.java
package cn.lixyz.servicedemo; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; public class MainActivity extends Activity { Intent intent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.btnStartService).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { intent = new Intent(MainActivity.this, MyStartService.class); startService(intent); } }); findViewById(R.id.btnStopService).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { stopService(intent); } }); } }
activity_layout.xml
<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="cn.lixyz.servicedemo.MainActivity"> <Button android:id="@+id/btnStartService" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="启动服务" /> <Button android:id="@+id/btnStopService" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="关闭服务" /> </LinearLayout>
MyStartService.java
package cn.lixyz.servicedemo; import android.app.Service; import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; import android.support.annotation.Nullable; import android.util.Log; public class MyStartService extends Service { int i = 1; @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { Log.d("TEST",i++ + ".onCreate方法执行。。。"); super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d("TEST",i++ + ".onStartCommand。。。"); return super.onStartCommand(intent, flags, startId); } @Override public boolean onUnbind(Intent intent) { Log.d("TEST",i++ + ".onUnbind。。。"); return super.onUnbind(intent); } @Override public void onDestroy() { Log.d("TEST",i++ + ".onDestroy。。。"); super.onDestroy(); } }
AndroidManiFest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cn.lixyz.servicedemo" > <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name=".MyStartService" android:enabled="true" android:exported="true" > </service> <service android:name=".MyBindService" android:enabled="true" android:exported="true" > </service> </application> </manifest>
连续点击三次启动服务按钮,再连续点击三次关闭服务按钮,Log如下
bindService方式启动
MainActivity.java
package cn.lixyz.servicedemo; import android.app.Activity; import android.app.Service; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.util.Log; import android.view.View; public class MainActivity extends Activity implements ServiceConnection { Intent intent ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.btnStartService).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { intent = new Intent(MainActivity.this, MyBindService.class); startService(intent); } }); findViewById(R.id.btnStopService).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { stopService(intent); } }); findViewById(R.id.btnBindService).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { intent = new Intent(MainActivity.this, MyBindService.class); bindService(intent, MainActivity.this, Service.BIND_AUTO_CREATE); } }); findViewById(R.id.btnUnbindService).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { unbindService(MainActivity.this); } }); } @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.d("TEST","onServiceConnected方法执行了。。。。"); } @Override public void onServiceDisconnected(ComponentName name) { Log.d("TEST","onServiceDisconnected。。。。"); } }
activity_layout.xml
<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="cn.lixyz.servicedemo.MainActivity"> <Button android:id="@+id/btnStartService" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="启动服务" /> <Button android:id="@+id/btnStopService" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="关闭服务" /> <Button android:id="@+id/btnBindService" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="绑定服务" /> <Button android:id="@+id/btnUnbindService" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="取消绑定服务" /> </LinearLayout>
MyBindService.java
package cn.lixyz.servicedemo; import android.app.Service; import android.content.Intent; import android.content.ServiceConnection; import android.os.Binder; import android.os.IBinder; import android.util.Log; public class MyBindService extends Service { int i = 1; public MyBindService() { } @Override public IBinder onBind(Intent intent) { return new Binder(); } @Override public void onCreate() { Log.d("TEST", i++ + ".onCreate方法执行。。。"); super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d("TEST", i++ + ".onStartCommand。。。"); return super.onStartCommand(intent, flags, startId); } @Override public boolean onUnbind(Intent intent) { Log.d("TEST", i++ + ".onUnbind。。。"); return super.onUnbind(intent); } @Override public void onDestroy() { Log.d("TEST", i++ + ".onDestroy。。。"); super.onDestroy(); } }
AndroidManiFest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cn.lixyz.servicedemo" > <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name=".MyStartService" android:enabled="true" android:exported="true" > </service> <service android:name=".MyBindService" android:enabled="true" android:exported="true" > </service> </application> </manifest>
运行结果:
Service的生命周期
从上面的运行结果可以看出Service的生命周期
1. 被启动的服务的声明周期:如果一个Service被某个Activity调用Context.startService()方法启动,那么不管是否有Activity使用bindService()绑定或者unbindService接触绑定到该Service,该Service都会在后台运行。如果一个Service被startService()方法多次启动,那么onCreate方法只调用一次,onstart()方法将会被调用多次,并且系统只会创建Service的一个实例(因此只需要调用一次stopService()),该Service将会一直在后台运行,而不管对应程序的Activity是否在运行,知道被调用stopService(),或者自身的stopSelf()。
2. 被绑定的服务的生命周期:如果一个Service被某个Activity调用Content.bindService()方法绑定,不管调用bindService()调用几次,onCreate()方法都只会调用一次,同时onStart()方法始终不会被调用,当建立连接之后,Service将会一直运行,除非调用Context.unbindService()断开链接或者之前调用bindService的Context不存在了(如Activity被finish掉了),系统将会自动停止Service,对应onDestroy()将被调用。
3. 被启动又被绑定的服务的生命周期:如果一个Service又被启动又被绑定,则该Service将会一直在后台运行,并且不管如何调用,onCreate()始终只会调用一次,对应startService() 调用多少次,Service的onStart()便会调用多少次,调用unbindService将不会停止Service,必须调用stopService或者Service的stopSelf来停止服务。
4. 当服务停止时清楚服务:当一个Service被终止(①调用stopService ②调用stopSelf ③不再有绑定的连接(没有被启动时)),onDestroy()方法将会被调用,在这里你应当做一些清除工作,如停止在Service中创建并运行线程。
Service中的数据传递
startService并传递数据
MainActivity.java
package cn.lixyz.servicedemo; import android.app.Activity; import android.app.Service; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.util.Log; import android.view.View; import android.widget.EditText; public class MainActivity extends Activity implements ServiceConnection { Intent intent ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.btnStartService).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { intent = new Intent(MainActivity.this, MyStartService.class); String str = ((EditText)findViewById(R.id.et_input)).getText().toString(); intent.putExtra("data",str); startService(intent); } }); findViewById(R.id.btnStopService).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { stopService(intent); } }); findViewById(R.id.btnBindService).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { intent = new Intent(MainActivity.this, MyBindService.class); bindService(intent, MainActivity.this, Service.BIND_AUTO_CREATE); } }); findViewById(R.id.btnUnbindService).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { unbindService(MainActivity.this); } }); } @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.d("TEST","onServiceConnected方法执行了。。。。"); } @Override public void onServiceDisconnected(ComponentName name) { Log.d("TEST","onServiceDisconnected。。。。"); } }
activity_layout.xml
<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="cn.lixyz.servicedemo.MainActivity"> <EditText android:id="@+id/et_input" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入要传入的内容"/> <Button android:id="@+id/btnStartService" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="启动服务" /> <Button android:id="@+id/btnStopService" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="关闭服务" /> <Button android:id="@+id/btnBindService" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="绑定服务" /> <Button android:id="@+id/btnUnbindService" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="取消绑定服务" /> </LinearLayout>
MyStartService.java
package cn.lixyz.servicedemo; import android.app.Service; import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; import android.os.IInterface; import android.os.Parcel; import android.os.RemoteException; import android.support.annotation.Nullable; import android.util.Log; import java.io.FileDescriptor; public class MyStartService extends Service { String str; @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); new Thread() { @Override public void run() { super.run(); str = "预定内容"; for (int i = 0; i <= 50; i++) { Log.d("TEST", str); try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { str = intent.getStringExtra("data"); return super.onStartCommand(intent, flags, startId); } @Override public boolean onUnbind(Intent intent) { return super.onUnbind(intent); } @Override public void onDestroy() { super.onDestroy(); } }
AndroidManiFest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cn.lixyz.servicedemo" > <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name=".MyStartService" android:enabled="true" android:exported="true" > </service> <service android:name=".MyBindService" android:enabled="true" android:exported="true" > </service> </application> </manifest>
运行结果:
bindService并传递数据
MainActivity.java
package cn.lixyz.servicedemo; import android.app.Activity; import android.app.Service; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.util.Log; import android.view.View; import android.widget.EditText; public class MainActivity extends Activity implements ServiceConnection { Intent intent ; MyBindService.Binder binder; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.btnStartService).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { intent = new Intent(MainActivity.this, MyStartService.class); startService(intent); } }); findViewById(R.id.btnStopService).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { stopService(intent); } }); findViewById(R.id.btnBindService).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { intent = new Intent(MainActivity.this, MyBindService.class); bindService(intent, MainActivity.this, Service.BIND_AUTO_CREATE); } }); findViewById(R.id.btnUnbindService).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { unbindService(MainActivity.this); } }); findViewById(R.id.btnSyncService).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String str = ((EditText) findViewById(R.id.et_input)).getText().toString(); binder.setString(str); } }); } @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.d("TEST","onServiceConnected方法执行了。。。。"); binder = (MyBindService.Binder) service; } @Override public void onServiceDisconnected(ComponentName name) { Log.d("TEST","onServiceDisconnected。。。。"); } }
activity_layout.xml
<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="cn.lixyz.servicedemo.MainActivity"> <EditText android:id="@+id/et_input" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入要传入的内容"/> <Button android:id="@+id/btnStartService" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="启动服务" /> <Button android:id="@+id/btnStopService" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="关闭服务" /> <Button android:id="@+id/btnBindService" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="绑定服务" /> <Button android:id="@+id/btnUnbindService" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="取消绑定服务" /> <Button android:id="@+id/btnSyncService" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="同步服务"/> </LinearLayout>
MyBindService.java
package cn.lixyz.servicedemo; import android.app.Service; import android.content.Intent; import android.content.ServiceConnection; import android.os.Binder; import android.os.IBinder; import android.util.Log; public class MyBindService extends Service { String str = "默认信息"; public MyBindService() { } @Override public IBinder onBind(Intent intent) { return new Binder(); } public class Binder extends android.os.Binder{ public void setString(String str){ MyBindService.this.str = str; } } @Override public void onCreate() { Log.d("TEST", ".onCreate方法执行。。。"); new Thread(){ @Override public void run() { super.run(); for (int i = 0;i<80;i++){ Log.d("TEST",i + str); try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d("TEST", ".onStartCommand方法执行。。。"); return super.onStartCommand(intent, flags, startId); } @Override public boolean onUnbind(Intent intent) { Log.d("TEST", ".onUnbind方法执行。。。"); return super.onUnbind(intent); } @Override public void onDestroy() { Log.d("TEST", ".onDestroy方法执行。。。"); super.onDestroy(); } }
AndroidManiFest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cn.lixyz.servicedemo" > <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name=".MyStartService" android:enabled="true" android:exported="true" > </service> <service android:name=".MyBindService" android:enabled="true" android:exported="true" > </service> </application> </manifest>
运行结果: