Android Studio App开发之服务Service的讲解及实战(包括启动和停止,绑定与解绑,推送服务到前台实现音乐播放器,附源码)

运行有问题或需要源码请点赞关注收藏后评论区留言~~~

一、服务的启动和停止

服务Service是Android的四大组件之一,它常用于页面的高级场合,这些系统服务平时几乎感觉不到它们的存在,却是系统不可或缺的重要组成部分。

既然Android自带了系统服务,App也可以拥有自己的服务,服务Service与活动Activity相比,不同之处在于没有对应的页面,相同之处在于都有生命周期 常用方法如下

1:onCreate 创建服务
2:onStart 开始服务
3:onStartCommand 开始服务
4:onDestroy 销毁服务
5:onBind 绑定服务
6:onUnbind 解除绑定
7:onRebind 重新绑定

点击启动服务和停止服务会调用相对应得方法 效果如下

Android Studio App开发之服务Service的讲解及实战(包括启动和停止,绑定与解绑,推送服务到前台实现音乐播放器,附源码)

代码如下

Java类

package com.example.chapter11;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import com.example.chapter11.service.NormalService;
import com.example.chapter11.util.DateUtil;

@SuppressLint("StaticFieldLeak")
public class ServiceNormalActivity extends AppCompatActivity implements View.OnClickListener {
    private static TextView tv_normal;
    private Intent mIntent; // 声明一个意图对象
    private static String mDesc;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_service_normal);
        tv_normal = findViewById(R.id.tv_normal);
        findViewById(R.id.btn_start).setOnClickListener(this);
        findViewById(R.id.btn_stop).setOnClickListener(this);
        mDesc = "";
        // 创建一个通往普通服务的意图
        mIntent = new Intent(this, NormalService.class);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.btn_start) { // 点击了启动服务按钮
            startService(mIntent); // 启动指定意图的服务
        } else if (v.getId() == R.id.btn_stop) { // 点击了停止服务按钮
            stopService(mIntent); // 停止指定意图的服务
        }
    }

    public static void showText(String desc) {
        if (tv_normal != null) {
            mDesc = String.format("%s%s %s\n", mDesc, DateUtil.getNowDateTime("HH:mm:ss"), desc);
            tv_normal.setText(mDesc);
        }
    }

}

XML文件

<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical">

    <linearlayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal">

        <button android:id="@+id/btn_start" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:text="&#x542F;&#x52A8;&#x670D;&#x52A1;" android:textcolor="@color/black" android:textsize="17sp">

        </button><button android:id="@+id/btn_stop" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:text="&#x505C;&#x6B62;&#x670D;&#x52A1;" android:textcolor="@color/black" android:textsize="17sp">
    </button></linearlayout>

    <textview android:id="@+id/tv_normal" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingleft="5dp" android:textcolor="@color/black" android:textsize="17sp">

</textview></linearlayout>

二、服务的绑定与解绑

服务启停除了上一小节介绍的普通方式,也就是绑定服务和解绑服务。对于服务来说,便要求提供粘合剂Binder指定服务的绑定关系,同时黏合剂指定服务的绑定关系,同时黏合剂还负责在两个组件或者在两个进程之间交流通信。效果如下

延迟绑定与立即绑定的生命周期区别在于
1:延迟绑定的首次绑定操作只触发onBind方法,再次绑定操作只触发onRebind方法
2:延迟绑定的解绑操作只触发onUnbind方法

Android Studio App开发之服务Service的讲解及实战(包括启动和停止,绑定与解绑,推送服务到前台实现音乐播放器,附源码)

代码如下

Java类

package com.example.chapter11;

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;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import com.example.chapter11.service.BindDelayService;
import com.example.chapter11.util.DateUtil;

public class BindDelayActivity extends AppCompatActivity implements View.OnClickListener {
    private static final String TAG = "BindDelayActivity";
    private static TextView tv_delay;
    private Intent mIntent; // &#x58F0;&#x660E;&#x4E00;&#x4E2A;&#x610F;&#x56FE;&#x5BF9;&#x8C61;
    private static String mDesc;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bind_delay);
        tv_delay = findViewById(R.id.tv_delay);
        findViewById(R.id.btn_start).setOnClickListener(this);
        findViewById(R.id.btn_bind).setOnClickListener(this);
        findViewById(R.id.btn_unbind).setOnClickListener(this);
        findViewById(R.id.btn_stop).setOnClickListener(this);
        mDesc = "";
        // &#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x901A;&#x5F80;&#x5EF6;&#x8FDF;&#x7ED1;&#x5B9A;&#x670D;&#x52A1;&#x7684;&#x610F;&#x56FE;
        mIntent = new Intent(this, BindDelayService.class);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.btn_start) { // &#x70B9;&#x51FB;&#x4E86;&#x5F00;&#x59CB;&#x670D;&#x52A1;&#x6309;&#x94AE;
            startService(mIntent); // &#x542F;&#x52A8;&#x670D;&#x52A1;
        } else if (v.getId() == R.id.btn_bind) { // &#x70B9;&#x51FB;&#x4E86;&#x7ED1;&#x5B9A;&#x670D;&#x52A1;&#x6309;&#x94AE;
            boolean bindFlag = bindService(mIntent, mFirstConn, Context.BIND_AUTO_CREATE); // &#x7ED1;&#x5B9A;&#x670D;&#x52A1;
            Log.d(TAG, "bindFlag=" + bindFlag);
        } else if (v.getId() == R.id.btn_unbind) { // &#x70B9;&#x51FB;&#x4E86;&#x89E3;&#x7ED1;&#x670D;&#x52A1;&#x6309;&#x94AE;
            if (mBindService != null) {
                unbindService(mFirstConn); // &#x89E3;&#x7ED1;&#x670D;&#x52A1;
                mBindService = null;
            }
        } else if (v.getId() == R.id.btn_stop) { // &#x70B9;&#x51FB;&#x4E86;&#x505C;&#x6B62;&#x670D;&#x52A1;&#x6309;&#x94AE;
            stopService(mIntent); // &#x505C;&#x6B62;&#x670D;&#x52A1;
        }
    }

    public static void showText(String desc) {
        if (tv_delay != null) {
            mDesc = String.format("%s%s %s\n", mDesc, DateUtil.getNowDateTime("HH:mm:ss"), desc);
            tv_delay.setText(mDesc);
        }
    }

    private BindDelayService mBindService; // &#x58F0;&#x660E;&#x4E00;&#x4E2A;&#x670D;&#x52A1;&#x5BF9;&#x8C61;
    private ServiceConnection mFirstConn = new ServiceConnection() {

        // &#x83B7;&#x53D6;&#x670D;&#x52A1;&#x5BF9;&#x8C61;&#x65F6;&#x7684;&#x64CD;&#x4F5C;
        public void onServiceConnected(ComponentName name, IBinder service) {
            // &#x5982;&#x679C;&#x670D;&#x52A1;&#x8FD0;&#x884C;&#x4E8E;&#x53E6;&#x5916;&#x4E00;&#x4E2A;&#x8FDB;&#x7A0B;&#xFF0C;&#x5219;&#x4E0D;&#x80FD;&#x76F4;&#x63A5;&#x5F3A;&#x5236;&#x8F6C;&#x6362;&#x7C7B;&#x578B;&#xFF0C;&#x5426;&#x5219;&#x4F1A;&#x62A5;&#x9519;
            mBindService = ((BindDelayService.LocalBinder) service).getService();
            Log.d(TAG, "onServiceConnected");
        }

        // &#x65E0;&#x6CD5;&#x83B7;&#x53D6;&#x5230;&#x670D;&#x52A1;&#x5BF9;&#x8C61;&#x65F6;&#x7684;&#x64CD;&#x4F5C;
        public void onServiceDisconnected(ComponentName name) {
            mBindService = null;
            Log.d(TAG, "onServiceDisconnected");
        }
    };

}

XML文件

<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical">

    <linearlayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal">

        <button android:id="@+id/btn_start" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:text="&#x542F;&#x52A8;&#x670D;&#x52A1;" android:textcolor="@color/black" android:textsize="15sp">

        </button><button android:id="@+id/btn_bind" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:text="&#x7ED1;&#x5B9A;&#x670D;&#x52A1;" android:textcolor="@color/black" android:textsize="15sp">

        </button><button android:id="@+id/btn_unbind" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:text="&#x89E3;&#x7ED1;&#x670D;&#x52A1;" android:textcolor="@color/black" android:textsize="15sp">

        </button><button android:id="@+id/btn_stop" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:text="&#x505C;&#x6B62;&#x670D;&#x52A1;" android:textcolor="@color/black" android:textsize="15sp">
    </button></linearlayout>

    <textview android:id="@+id/tv_delay" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingleft="5dp" android:textcolor="@color/black" android:textsize="17sp">

</textview></linearlayout>

三、推送服务到前台

服务没有自己的布局文件,意味着无法直接在页面上展示服务信息,要想了解服务的运行情况,要么通过打印日志观察,要么通过某个页面的静态控件显示运行结果,然而活动页面有自身的生命周期,为此Android设计了一个让服务在前台运行的机制,也就是在手机的通知栏展示服务的画像,同时允许自己是否需要在通知栏显示 包括下面两个方法

1:startForeground 把当前服务切换到前台运行 即展示到通知栏
2:stopForeground 停止前台运行 即取消通知栏上的展示

效果如下 连接了真机后会在 后台显示

Android Studio App开发之服务Service的讲解及实战(包括启动和停止,绑定与解绑,推送服务到前台实现音乐播放器,附源码)

代码如下

Java类

package com.example.chapter11;

import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import com.example.chapter11.service.MusicService;
import com.example.chapter11.util.ViewUtil;

public class ForegroundServiceActivity extends AppCompatActivity implements View.OnClickListener {
    private EditText et_song;
    private Button btn_send_service;
    private boolean isPlaying = true; // &#x662F;&#x5426;&#x6B63;&#x5728;&#x64AD;&#x653E;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_foreground_service);
        et_song = findViewById(R.id.et_song);
        btn_send_service = findViewById(R.id.btn_send_service);
        btn_send_service.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.btn_send_service) {
            if (TextUtils.isEmpty(et_song.getText())) {
                Toast.makeText(this, "&#x8BF7;&#x586B;&#x5199;&#x6B4C;&#x66F2;&#x540D;&#x79F0;", Toast.LENGTH_SHORT).show();
                return;
            }
            // &#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x901A;&#x5F80;&#x97F3;&#x4E50;&#x670D;&#x52A1;&#x7684;&#x610F;&#x56FE;
            Intent intent = new Intent(this, MusicService.class);
            intent.putExtra("is_play", isPlaying); // &#x662F;&#x5426;&#x6B63;&#x5728;&#x64AD;&#x653E;&#x97F3;&#x4E50;
            intent.putExtra("song", et_song.getText().toString());
            btn_send_service.setText(isPlaying?"&#x6682;&#x505C;&#x64AD;&#x653E;&#x97F3;&#x4E50;":"&#x5F00;&#x59CB;&#x64AD;&#x653E;&#x97F3;&#x4E50;");
            startService(intent); // &#x542F;&#x52A8;&#x97F3;&#x4E50;&#x64AD;&#x653E;&#x670D;&#x52A1;
            isPlaying = !isPlaying;
        }
    }

}

XML文件

<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="5dp">

    <linearlayout android:layout_width="match_parent" android:layout_height="50dp" android:orientation="horizontal">

        <textview android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center" android:text="&#x6B4C;&#x66F2;&#x540D;&#x79F0;&#xFF1A;" android:textcolor="@color/black" android:textsize="17sp">

        <edittext android:id="@+id/et_song" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:layout_margin="5dp" android:background="@drawable/editext_selector" android:hint="&#x8BF7;&#x586B;&#x5199;&#x6B4C;&#x66F2;&#x540D;&#x79F0;" android:textcolor="@color/black" android:textsize="17sp">

    </edittext></textview></linearlayout>

    <button android:id="@+id/btn_send_service" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="&#x5F00;&#x59CB;&#x64AD;&#x653E;&#x97F3;&#x4E50;" android:textcolor="#000000" android:textsize="17sp">

</button></linearlayout>

创作不易 觉得有帮助请点赞关注收藏~~~

Original: https://blog.csdn.net/jiebaoshayebuhui/article/details/127825857
Author: showswoller
Title: Android Studio App开发之服务Service的讲解及实战(包括启动和停止,绑定与解绑,推送服务到前台实现音乐播放器,附源码)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/661318/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球