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?