最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用Android Service實(shí)現(xiàn)后臺(tái)音樂(lè)播放功能

 更新時(shí)間:2025年11月18日 08:45:30   作者:珹洺  
本文將基于Android Studio 2025.1.4 + 模擬器Android 14 環(huán)境,手把手實(shí)現(xiàn)后臺(tái)音樂(lè)播放功能,通過(guò)Service管理音樂(lè)播放/暫停邏輯,Activity作為界面交互入口,讓你徹底理解Service的生命周期、啟動(dòng)/停止方式以及組件間的通信邏輯,需要的朋友可以參考下

前言

本文將聚焦Android另一個(gè)核心組件——Service(服務(wù)),它是運(yùn)行在后臺(tái)的“無(wú)界面組件”,適合執(zhí)行長(zhǎng)時(shí)間運(yùn)行的任務(wù)(如音樂(lè)播放、文件下載、網(wǎng)絡(luò)請(qǐng)求)。

本文將基于 Android Studio 2025.1.4 + 模擬器Android 14 環(huán)境,手把手實(shí)現(xiàn)“后臺(tái)音樂(lè)播放”功能:通過(guò)Service管理音樂(lè)播放/暫停邏輯,Activity作為界面交互入口,讓你徹底理解Service的生命周期、啟動(dòng)/停止方式以及組件間的通信邏輯。

前置準(zhǔn)備

開(kāi)始前確保以下環(huán)境和資源就緒:

  • 開(kāi)發(fā)工具:Android Studio 2025.1.4
  • 模擬器/真機(jī):Android 14(API 34)
  • 音樂(lè)資源:準(zhǔn)備一首MP3格式音樂(lè),命名為music.mp3(后續(xù)放入res/raw文件夾)
  • 核心知識(shí)點(diǎn):了解Android組件基礎(chǔ)、Intent通信(前序博客已覆蓋)

一、Service核心概念

1.1 什么是Service?

Service是Android四大組件之一,運(yùn)行在主線程后臺(tái)(非獨(dú)立進(jìn)程),無(wú)可視化界面,適合執(zhí)行不需要用戶交互的長(zhǎng)時(shí)間任務(wù)。

Service核心特性說(shuō)明類比場(chǎng)景
無(wú)界面不占用屏幕空間,后臺(tái)運(yùn)行電腦后臺(tái)的音樂(lè)播放器進(jìn)程
生命周期長(zhǎng)即使Activity銷毀,Service可繼續(xù)運(yùn)行關(guān)閉視頻軟件窗口,背景音樂(lè)仍播放
主線程運(yùn)行默認(rèn)在主線程執(zhí)行,耗時(shí)操作需手動(dòng)開(kāi)子線程需配合Thread/AsyncTask處理耗時(shí)任務(wù)

1.2 Service生命周期(重點(diǎn))

本次實(shí)戰(zhàn)使用“啟動(dòng)式Service”(startService()啟動(dòng),stopService()停止),核心生命周期方法如下:

  1. onCreate():Service首次創(chuàng)建時(shí)調(diào)用(僅執(zhí)行1次),用于初始化資源(如創(chuàng)建MediaPlayer);
  2. onStartCommand():每次調(diào)用startService()時(shí)觸發(fā),用于執(zhí)行具體業(yè)務(wù)邏輯(如播放音樂(lè));
  3. onDestroy():Service銷毀時(shí)調(diào)用(執(zhí)行stopService()或系統(tǒng)回收),用于釋放資源(如停止播放、釋放MediaPlayer)。

1.3 項(xiàng)目結(jié)構(gòu)總覽

com.example.ch9service
├── MusicService.java       // 核心Service:管理音樂(lè)播放/暫停/釋放
├── ServiceActivity.java    // 界面Activity:提供播放/暫停按鈕交互
├── res
│   ├── raw                 // 音樂(lè)資源文件夾(存放music.mp3)
│   │   └── music.mp3
│   ├── layout
│   │   └── activity_service.xml  // 界面布局(僅1個(gè)按鈕)
│   └── values
│       └── strings.xml
└── AndroidManifest.xml     // 清單文件:注冊(cè)Service和Activity

二、代碼實(shí)現(xiàn)

2.1 第一步:添加音樂(lè)資源

  1. res文件夾下新建raw文件夾(右鍵res→New→Android Resource Directory→Resource type選raw);
  2. 將MP3音樂(lè)文件放入raw文件夾,命名為music.mp3(注意:文件名只能包含字母、數(shù)字和下劃線,不能有中文)。

2.2 第二步:編寫Service核心類(MusicService.java)

MusicService負(fù)責(zé)音樂(lè)播放的核心邏輯:初始化MediaPlayer、播放、停止、釋放資源,通過(guò)靜態(tài)變量ispaly記錄播放狀態(tài)。

package com.example.ch9service;

import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;

// 后臺(tái)音樂(lè)播放Service
public class MusicService extends Service {
    private MediaPlayer player; // 音樂(lè)播放器實(shí)例
    public static boolean ispaly = false; // 播放狀態(tài)標(biāo)記(靜態(tài)變量,供Activity訪問(wèn))

    public MusicService() {
        // 必須實(shí)現(xiàn)的構(gòu)造方法(無(wú)參)
    }

    @Override
    public IBinder onBind(Intent intent) {
        // 啟動(dòng)式Service無(wú)需綁定,返回null即可(若為綁定式Service需實(shí)現(xiàn))
        throw new UnsupportedOperationException("Not yet implemented");
    }

    // Service創(chuàng)建時(shí)調(diào)用(僅1次):初始化MediaPlayer
    @Override
    public void onCreate() {
        super.onCreate();
        // 創(chuàng)建MediaPlayer實(shí)例,加載raw文件夾中的音樂(lè)資源
        player = MediaPlayer.create(this, R.raw.music);
        // 設(shè)置音樂(lè)循環(huán)播放(可選,根據(jù)需求調(diào)整)
        player.setLooping(true);
    }

    // 每次調(diào)用startService()時(shí)觸發(fā):執(zhí)行播放邏輯
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // 若未在播放,則啟動(dòng)播放
        if (!player.isPlaying()) {
            player.start(); // 開(kāi)始播放音樂(lè)
            ispaly = player.isPlaying(); // 更新播放狀態(tài)為true
        }
        // 返回值:Service被系統(tǒng)回收后是否重建,START_STICKY表示重建
        return super.onStartCommand(intent, flags, startId);
    }

    // Service銷毀時(shí)調(diào)用:釋放資源(關(guān)鍵,避免內(nèi)存泄漏)
    @Override
    public void onDestroy() {
        super.onDestroy();
        if (player != null) {
            player.stop(); // 停止播放
            ispaly = player.isPlaying(); // 更新播放狀態(tài)為false
            player.release(); // 釋放MediaPlayer資源
            player = null; // 置空,便于GC回收
        }
    }
}

2.3 第三步:編寫界面布局(activity_service.xml)

布局僅包含1個(gè)按鈕,用于切換“播放”和“暫停”狀態(tài),采用ConstraintLayout居中布局。

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ServiceActivity">

    <!-- 播放/暫停切換按鈕 -->
    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="播放音樂(lè)"
        android:textSize="18sp"
        android:paddingHorizontal="30dp"
        android:paddingVertical="10dp"
        <!-- 約束布局:水平+垂直居中 -->
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

2.4 第四步:編寫Activity交互邏輯(ServiceActivity.java)

ServiceActivity作為界面入口,通過(guò)按鈕點(diǎn)擊事件啟動(dòng)/停止MusicService,并根據(jù)ispaly狀態(tài)切換按鈕文本。

package com.example.ch9service;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;

public class ServiceActivity extends AppCompatActivity {

    private Button playBtn; // 播放/暫停按鈕

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this); // 啟用沉浸式布局
        setContentView(R.layout.activity_service);

        // 適配系統(tǒng)狀態(tài)欄(避免按鈕被遮擋)
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
            Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
            return insets;
        });

        // 綁定按鈕控件
        playBtn = findViewById(R.id.button);
        // 設(shè)置按鈕點(diǎn)擊事件
        playBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 創(chuàng)建Intent,指定目標(biāo)Service
                Intent intent = new Intent(ServiceActivity.this, MusicService.class);

                // 根據(jù)播放狀態(tài)切換:未播放→啟動(dòng)Service(播放);已播放→停止Service(暫停)
                if (!MusicService.ispaly) {
                    startService(intent); // 啟動(dòng)Service,觸發(fā)onStartCommand()
                    playBtn.setText("暫停音樂(lè)"); // 切換按鈕文本
                } else {
                    stopService(intent); // 停止Service,觸發(fā)onDestroy()
                    playBtn.setText("播放音樂(lè)"); // 切換按鈕文本
                }
            }
        });
    }
}

2.5 第五步:注冊(cè)組件(AndroidManifest.xml)

Service和Activity都需在清單文件中注冊(cè),否則無(wú)法使用。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.MyApplication">

        <!-- 注冊(cè)Service:android:exported="true"允許外部啟動(dòng)(此處為應(yīng)用內(nèi)部使用,也可設(shè)為false) -->
        <service
            android:name=".MusicService"
            android:enabled="true"
            android:exported="true"></service>

        <!-- 注冊(cè)Activity(啟動(dòng)頁(yè)) -->
        <activity
            android:name=".ServiceActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

三、運(yùn)行測(cè)試

到此這篇關(guān)于使用Android Service實(shí)現(xiàn)后臺(tái)音樂(lè)播放功能的文章就介紹到這了,更多相關(guān)Android Service后臺(tái)音樂(lè)播放內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Input系統(tǒng)按鍵事件的分發(fā)處理示例詳解

    Input系統(tǒng)按鍵事件的分發(fā)處理示例詳解

    這篇文章主要為大家介紹了Input系統(tǒng)按鍵事件的分發(fā)處理示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • Android?Glide使用方法與原理分析

    Android?Glide使用方法與原理分析

    Android?Glide是一款強(qiáng)大的圖片加載庫(kù),提供了豐富的功能和靈活的使用方式,本文將深入分析Glide的工作原理,并介紹一些使用姿勢(shì),助你更好地運(yùn)用這個(gè)優(yōu)秀的庫(kù),需要的朋友可以參考下
    2023-09-09
  • android實(shí)現(xiàn)上滑屏幕隱藏底部菜單欄的示例

    android實(shí)現(xiàn)上滑屏幕隱藏底部菜單欄的示例

    這篇文章主要介紹了android實(shí)現(xiàn)上滑屏幕隱藏底部菜單欄的示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-02-02
  • Android?Activity通用懸浮可拖拽View封裝的思路詳解

    Android?Activity通用懸浮可拖拽View封裝的思路詳解

    這篇文章主要介紹了Android?Activity通用懸浮可拖拽View封裝,實(shí)現(xiàn)思路是通過(guò)封裝通用的基礎(chǔ)懸浮View,繼承通用View,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-07-07
  • android教程之hockeyapp捕獲異常示例

    android教程之hockeyapp捕獲異常示例

    這篇文章主要介紹了android中hockeyapp捕獲異常的示例,需要的朋友可以參考下
    2014-02-02
  • android在連拍菜單中增加連拍張數(shù)選項(xiàng)功能實(shí)現(xiàn)代碼

    android在連拍菜單中增加連拍張數(shù)選項(xiàng)功能實(shí)現(xiàn)代碼

    想要增加連拍張數(shù)選項(xiàng)需要在entries, entryvalues中添加兩項(xiàng),同時(shí)在mtk_strings.xml中添加相應(yīng)的字符串,具體如下,感興趣的朋友可以參考下哈
    2013-06-06
  • Android開(kāi)發(fā)自定義雙向SeekBar拖動(dòng)條控件

    Android開(kāi)發(fā)自定義雙向SeekBar拖動(dòng)條控件

    這篇文章主要為大家介紹了Android開(kāi)發(fā)自定義雙向SeekBar拖動(dòng)條控件使用實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • Android中的指紋識(shí)別demo開(kāi)發(fā)實(shí)例

    Android中的指紋識(shí)別demo開(kāi)發(fā)實(shí)例

    這篇文章主要介紹了Android中的指紋識(shí)別demo開(kāi)發(fā)實(shí)例的相關(guān)知識(shí),非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-09-09
  • Android自定義圓形進(jìn)度條

    Android自定義圓形進(jìn)度條

    這篇文章主要為大家詳細(xì)介紹了Android自定義圓形進(jìn)度條的相關(guān)代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • kotlin中新增擴(kuò)展函數(shù)功能的原因解析

    kotlin中新增擴(kuò)展函數(shù)功能的原因解析

    Kotlin擴(kuò)展函數(shù)通過(guò)語(yǔ)法糖在不修改原類的前提下添加功能,遵循開(kāi)閉原則,適用于第三方庫(kù)和基礎(chǔ)類型,避免繼承限制,本文給大家介紹kotlin中新增擴(kuò)展函數(shù)功能的原因解析,感興趣的朋友一起看看吧
    2025-07-07

最新評(píng)論

凤凰县| 常山县| 保山市| 通化市| 瑞金市| 巫山县| 呼玛县| 工布江达县| 邛崃市| 禹城市| 崇仁县| 汾阳市| 冕宁县| 抚松县| 松滋市| 岚皋县| 晋江市| 邛崃市| 普洱| 凤冈县| 二连浩特市| 宁德市| 娄底市| 甘洛县| 嫩江县| 定日县| 莎车县| 临沂市| 西吉县| 武邑县| 多伦县| 长葛市| 广州市| 无棣县| 新干县| 崇明县| 乌鲁木齐县| 博白县| 江北区| 博爱县| 弋阳县|