You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin开发:Activity启动音乐播放Service无声音问题求助

问题描述

通过Activity启动实现音乐播放能力的Service,已在AndroidManifest清单文件完成Service注册,但点击Activity界面上的启动按钮后无任何声音输出,相关Kotlin代码如下:

class MyService : Service() {
    lateinit var  mediaPlayer:MediaPlayer

    override fun onCreate() {
        super.onCreate()
        Log.i("Service","service Created")
        mediaPlayer=MediaPlayer.create(this,R.raw.music2)
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.i("Service","service Destroyed")
        if(mediaPlayer.isPlaying){
            mediaPlayer.stop()
            mediaPlayer.release()
        }
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        Log.i("Service","service Started")
        if(!mediaPlayer.isPlaying)
            mediaPlayer.start()
        return START_STICKY
    }

    override fun onBind(intent: Intent): IBinder {
        TODO("Return the communication channel to the service.")
    }
}

class MainActivity : AppCompatActivity() {
    lateinit var startBtn:Button
    lateinit var stopBtn:Button

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? {
        return super.onCreateView(name, context, attrs)
        Log.i("Service","activityCreated")
        startBtn=findViewById(R.id.startBtn)
        stopBtn=findViewById(R.id.stopBtn)
        startBtn.setOnClickListener {
        val intent=Intent(context,MyService::class.java)
            if(context!=null)
             context.startService(intent)
        }

        stopBtn.setOnClickListener {
            val intent=Intent(context,MyService::class.java)
            stopService(intent)
        }
    }
}
核心问题点
  • 按钮初始化、点击事件绑定代码属于永远不会执行的死代码:你把这部分逻辑写在了onCreateView方法内,且方法第一行就执行了return返回,后续代码没有任何执行机会。同时AppCompatActivity通过setContentView加载布局时,不会触发你重写的这个onCreateView回调来处理布局内控件,等于两个按钮从来没绑定过点击逻辑,点击自然不会触发Service启动。
  • Service的onBind方法存在崩溃隐患:Kotlin中TODO()函数会直接抛出NotImplementedError,即使你通过startService启动Service不走绑定逻辑,异常触发时也会导致Service直接崩溃,非绑定场景下该方法直接返回null即可。
  • MediaPlayer资源释放逻辑不严谨:当前仅当音频处于播放状态时才会执行stop和release操作,如果Service销毁时音频已经自然播放结束,MediaPlayer占用的资源不会被释放,后续重复启动Service容易出现状态异常。
修复方案
  1. 把控件初始化、点击事件绑定逻辑移到Activity的onCreate方法中,放在setContentView调用之后执行,删除无效的onCreateView重写逻辑。
  2. 修改Service的onBind方法,非绑定场景直接返回null。
  3. 补全MediaPlayer的释放逻辑,无论是否处于播放状态,Service销毁时都要释放资源。

修复后的完整代码:

class MyService : Service() {
    private lateinit var mediaPlayer: MediaPlayer

    override fun onCreate() {
        super.onCreate()
        Log.i("Service", "service Created")
        mediaPlayer = MediaPlayer.create(this, R.raw.music2)
        // 如需循环播放可打开下方配置
        // mediaPlayer.isLooping = true
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.i("Service", "service Destroyed")
        // 统一释放资源,无需额外判断播放状态
        mediaPlayer.stop()
        mediaPlayer.release()
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        Log.i("Service", "service Started")
        if (!mediaPlayer.isPlaying) {
            mediaPlayer.start()
        }
        return START_STICKY
    }

    override fun onBind(intent: Intent): IBinder? {
        // 非绑定启动模式直接返回null即可
        return null
    }
}

class MainActivity : AppCompatActivity() {
    private lateinit var startBtn: Button
    private lateinit var stopBtn: Button

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        Log.i("Service", "activityCreated")
        // 初始化控件、绑定点击事件
        startBtn = findViewById(R.id.startBtn)
        stopBtn = findViewById(R.id.stopBtn)

        startBtn.setOnClickListener {
            val intent = Intent(this, MyService::class.java)
            startService(intent)
        }

        stopBtn.setOnClickListener {
            val intent = Intent(this, MyService::class.java)
            stopService(intent)
        }
    }
}

补充说明:如果应用运行在Android 8.0(API 26)及以上版本,后台启动Service存在系统限制,建议使用startForegroundService启动前台Service,并在Service的onCreate中调用startForeground挂载常驻通知,否则Service可能无法正常启动。

内容的提问来源于stack exchange,提问作者Beginner developer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 04:21:15