Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >com.example.spotifyclone.exoplayer.MusicService: java.lang.RuntimeException:无法创建服务java.lang.IllegalArgumentException

com.example.spotifyclone.exoplayer.MusicService: java.lang.RuntimeException:无法创建服务java.lang.IllegalArgumentException
EN

Stack Overflow用户
提问于 2022-08-12 09:11:29
回答 1查看 182关注 0票数 0

我已经在我的spotifyclone应用程序中实现了音乐服务,但是当我运行项目时,我得到了以下异常

代码语言:javascript
运行
AI代码解释
复制
java.lang.RuntimeException: Unable to create service com.example.spotifyclone.exoplayer.MusicService: java.lang.IllegalArgumentException
 at android.app.ActivityThread.handleCreateService(ActivityThread.java:3610)
 at android.app.ActivityThread.access$1500(ActivityThread.java:206)
 at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1716)
 at android.os.Handler.dispatchMessage(Handler.java:106)
 at android.os.Looper.loop(Looper.java:201)
 at android.app.ActivityThread.main(ActivityThread.java:6820)
 at java.lang.reflect.Method.invoke(Native Method)
 at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:922)
Caused by: java.lang.IllegalArgumentException
 at com.google.android.exoplayer2.util.Assertions.checkArgument(Assertions.java:39)
 at com.google.android.exoplayer2.ui.PlayerNotificationManager$Builder.<init>(PlayerNotificationManager.java:353)
 at com.example.spotifyclone.exoplayer.MusicNotificationManager.<init>(MusicNotificationManager.kt:33)
 at com.example.spotifyclone.exoplayer.MusicService.onCreate(MusicService.kt:71)
 at android.app.ActivityThread.handleCreateService(ActivityThread.java:3598)

低于我的MusicService.kt

代码语言:javascript
运行
AI代码解释
复制
import android.app.PendingIntent
import android.content.Intent
import android.os.Bundle
import android.support.v4.media.MediaBrowserCompat
import android.support.v4.media.MediaDescriptionCompat
import android.support.v4.media.MediaMetadataCompat
import android.support.v4.media.session.MediaSessionCompat
import androidx.media.MediaBrowserServiceCompat
import com.example.spotifyclone.exoplayer.callbacks.MusicPlaybackPreparer
import com.example.spotifyclone.exoplayer.callbacks.MusicPlayerEventListener
import com.example.spotifyclone.exoplayer.callbacks.MusicPlayerNotificationListener
import com.example.spotifyclone.other.Constants.MEDIA_ROOT_ID
import com.example.spotifyclone.other.Constants.NETWORK_ERROR
import com.google.android.exoplayer2.ExoPlayer
import com.google.android.exoplayer2.Player
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector
import com.google.android.exoplayer2.ext.mediasession.TimelineQueueNavigator
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.*
import javax.inject.Inject

private const val SERVICE_TAG = "MusicService"


@AndroidEntryPoint
class MusicService : MediaBrowserServiceCompat() {

    @Inject
    lateinit var dataSourceFactory: DefaultDataSourceFactory

    @Inject
    lateinit var exoPlayer: ExoPlayer

    @Inject
    lateinit var firebaseMusicSource: FirebaseMusicSource

    private val serviceJob = Job()
    private val serviceScope = CoroutineScope(Dispatchers.Main + serviceJob)

    private lateinit var mediaSession: MediaSessionCompat
    private lateinit var mediaSessionConnector: MediaSessionConnector
    var isForegroundService = false
    private var curPlayingSong: MediaMetadataCompat? = null
    private lateinit var musicNotificationManager: MusicNotificationManager
    private var isPlayerInitialized = false
    private lateinit var musicPlayerEventListener: MusicPlayerEventListener

    companion object {
        var curSongDuration = 0L
            private set
    }

    override fun onCreate() {
        super.onCreate()
        serviceScope.launch {
            firebaseMusicSource.fetchMediaData()
        }
        val activityIntent = packageManager?.getLaunchIntentForPackage(packageName)?.let {
            PendingIntent.getActivity(this, 0, it, 0)
        }

        mediaSession = MediaSessionCompat(this, SERVICE_TAG).apply {
            setSessionActivity(activityIntent)
            isActive = true
        }

        sessionToken = mediaSession.sessionToken
        musicNotificationManager = MusicNotificationManager(
            this,
            mediaSession.sessionToken,
            MusicPlayerNotificationListener(this)
        ) {
            curSongDuration = exoPlayer.duration
        }

        val musicPlaybackPreparer = MusicPlaybackPreparer(firebaseMusicSource) {
            curPlayingSong = it
            preparePlayer(
                firebaseMusicSource.songs,
                it,
                true
            )
        }
        mediaSessionConnector = MediaSessionConnector(mediaSession)
        mediaSessionConnector.setPlaybackPreparer(musicPlaybackPreparer)
        mediaSessionConnector.setQueueNavigator(MusicQueueNavigator())
        mediaSessionConnector.setPlayer(exoPlayer)
        musicPlayerEventListener = MusicPlayerEventListener(this)
        exoPlayer.addListener(musicPlayerEventListener)
        musicNotificationManager.showNotification(exoPlayer)
    }

    private inner class MusicQueueNavigator : TimelineQueueNavigator(mediaSession) {
        override fun getMediaDescription(player: Player, windowIndex: Int): MediaDescriptionCompat {
            return firebaseMusicSource.songs[windowIndex].description
        }

    }

    private fun preparePlayer(
        songs: List<MediaMetadataCompat>,
        itemToPlay: MediaMetadataCompat?,
        playNow: Boolean

    ) {
        val curSongIndex = if (curPlayingSong == null) 0 else songs.indexOf(itemToPlay)
        exoPlayer.setMediaSource(firebaseMusicSource.asMediaSource(dataSourceFactory))
        exoPlayer.prepare()
        exoPlayer.seekTo(curSongIndex, 0L)
        exoPlayer.playWhenReady = playNow

    }

    override fun onTaskRemoved(rootIntent: Intent?) {
        super.onTaskRemoved(rootIntent)
        exoPlayer.stop()
    }

    override fun onDestroy() {
        super.onDestroy()
        serviceScope.cancel()
        exoPlayer.removeListener(musicPlayerEventListener)
        exoPlayer.release()
    }

    override fun onGetRoot(
        clientPackageName: String,
        clientUid: Int,
        rootHints: Bundle?
    ): BrowserRoot? {
        return BrowserRoot(MEDIA_ROOT_ID, null)
    }

    override fun onLoadChildren(
        parentId: String,
        result: Result<MutableList<MediaBrowserCompat.MediaItem>>
    ) {
        when (parentId) {
            MEDIA_ROOT_ID -> {
                val resultsSent = firebaseMusicSource.whenReady { isInitialized ->
                    if (isPlayerInitialized) {
                        result.sendResult(firebaseMusicSource.asMediaItems())
                        if (!isInitialized && firebaseMusicSource.songs.isNotEmpty()) {
                            preparePlayer(
                                firebaseMusicSource.songs,
                                firebaseMusicSource.songs[0],
                                false
                            )
                            isPlayerInitialized = true
                        }
                    } else {
                        mediaSession.sendSessionEvent(NETWORK_ERROR, null)
                        result.sendResult(null)

                    }

                }
                if (!resultsSent) {
                    result.detach()
                }
            }
        }
    }
}

低于我的AndroidManifest.xml

代码语言:javascript
运行
AI代码解释
复制
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.spotifyclone">


    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

    <application
        android:name=".SpotifyApplication"
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.SpotifyClone"
        tools:targetApi="31">
        <service android:name="com.example.spotifyclone.exoplayer.MusicService"
            android:exported="false">
            <intent-filter>
                <action android:name="android.media.browse.MediaBrowserService" />
            </intent-filter>
        </service>
        <activity
            android:name=".ui.MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

低于MusicNotificationManager.kt

代码语言:javascript
运行
AI代码解释
复制
@SuppressLint("Range")
class MusicNotificationManager(
    private val context:Context,
    sessionToken:MediaSessionCompat.Token,
    notificationListener:PlayerNotificationManager.NotificationListener,
    private val newSongCallback:() -> Unit

) {
    private val notificationManager: PlayerNotificationManager

    init {
        val mediaController = MediaControllerCompat(context, sessionToken)

        notificationManager = PlayerNotificationManager.Builder(
            context,
            NOTIFICATION_ID, NOTIFICATION_CHANNEL_ID

        )
            .setChannelNameResourceId(R.string.notification_channel_name)
            .setChannelDescriptionResourceId(R.string.notification_channel_description)
            .setMediaDescriptionAdapter(DescriptionAdapter(mediaController))
            .setNotificationListener(notificationListener)
            .setSmallIconResourceId(R.drawable.ic_music)
            .build()

    }

    fun showNotification(player: Player) {
        notificationManager.setPlayer(player)
    }

    private inner class DescriptionAdapter(
        private val mediaController: MediaControllerCompat
    ) : PlayerNotificationManager.MediaDescriptionAdapter {

        override fun getCurrentContentTitle(player: Player): CharSequence {
            return mediaController.metadata.description.title.toString()
        }

        override fun createCurrentContentIntent(player: Player): PendingIntent? {
            return mediaController.sessionActivity
        }

        override fun getCurrentContentText(player: Player): CharSequence? {
            return mediaController.metadata.description.subtitle.toString()
        }

        override fun getCurrentLargeIcon(
            player: Player,
            callback: PlayerNotificationManager.BitmapCallback
        ): Bitmap? {
            Glide.with(context).asBitmap()
                .load(mediaController.metadata.description.iconUri)
                .into(object : CustomTarget<Bitmap>() {
                    override fun onResourceReady(
                        resource: Bitmap,
                        transition: Transition<in Bitmap>?
                    ) {
                        callback.onBitmap(resource)
                    }

                    override fun onLoadCleared(placeholder: Drawable?) = Unit
                })
            return null
        }
    }
}

我所做的,重建,失效,缓存和重新启动,并遵循所有的堆栈溢出的答案,我想知道我到底在哪里犯了错误,我必须做的是避免在我的应用程序崩溃。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-08-13 01:18:26

堆栈跟踪在源代码中提到了PlayerNotificationManager第353行

代码语言:javascript
运行
AI代码解释
复制
at com.google.android.exoplayer2.ui.PlayerNotificationManager$Builder.<init>(PlayerNotificationManager.java:353)

这正是这一行(您可以在github上找到源代码):

代码语言:javascript
运行
AI代码解释
复制
checkArgument(notificationId > 0);

如您所见,库将检查所传递的NOTIFICATION_ID是否大于0。解决方案是将NOTIFICATION_ID的定义更改为大于0的整数。祝你好运

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73337662

复制
相关文章
如何平滑等值线
因为种种原因,使用MATLAB绘图时,可能会导致等值线出现锯齿,这样画出来的图就会显得不美观。本文就介绍一下,如何平滑等值线。
bugsuse
2020/04/21
3.6K0
如何平滑等值线
geotools等值线生成
前文中,提到了等值面的生成,后面有人经常会问等值线的生成,本文在前文的基础上做了一点修改,完成了等值线的geotools生成。
牛老师讲GIS
2018/10/23
2.8K0
geotools等值线生成
Shader初学笔记:等值线
http://www.cnblogs.com/lpcoder/p/7103634.html
clawclaw
2018/03/26
1.8K5
Shader初学笔记:等值线
【python】气象绘图—等值线
本节提要:关于等值线的一些操作,解决等值线标签无法正常显示的问题,等值线填色图的阴影操作。
自学气象人
2023/06/20
2.2K0
【python】气象绘图—等值线
Python兰伯特投影中国区域等值线图(含南海小地图)
自定义兰伯特投影: 原作者:“坎坷”大佬 PlateCarree (无坐标转换)作图: 代码调试作者:气象水文科研猫 注:因小编时间有限,代码未进行精简。 import numpy as np i
bugsuse
2021/01/04
7.5K1
Python兰伯特投影中国区域等值线图(含南海小地图)
等值线算法「建议收藏」
大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。 Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺
全栈程序员站长
2022/09/20
8740
等值线算法「建议收藏」
Python 空间绘图 - 等值线绘制
等值线是气象上比较常用的一种图形,特别是分析天气形势时,常用的地面气压、位势高度、气温等以等值线展示效果最好;在某些时候,我们还需要对等值线填色图进行进一步的美化。兹分别介绍之。
DataCharm
2021/02/22
6.1K2
Python 空间绘图 - 等值线绘制
使用Python制作3个简易地图
在处理地理空间数据时,经常需要以最自然的方式可视化这些数据:地图。如果可以使用Python快速轻松地创建数据的交互式地图,在本教程中使用洛杉矶县所有星巴克位置的数据集。在文章的最后将能够创建:
代码医生工作室
2019/06/21
4.3K0
使用Python制作3个简易地图
图像处理常用插值方法总结
在做数字图像处理时,经常会碰到小数象素坐标的取值问题,这时就需要依据邻近象素的值来对该坐标进行插值。比如:做地图投影转换,对目标图像的一个象素进行坐标变换到源图像上对应的点时,变换出来的对应的坐标是一个小数,再比如做图像的几何校正,也会碰到同样的问题。以下是对常用的三种数字图像插值方法进行介绍。 1、最邻近元法   这是最简单的一种插值方法,不需要计算,在待求象素的四邻象素中,将距离待求象素最近的邻象素灰度赋给待求象素。设i+u, j+v(i, j为正整数, u, v为大于零小于1的小数,下同)为待求象素坐
智能算法
2018/04/03
4K0
图像处理常用插值方法总结
Python气象绘图教程特刊(二)等值线
在气象研究领域,限制于世界的地貌和人文地理,大部分的气象原始资料是站点分布的。气象站的分布的特点是北多南少(有闲钱建设气象站的国家基本在北半球,陆地基本集中于北半球,世界人口集中于北半球),陆多海少(陆地易于永久和半永久观测站建设,海上的漂浮测站和轮船的观测不稳定)。中国的气象站密度基本与人口密度的漠河-腾冲县线吻合,表现在东多西少,中间多南北少(河北县级气象局的密度比长江以南任何一个省都高,中原地区又高于其他地区,这些牵扯到历史自然地理和人文地理)。
气象学家
2020/06/17
7.7K0
C程序中的raise和kill两个函数有何不同?
在多线程程序中,进程给自己发SIGTERM信号退出,应当调用“kill(getpid(), SIGTERM)”,而不是“raise(SIGTERM)”。
一见
2020/02/13
1.7K0
R可视乎|等高线图
等高线图(contour map) 是可视化二维空间标量场的基本方法[1],可以将三维数据使用二维的方法可视化,同时用颜色视觉特征表示第三维数据,如地图上的等高线、天气预报中的等压线和等温线等。假设
庄闪闪
2021/04/09
4.6K0
numpy简单应用---等值线(多边形)平滑
风向条件下的气体扩散模型计算得到的数据,相当于等值线需要在地图上展示。如下图,可以看到,离中心最近的多边形毛糙锯齿严重。
MiaoGIS
2020/11/04
1.4K0
numpy简单应用---等值线(多边形)平滑
Shader初学笔记:一种三维等值线的算法
把反距离加权算法转换到三维空间,是不是很方便的算出三维空间下的等值线了呢,再结合Shatter Toolkit插件进行剖切,修改修改代码。应该可以解决地层模型任意剖切后,切面的等值线渲染问题了。先写个思路,代码有空再补上。(发现发表文章还不能少于140字!先写个三维的反距离加权算法。)
clawclaw
2018/03/30
1.2K8
LeetCode,给定一个链表,判断链表中是否有环
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
微客鸟窝
2021/08/18
6600
LeetCode,给定一个链表,判断链表中是否有环
2021-10-08:填充每个节点的下一个右侧节点指针。给定一个
2021-10-08:填充每个节点的下一个右侧节点指针。给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点。填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。初始状态下,所有 next 指针都被设置为 NULL。进阶:你只能使用常量级额外空间。使用递归解题也符合要求,本题中递归程序占用的栈空间不算做额外的空间复杂度。力扣116。
福大大架构师每日一题
2021/10/08
3090
[android] 在不同的activity之间传递数据
添加<TextView/>控件,设置控件内容水平居中,android:gravity=”center_horizontal”
唯一Chat
2019/09/10
2.4K0
[android] 在不同的activity之间传递数据
2021-11-06:3的幂。给定一个整数,写一个函数来判断它是
2021-11-06:3的幂。给定一个整数,写一个函数来判断它是否是 3 的幂次方。如果是,返回 true ;否则,返回 false 。整数 n 是 3 的幂次方需满足:存在整数 x 使得 n == 3**x。力扣326。
福大大架构师每日一题
2021/11/06
3750
绘图系列(1):利用matplotlib绘制等值线图
绘图系列是为了给出一些图形绘制示例,便于快速绘制一些图形。此系列不受所用语言和工具的限制,可能会使用 python,matlab,ncl,idl以及其它一些语言或是工具。
bugsuse
2020/04/21
2.7K0
绘图系列(1):利用matplotlib绘制等值线图
点击加载更多

相似问题

R中的填充等值线图/等值线

12

如何用openCV区域指定的颜色填充等值线?

12

在等值线中查找等值线

25

R中函数的等值线

27

Python中的等值线标注

11
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档