IllegalArgumentException in kotlin while trying to build audio plaback capture recorder - "Unknown mixing rule type"

Viewed 27

I'm trying to make an app that records the audio being played on your device and ran into an error while generating the audio record object required for it.

I have tried what I could find on the internet but the problem has not been resolved and there also seems to be very little documentation on the topic.

Here's my code:

class AudioPlaybackRecorderService : Service() {
    private lateinit var notificationManager: NotificationManager
    private lateinit var notificationChannel: NotificationChannel
    private lateinit var notification: Notification

    private lateinit var mediaProjectionManager: MediaProjectionManager;
    private lateinit var audioPlaybackCapConfig: AudioPlaybackCaptureConfiguration
    private lateinit var audioFormat: AudioFormat
    private lateinit var audioRecord: AudioRecord

    @RequiresApi(Build.VERSION_CODES.R)
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {

        notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        notificationChannel = NotificationChannel("foregroundNotificationChannel", "foreNifChannel", NotificationManager.IMPORTANCE_HIGH)
        notificationManager.createNotificationChannel(notificationChannel)

        notification = NotificationCompat.Builder(this, notificationChannel.id)
            .setSmallIcon(R.mipmap.ic_launcher_round)
            .setContentTitle("Usb Audio")
            .setContentText("App running in foreground")
            .build()

        startForeground(startId, notification, FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION)


        mediaProjectionManager = getSystemService(MEDIA_PROJECTION_SERVICE) as MediaProjectionManager

        audioPlaybackCapConfig = AudioPlaybackCaptureConfiguration.Builder(mediaProjectionManager.getMediaProjection(
            intent!!.getIntExtra("resCode", 120),
            intent!!.extras!!["data"] as Intent
        )).build()

        audioFormat = AudioFormat.Builder()
            .setEncoding(AudioFormat.ENCODING_MP3)
            .setSampleRate(44100)
            .setChannelMask(AudioFormat.CHANNEL_IN_MONO)
            .build()

        if(ContextCompat.checkSelfPermission(this,
                "android.permission.RECORD_AUDIO") == PackageManager.PERMISSION_GRANTED)
        {
            audioRecord = AudioRecord.Builder()
                .setAudioPlaybackCaptureConfig(audioPlaybackCapConfig)
                .setAudioFormat(audioFormat)
                .setBufferSizeInBytes(20)
                .build()
        }


        return super.onStartCommand(intent, flags, startId)
    }


    override fun onBind(intent: Intent): IBinder? {
        return null
    }
}

I'm passing the data to the service like this:

    val serviceIntent = Intent(this, AudioPlaybackRecorderService::class.java)
                        serviceIntent.putExtra("resCode", resultCode)
                        serviceIntent.putExtra("data", data)
                        startService(serviceIntent)

And here's the stack trace:

java.lang.RuntimeException: Unable to start service com.example.usbaudio.AudioPlaybackRecorderService@11bcb6e with Intent { cmp=com.example.usbaudio/.AudioPlaybackRecorderService (has extras) }: java.lang.IllegalArgumentException: Unknown mixing rule type
    at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4339)
    at android.app.ActivityThread.access$1800(ActivityThread.java:238)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1952)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:223)
    at android.app.ActivityThread.main(ActivityThread.java:7700)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:952)
 Caused by: java.lang.IllegalArgumentException: Unknown mixing rule type
    at android.media.audiopolicy.AudioMix$Builder.build(AudioMix.java:448)
    at android.media.AudioPlaybackCaptureConfiguration.createAudioMix(AudioPlaybackCaptureConfiguration.java:135)
    at android.media.AudioRecord$Builder.buildAudioPlaybackCaptureRecord(AudioRecord.java:688)
    at android.media.AudioRecord$Builder.build(AudioRecord.java:716)
    at com.example.usbaudio.AudioPlaybackRecorderService.onStartCommand(AudioPlaybackRecorderService.kt:66)
    at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4321)
    at android.app.ActivityThread.access$1800(ActivityThread.java:238) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1952) 
    at android.os.Handler.dispatchMessage(Handler.java:106) 
    at android.os.Looper.loop(Looper.java:223) 
    at android.app.ActivityThread.main(ActivityThread.java:7700) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:952) 

Thanks in advance to anyone who can help!

1 Answers

You are not calling addMatchingUsage or excludeUsage on the AudioPlaybackCaptureConfiguration object. This is described here. Use something like

AudioPlaybackCaptureConfiguration.Builder(mediaProjectionManager.getMediaProjection(
        intent!!.getIntExtra("resCode", 120),
        intent!!.extras!!["data"] as Intent
    )).addMatchingUsage(AudioAttributes.USAGE_MEDIA).build()
Related