Service 基础用法简介

本文介绍了Android Service的基础用法,包括通过startService和bindService启动服务的区别,强调服务的生命周期及其在主线程中运行的特点。同时提到了前台服务以增加服务的优先级和IntentService用于处理耗时任务避免ANR问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 Service简介

        服务(Service)  是Android中实现程序后台运行的解决方案,它非常适合去执行那些不需要 和用户交互而且还要求长期运行的任务。服务的运行不依赖于任何用户界面,即使程序被切换到 后台,或者用户打开了另外一个应用程序,服务仍然能够保持正常运行。

        服务并不是运行在一个独立的进程当中的,而是依赖于创建服务时所在 的应用程序进程。当某个应用程序进程被杀掉时,所有依赖于该进程的服务也会停止运行。

        服务并不会自动幵启线程,所有的代码都是 默认运行在主线程当中的。我们需要在服务的内部手动创建子线程,并在这里执行具 体的任务,否则就有可能出现主线程被阻塞住的情况。

 

2  Service的两种启动方式

  1  使用ContextstartService(Intent)方法启动Service

  • 步骤
  1. 定义一个类继承Service
  2. 在Manifest.xml文件中配置该Service
  3. 使用Context的startService(Intent)方法启动该Service
  4. 不再使用时,调用stopService(Intent)或者stopSelf()方法停止该服务
  • 生命周期

       onCreate()--->onStartCommand()(onStart()方法已过时)---> onDestory()

  • 特点
  1. 如果服务已经开启,不会重复的执行onCreate(), 而是会调用onStartCommand()。服务停止的时候调用 onDestory()。服务只会被停止一次。

     2. 一旦服务开启跟调用者(开启者)就没有任何关系了。开启者退出了,开启者挂了,服务还在后台长期的运行。开启者不能调用服务里面的方法。

  • 代码示例        

            Actiivity 中代码            

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private static final String TAG = "MainActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button startService = findViewById(R.id.start_service);
        Button stopService = findViewById(R.id.stop_services);
        startService.setOnClickListener(this);
        stopService.setOnClickListener(this);

    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.start_service:
                Intent startIntent=new Intent(this,MyService.class);
                //开启服务
                startService(startIntent);
                break;
            case R.id.stop_services:
                Intent stopIntent=new Intent(this,MyService.class);
                //结束服务
                stopService(stopIntent);
                break;
            default:
                break;
        }
    }
}

          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=".MainActivity">

   <Button
       android:id="@+id/start_service"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:text="Start Service"/>
   <Button
       android:layout_marginTop="10dp"
       android:id="@+id/stop_service"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:text="Stop Service"/>
</LinearLayout>

            Service 中代码

public class MyService extends Service {
    private static final String TAG = "MyService";
    public MyService() {
    }

    /**
     * @param intent
     * @return
     * Services中唯一一个抽象方法
     */
    @Override
    public IBinder onBind(Intent intent) {

        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate()");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "onStartCommand()");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy()");
    }
}

            第一次点击启动服务        

 E/MyService: onCreate()
 E/MyService: onStartCommand()

             再次点击启动服务(注意多次调用startService(Intent)也只会存在一个服务实例

 E/MyService: onCreate()
 E/MyService: onStartCommand()
 E/MyService: onStartCommand()

             停止服务

 E/MyService: onCreate()
 E/MyService: onStartCommand()
 E/MyService: onStartCommand()
 E/MyService: onDestroy()

 

  2  使用ContextbindService(Intent, ServiceConnection, int)方法启动Service

  • 步骤
  1. 定义一个类继承Service
  2. 在Manifest.xml文件中配置该Service
  3. 使用Context的bindService(Intent, ServiceConnection, int)方法启动该Service
  4. 不再使用时,调用unbindService(ServiceConnection)方法停止该服务
  • 生命周期

       onCreate()--->onBind()---> onUnbind()---> onDestory()

  • 特点
  1. 绑定服务不会调用onStart()或者onStartCommand()。

     2. 用bind的方式开启服务,绑定服务,调用者挂了,服务也会跟着挂掉。绑定者可以调用服务里面的方法

  • 代码示例        

             Service 代码

public class MyService extends Service {
    private static final String TAG = "MyService";
    private MyBinder myBinder=new MyBinder();
    public MyService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.e(TAG, "onCreate()");
    }

    /**
     * @param intent
     * @return
     * Services中唯一一个抽象方法
     */
    @Override
    public IBinder onBind(Intent intent) {
        Log.e(TAG, "onBind()");
        return myBinder;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(TAG, "onStartCommand()");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.e(TAG, "onUnbind()");
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.e(TAG, "onDestroy()");
    }

    class MyBinder extends Binder implements IMyBinder{

        @Override
        public void proMethodInMyService() {
            methodInMyService();
        }
    }

    private void methodInMyService() {
        Log.e(TAG, "服务里的方法执行了");
    }
}

            IMyBinder 接口代码

/**
 * 用于保护服务中不想让外界访问的方法。
 */
public interface IMyBinder {

    void proMethodInMyService();
}

           MainActivity 代码

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private static final String TAG = "MainActivity";
    private IMyBinder myBinder;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button bindService = findViewById(R.id.bind_service);
        Button serviceMethod = findViewById(R.id.service_method);
        Button unbindService = findViewById(R.id.unbind_service);
        bindService.setOnClickListener(this);
        serviceMethod.setOnClickListener(this);
        unbindService.setOnClickListener(this);


    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.bind_service:
                //绑定服务
                Intent bindIntent=new Intent(this,MyService.class);
                // 第一个参数是intent对象,表面开启的服务。
                // 第二个参数是绑定服务的监听器
                // 第三个参数一般为BIND_AUTO_CREATE常量,表示自动创建bind
                bindService(bindIntent,connection,BIND_AUTO_CREATE);
                break;
            case R.id.service_method:
                //调用服务中方法
                myBinder.proMethodInMyService();
                break;
            case R.id.unbind_service:
                //解绑服务
                unbindService(connection);
                break;
            default:
                break;
        }
    }

    /**
     * connection
     * ServiceConnection 匿名类
     */
    private ServiceConnection connection=new ServiceConnection(){

        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            //iBinder为服务里面onBind()方法返回的对象
            myBinder = (IMyBinder) iBinder;
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {

        }
    };

}

            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=".MainActivity">

   <Button
       android:id="@+id/bind_service"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:text="Bind Service"/>
   <Button
       android:layout_marginTop="10dp"
       android:id="@+id/service_method"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:text="Service method"/>
   <Button
       android:layout_marginTop="10dp"
       android:id="@+id/unbind_service"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:text="Unbind Service"/>
</LinearLayout>

           点击绑定服务

 E/MyService: onCreate()
 E/MyService: onBind()

          点击调用方法

 E/MyService: onCreate()
 E/MyService: onBind()
 E/MyService: 服务里的方法执行了

          点击解绑服务

 E/MyService: onCreate()
 E/MyService: onBind()
 E/MyService: 服务里的方法执行了
 E/MyService: onUnbind()
 E/MyService: onDestroy()

3  前台服务

         服务的系统优先级比较低,当系统出现内存不足的情况时,就有可能会回收掉正在后台运行的服务。如果希望服务可以一直保持运行状态,而不会由于系统内存不足的原因导致被回收,就可以考虑使用前台服务。前台服务和普通服务最大的区别就在于,它会一直有一个正在运行的图标在系统的 状态栏显示,下拉状态栏后可以看到更加详细的信息,非常类似于通知的效果。  

  • 代码示例     
public class MyService extends Service {
    private static final String TAG = "MyService";
    private MyBinder myBinder=new MyBinder();
    public MyService() {
    }

    /**
     *
     */
    @Override
    public void onCreate() {
        super.onCreate();
        Log.e(TAG, "onCreate()");
        Intent intent=new Intent(this,MainActivity.class);
        PendingIntent pi=PendingIntent.getActivity(this,0,intent,0);
        Notification notification=new NotificationCompat.Builder(this)
                .setContentTitle("this is content title")
                .setContentText("this is content text")
                .setWhen(System.currentTimeMillis())
                .setSmallIcon(R.mipmap.ic_launcher)
                .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher))
                .setContentIntent(pi)
                .build();
        // 第一个参数是通知的id
        // 第二个参数是构建出的Notification对象
        startForeground(1,notification);
    }

    /**
     * @param intent
     * @return
     * Services中唯一一个抽象方法
     */
    @Override
    public IBinder onBind(Intent intent) {
        Log.e(TAG, "onBind()");
        return myBinder;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(TAG, "onStartCommand()");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.e(TAG, "onUnbind()");
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.e(TAG, "onDestroy()");
    }

    class MyBinder extends Binder implements IMyBinder{

        @Override
        public void proMethodInMyService() {
            methodInMyService();
        }
    }

    private void methodInMyService() {
        Log.e(TAG, "服务里的方法执行了");
    }
}

  4 IntentService

         服务中的代码都是默认运行在主线程当中 的,如果直接在服务里去处理一些耗时的逻辑,就很容易出现ANR ( Application Not Responding ) 的情况。 

           1、 普通Service和Android 多线程结合                 

public class MyService extends Service {
    private static final String TAG = "MyService";
    public MyService() {
    }

    /**
     * @param intent
     * @return
     * Services中唯一一个抽象方法
     */
    @Override
    public IBinder onBind(Intent intent) {

        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate()");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "onStartCommand()");
        new Thread(new Runnable() {
            @Override
            public void run() {
                //处理具体逻辑
                stopSelf();
            }
        }).start();
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy()");
    }
}

        2 、使用IntentService

             IntentService代码           

public class MyIntentService extends IntentService {
    private static final String TAG = "MyIntentService";
    public MyIntentService() {
        //调用父类的有参构造函数
        super("MyIntentService");
    }

    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        //打印当前线程id
        Log.e(TAG, "Thread id is"+Thread.currentThread().getId());
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.e(TAG, "onDestroy()");
    }
}

          MainActivity 代码                           

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private static final String TAG = "MainActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button startIntentService = findViewById(R.id.start_intent_service);
        startIntentService.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.start_intent_service:
                //开启服务
                Log.e(TAG, "Thread id is"+Thread.currentThread().getId() );
                Intent intentService =new Intent(this,MyIntentService.class);
                startService(intentService);
                break;
            default:
                break;
        }
    }
}

        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=".MainActivity">

   <Button
       android:layout_marginTop="10dp"
       android:id="@+id/start_intent_service"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:text="Start IntentService"/>

</LinearLayout>

       启动IntentService 打印结果

 E/MainActivity: Thread id is1
 E/MyIntentService: Thread id is4110
 E/MyIntentService: onDestroy()

 

  注:参考内容:1  https://www.jianshu.com/p/2fb6eb14fdec

                           2  郭霖《第一行代码》(第二版)    

 

                                        

                                       

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值