什么是Service
有些用时比较长的操作我们希望他在后台运行,不耽误我们当前的操作。这就引入了Service的概念。常见的比如:访问网络,文件IO操作,大数据的数据库任务,播放音乐等。
Service在后台运行,并不用户进行交互。在默认的情况下,Service运行在应用程序进程的主线程中,如果要在Service中处理一些网络连接等耗时的操作,那么应当将这些任务放到单独的线程中处理,避免阻塞用户界面
有些用时比较长的操作我们希望他在后台运行,不耽误我们当前的操作。这就引入了Service的概念。常见的比如:访问网络,文件IO操作,大数据的数据库任务,播放音乐等。
Service在后台运行,并不用户进行交互。在默认的情况下,Service运行在应用程序进程的主线程中,如果要在Service中处理一些网络连接等耗时的操作,那么应当将这些任务放到单独的线程中处理,避免阻塞用户界面
What is a service?
API解释:
Most confusion about the Service class actually revolves around what it is not:
A Service is not a separate process. The Service object itself does not imply it is running in its own process; unless otherwise specified, it runs in the same process as the application it is part of.
A Service is not a thread. It is not a means itself to do work off of the main thread (to avoid Application Not Responding errors).
Most confusion about the Service class actually revolves around what it is not:
A Service is not a separate process. The Service object itself does not imply it is running in its own process; unless otherwise specified, it runs in the same process as the application it is part of.
A Service is not a thread. It is not a means itself to do work off of the main thread (to avoid Application Not Responding errors).
启动服务,不用多线程,界面是否会阻塞 Yes
启动服务后,按Home键,服务是否还在运行 Yes
启动服务后,退出进程,是否服务还会运行 No
public class ServiceTest extends Activity{
Intent service;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.service);
Button startService=(Button)findViewById(R.id.start);
startService.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
service=new Intent(ServiceTest.this, MyService.class);
startService(service);
}
});
Button stopService=(Button)findViewById(R.id.stop);
stopService.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(service!=null){
boolean returnResult=stopService(service);
Log.d("MyLog", "MyService has stoped "+returnResult);
}
}
});
}
}
public class MyService extends Service{
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//证明是主线程
/*for (int i = 0; i < 100; i++) {
try{
Thread.sleep(1000);
Log.d("MyLog", "Starting BeginService "+i);
}catch(InterruptedException e){
e.printStackTrace();
}
}*/
//采用多线程
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(1000);
Log.d("MyLog", "Starting BeginService "+i);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).start();
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.d("MyLog", "MyService OnDestory");
super.onDestroy();
}
}
//证明是主线程
for (int i = 0; i < 100; i++) {
try{
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
}
08-28 15:24:35.100: DEBUG/MyLog(493): Starting BeginService 0
08-28 15:24:36.142: DEBUG/MyLog(493): Starting BeginService 1
08-28 15:24:37.163: DEBUG/MyLog(493): Starting BeginService 2
08-28 15:24:38.166: DEBUG/MyLog(493): Starting BeginService 3
08-28 15:24:39.165: DEBUG/MyLog(493): Starting BeginService 4
08-28 15:24:40.167: DEBUG/MyLog(493): Starting BeginService 5
08-28 15:24:41.164: DEBUG/MyLog(493): Starting BeginService 6
08-28 15:24:42.175: DEBUG/MyLog(493): Starting BeginService 7
08-28 15:24:43.175: DEBUG/MyLog(493): Starting BeginService 8
08-28 15:24:44.242: DEBUG/MyLog(493): Starting BeginService 9
08-28 15:24:45.244: DEBUG/MyLog(493): Starting BeginService 10
当按home键的时候程序正常执行,但是当按back键的时候出现ANR错误:
08-28 07:00:09.114: ERROR/ActivityManager(58): ANR in com.gao
08-28 07:00:09.114: ERROR/ActivityManager(58): Reason: Executing service com.gao/.service.MyService
08-28 07:00:09.114: ERROR/ActivityManager(58): Load: 0.61 / 0.51 / 0.33
08-28 07:00:09.114: ERROR/ActivityManager(58): CPU usage from 182882ms to 55ms ago:
08-28 07:00:09.114: ERROR/ActivityManager(58): system_server: 10% = 7% user + 2% kernel / faults: 3353 minor 6 major
08-28 07:00:09.114: ERROR/ActivityManager(58): adbd: 0% = 0% user + 0% kernel / faults: 55 minor
08-28 07:00:09.114: ERROR/ActivityManager(58): ndroid.launcher: 0% = 0% user + 0% kernel / faults: 775 minor
08-28 07:00:09.114: ERROR/ActivityManager(58): qemud: 0% = 0% user + 0% kernel / faults: 2 minor
08-28 07:00:09.114: ERROR/ActivityManager(58): d.process.acore: 0% = 0% user + 0% kernel / faults: 1124 minor
08-28 07:00:09.114: ERROR/ActivityManager(58): id.defcontainer: 0% = 0% user + 0% kernel / faults: 135 minor
08-28 07:00:09.114: ERROR/ActivityManager(58): com.svox.pico: 0% = 0% user + 0% kernel / faults: 89 minor
08-28 07:00:09.114: ERROR/ActivityManager(58): logcat: 0% = 0% user + 0% kernel / faults: 3 minor
08-28 07:00:09.114: ERROR/ActivityManager(58): events/0: 0% = 0% user + 0% kernel
08-28 07:00:09.114: ERROR/ActivityManager(58): zygote: 0% = 0% user + 0% kernel / faults: 94 minor
08-28 07:00:09.114: ERROR/ActivityManager(58): ndroid.settings: 0% = 0% user + 0% kernel / faults: 92 minor
08-28 07:00:09.114: ERROR/ActivityManager(58): m.android.phone: 0% = 0% user + 0% kernel / faults: 67 minor 1 major
08-28 07:00:09.114: ERROR/ActivityManager(58): com.android.mms: 0% = 0% user + 0% kernel / faults: 43 minor
08-28 07:00:09.114: ERROR/ActivityManager(58): m.android.email: 0% = 0% user + 0% kernel / faults: 43 minor
08-28 07:00:09.114: ERROR/ActivityManager(58): .quicksearchbox: 0% = 0% user + 0% kernel / faults: 42 minor
08-28 07:00:09.114: ERROR/ActivityManager(58): d.process.media: 0% = 0% user + 0% kernel / faults: 44 minor
08-28 07:00:09.114: ERROR/ActivityManager(58): roid.alarmclock: 0% = 0% user + 0% kernel / faults: 41 minor
08-28 07:00:09.114: ERROR/ActivityManager(58): android.protips: 0% = 0% user + 0% kernel / faults: 41 minor
08-28 07:00:09.114: ERROR/ActivityManager(58): zygote: 0% = 0% user + 0% kernel / faults: 53 minor
08-28 07:00:09.114: ERROR/ActivityManager(58): pdflush: 0% = 0% user + 0% kernel
08-28 07:00:09.114: ERROR/ActivityManager(58): installd: 0% = 0% user + 0% kernel / faults: 3 minor
08-28 07:00:09.114: ERROR/ActivityManager(58): m.android.music: 0% = 0% user + 0% kernel / faults: 41 minor
08-28 07:00:09.114: ERROR/ActivityManager(58): +com.gao: 0% = 0% user + 0% kernel
08-28 07:00:09.114: ERROR/ActivityManager(58): -com.gao: 0% = 0% user + 0% kernel
08-28 07:00:09.114: ERROR/ActivityManager(58): TOTAL: 18% = 11% user + 6% kernel + 0% irq + 0% softirq
08-28 07:00:09.274: DEBUG/dalvikvm(58): GC_FOR_MALLOC freed 3354 objects / 253392 bytes in 119ms
08-28 07:00:09.274: INFO/dalvikvm-heap(58): Grow heap (frag case) to 5.096MB for 82056-byte allocation
08-28 07:00:09.474: DEBUG/dalvikvm(58): GC_FOR_MALLOC freed 295 objects / 14200 bytes in 190ms
08-28 07:00:09.675: DEBUG/dalvikvm(58): GC_FOR_MALLOC freed 72 objects / 228600 bytes in 194ms
08-28 07:00:14.190: WARN/ActivityManager(58): Launch timeout has expired, giving up wake lock!
08-28 07:00:14.280: WARN/ActivityManager(58): Activity idle timeout for HistoryRecord{43f20808 com.gao/.service.ServiceTest}
这也就证明了service是在主线程里面执行的,而在service里面新建一个线程就可以正常的执行。
当单击StopService按钮时,在主线程里面的会出现按钮不可点击,出现ANR错误。当以一个线程启动的时候,可以正常停止服务,但是已经启动的线程还是继续在运行。
08-28 16:13:37.265: DEBUG/MyLog(781): Starting BeginService 0
08-28 16:13:38.279: DEBUG/MyLog(781): Starting BeginService 1
08-28 16:13:39.328: DEBUG/MyLog(781): Starting BeginService 2
08-28 16:13:40.375: DEBUG/MyLog(781): Starting BeginService 3
08-28 16:13:41.437: DEBUG/MyLog(781): Starting BeginService 4
08-28 16:13:42.184: DEBUG/MyLog(781): MyService has stoped true
08-28 16:13:42.184: DEBUG/MyLog(781): MyService OnDestory
08-28 16:13:42.503: DEBUG/MyLog(781): Starting BeginService 5
08-28 16:13:43.560: DEBUG/MyLog(781): Starting BeginService 6
08-28 16:13:44.566: DEBUG/MyLog(781): Starting BeginService 7
08-28 16:13:45.582: DEBUG/MyLog(781): Starting BeginService 8