Home > database >  Android Power Screen `Control` always takes the same intent
Android Power Screen `Control` always takes the same intent

Time:10-07

I am cooperating with TheLastProject@github on an app that works as a loyalty card wallet: Catima (link to my fork and to app listing)

I tried to implement Power screen cards and I followed the Android development guide on Device Controls

The resulting code is (this link could be invalidated during a rebase) has prblems

@NonNull
@Override
public Flow.Publisher<Control> createPublisherFor(@NonNull List<String> controlIds) {
    return subscriber -> {
        subscriber.onSubscribe(new NoOpSubscription());
        for (String controlId : controlIds) {
            Integer cardId = this.controlIdToCardId(controlId);
            if (cardId == null)
                continue;
            LoyaltyCard card = dbHelper.getLoyaltyCard(cardId);
            Intent openIntent = new Intent(this, LoyaltyCardViewActivity.class)
                    .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                    .putExtra("id", card.id);
            PendingIntent pendingIntent = PendingIntent.getActivity(getBaseContext(), 0, openIntent, PendingIntent.FLAG_IMMUTABLE);
            var ret = new Control.StatefulBuilder(controlId, pendingIntent)
                    .setTitle(card.store)
                    .setDeviceType(DeviceTypes.TYPE_GENERIC_OPEN_CLOSE)
                    .setSubtitle(card.note)
                    .setStatus(Control.STATUS_OK)
                    .setControlTemplate(new StatelessTemplate(controlId))
                    .setCustomIcon(Icon.createWithBitmap(Utils.generateIcon(this, card.store, card.headerColor).getLetterTile()))
                    .build();
            Log.d(TAG, "Dispatching widget "   controlId);
            subscriber.onNext(ret);
        }
        subscriber.onComplete();
    };
}

Code design

Loyalty cards are identified by an integer. I have generated unique control IDs based on that integer, so that I can query them. As told me by the Maintainer, LoyaltyCardViewActivity is the view that can be used to display a loyalty card, and the intent looks genuine.

So for each card in the input, I iterate and reactively emit a new Control for each card. Each control has its own intent and every intent is bound to the card ID.

Problem

The problem is that when I long-press on the widget, the intent emitted by Android carries the same card ID, which means that no matter I select different widgets, the same (not so deterministic) card is displayed.

"Not so deterministic". When I remove all controls and add them again, I can't predict which card is displayed. But every time I open the power menu again I get the same card.

In Android studio I debugged and I see the very same card ID passed to LoyaltyCardViewActivity, despite when I create the Control object I can clearly debug that the intent carries always a different ID

How to reproduce

Works on the emulator. I used a dump of real loyalty cards and an EU digital green certificate. But one could create two or more barcode cards by inputting random numbers.

Question

What's wrong with my code?

CodePudding user response:

PendingIntent pendingIntent = PendingIntent.getActivity(getBaseContext(), 0, openIntent, PendingIntent.FLAG_IMMUTABLE);

You are calling this N times, and so my guess is that you expect that you are creating N distinct PendingIntent objects. In reality, you are only creating one, because your PendingIntent identifier is the same for all of them: 0.

Change this to be something more like:

PendingIntent pendingIntent = PendingIntent.getActivity(this, cardId, openIntent, PendingIntent.FLAG_IMMUTABLE);

(I am guessing that cardId is unique for all your cards)

  • Related