Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are Bubbles appearing as normal Notifications?

I've been experimenting with the new Bubbles API recently. No matter what I do, the notifications that I expect to appear as a bubble always appear in the system tray as a normal notification.

I've written my own toy app, which I'll add here. I have also pulled down a couple of other apps from tutorials (here and here) that I have studied. In every single case, no bubble, just a system tray notification.

Since the sample apps assert that they can present bubbles, I assume that the problem must be somewhere in my emulator environment. I'm running an emulator that uses Android API R. And I have enabled bubbles in the developer options:

enter image description here

Here is the relevant code from the app that I have developed:

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.bubbles">

    <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/AppTheme">
        <activity
            android:name=".BubbleActivity"
            android:allowEmbedded="true"
            android:documentLaunchMode="always"
            android:resizeableActivity="true" />
        <activity
            android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>

MainActivity.kt

import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModelProvider

class MainActivity : AppCompatActivity() {

    private lateinit var bubbleViewModel: BubbleViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        bubbleViewModel = ViewModelProvider(
            this, BubbleViewModelFactory(this.application))
            .get(BubbleViewModel::class.java)
    }

    fun blowBubble(view: View) {
        bubbleViewModel.showBubble()
    }
}

BubbleViewModel.kt

class BubbleViewModel(application: Application): AndroidViewModel(application) {

    private val notificationHelper = NotificationHelper(getApplication())

    init {
        notificationHelper.createNotificationChannels()
    }

    fun showBubble() {
        viewModelScope.launch{
            withContext(Dispatchers.Main) {
                with (notificationHelper) {
                    if (canBubble())
                        showNotification()
                }
            }
        }
    }
}

NotificationHelper.kt

class NotificationHelper(private val context: Context) {

    private val notificationManager = context.getSystemService(NotificationManager::class.java)
    private lateinit var channel: NotificationChannel

    fun createNotificationChannels() {

        channel = NotificationChannel(
            CHANNEL_NEW_MESSAGES,
            context.getString(R.string.channel_name),
            NotificationManager.IMPORTANCE_HIGH)

        with(channel) {
            enableVibration(true)
            lockscreenVisibility = NotificationCompat.VISIBILITY_PUBLIC
            description = context.getString(R.string.channel_description)
            setAllowBubbles(true)
        }

        Log.d("bubble", "Can Bubble: $channel.canBubble()")
        notificationManager?.let {
            it.createNotificationChannel(channel)
        }
    }

    @WorkerThread
    fun showNotification() {

        val bubbleIntent = PendingIntent.getActivity(
            context,
            REQUEST_BUBBLE,
            Intent(context, BubbleActivity::class.java).setAction(Intent.ACTION_VIEW),
            PendingIntent.FLAG_UPDATE_CURRENT)

        val bubbleMetaData = Notification.BubbleMetadata.Builder()
            .setDesiredHeight(600)
            .createIntentBubble(bubbleIntent, Icon.createWithResource(context, R.drawable.baseball))
            .setAutoExpandBubble(false)
            .setSuppressNotification(false)
            .build()

        val person = Person.Builder()
            .setIcon(Icon.createWithResource(context, R.drawable.baseball))
            .setName("Bubbles...")
            .setImportant(true)
            .build()

        val style = Notification.MessagingStyle(person)
            .addMessage("...are the Best!", System.currentTimeMillis(), person)

        val builder = Notification.Builder(context, CHANNEL_NEW_MESSAGES)
            .setBubbleMetadata(bubbleMetaData)
            .setContentIntent(bubbleIntent)
//            .setContentTitle("Title")
//            .setContentText("Hello this is a notification")
            .setSmallIcon(R.drawable.baseball)
            .setShowWhen(true)
            .setAutoCancel(true)
            .setStyle(style)
//            .addPerson(person.uri)


        notificationManager?.notify(0, builder.build())
    }

    fun canBubble(): Boolean {
        notificationManager?.let {
            val channel = it.getNotificationChannel(CHANNEL_NEW_MESSAGES)
            return it.areBubblesAllowed() && channel.canBubble()
        }
        return false
    }

    companion object {
        private const val CHANNEL_NEW_MESSAGES = "new_messages"
        const val REQUEST_BUBBLE = 2
    }
}

And finally, the destination activity, which I don't think really matters too much since it only fires if the bubble were available to click: BubbleActivity.kt

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity

class BubbleActivity : AppCompatActivity() {

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

And that's really all there is to this. But when run this and click the button to display a bubble, I get this result:

enter image description here

like image 562
AndroidDev Avatar asked Mar 05 '20 20:03

AndroidDev


Video Answer


1 Answers

@AndroidDev your code works fine in API level 29 and shows the notifications as bubbles but it does not work in Android R. I guess you should not worry about that as it is in preview stage and definitely not stable.

So if you run your code in an emulator with API level 29, it should work fine.

This issue is a regression from Android 10 and is reported here

like image 159
Niladree Avatar answered Oct 03 '22 23:10

Niladree