Android intents to launch music app on phone

Posted on
  • Hi!

    I've started experimenting with android intents as a means to start music and podcast apps on my phone. I've found and tested this to start spotify from Tasker:

    Action:android.intent.action.VIEW
    Cat:Default
    Data:spotify:track:7lD7gxCk2Pt4lUmCZSWiM­Y [Differs from the forum post above]
    Package:com.spotify.music
    Target:Activity

    Now I want to send an intent with these contents from Gadgetbridge (bangle.js flavor) instead, initiated on my bangle.js 2.

    From looking at the code on codeberg (gfwilliams/Gadgetbridge) it seems I cannot specify all the contents above in the way I need to. I think.

    I've written a small Bangle.js 2 app to send intent contents to gadgetbridge:

    function touchHandler() { Bluetooth.println(JSON.stringify({t:"int­ent", action:"android.intent.action.VIEW", category:"android.intent.category.DEFAUL­T", "package":"com.spotify.music", data:"spotify:track:7lD7gxCk2Pt4lUmCZSWi­MY", target:"Action", extra:{key1:"asdfas"}}));
                            }
    g.clear();
    
    Bangle.setUI({
      mode: 'custom',
      back: () => {load();},
      touch: touchHandler
    });
    

    But Gadgetbridge only handles the "action" and "extra" keys.

    So I have had a try at adding code to gadgetbridge, for adding the contents I need to the intent:

    case "intent": {
        Prefs devicePrefs = new Prefs(GBApplication.getDeviceSpecificSha­redPrefs(gbDevice.getAddress()));
        if (devicePrefs.getBoolean(PREF_DEVICE_INTE­NTS, false)) {
            String action = json.getString("action"); // Sending form Bangle, action:"android.intent.action.VIEW".
            JSONObject extra = json.getJSONObject("extra");
            Intent in = new Intent();
            in.setAction(action);
            
            // MY CODE STARTS HERE
            
            String data = json.getString("data"); // Sending from Bangle, data:"spotify:track:7lD7gxCk2Pt4lUmCZSWi­MY".
            String category = json.getString("category"); // Sending from Bangle, category:"android.intent.category.DEFAUL­T".
            String pkge = json.getString("package"); // Sending from Bangle, package:"com.spotify.music".
            String target = json.getString("target"); // Sending from Bangle, target:"Activity".
            
            in.setData(data);
            in.addCategory(category);
            in.setPackage(pkge);
            in.setTarget(target); // THIS IS PROBABLY WRONG - haven't found how to add "Activity" as target.
            
            //MY CODE ENDS HERE
            
            if (extra != null) {
                Iterator<String> iter = extra.keys();
                while (iter.hasNext()) {
                    String key = iter.next();
                    in.putExtra(key, extra.getString(key));
                }
            }
            LOG.info("Sending intent " + action);
            this.getContext().getApplicationContext(­).sendBroadcast(in);
        } else {
            uartTxJSONError("intent", "Android Intents not enabled, check Gadgetbridge Device Settings");
        }
    }
    default : {
        LOG.info("UART RX JSON packet type '"+packetType+"' not understood.");
    }
    

    I think I have found the correct methods to add data, category and package information. What I haven't managed to find is how to set/add/specify a target, in my case to "Activity".

    Does anyone know how target information is added to an intent? In Tasker it's just a dropdown menu and I haven't found the java-code behind it.

    Also, if I have misinterpreted and I can achieve what I want without changing Gadgetbridge java-code please tell - that would be great! :P

    I might try building gadgetbridge with the above changes. If I get it to work then I'll create an account and do a PR on codeberg. Although, a PR should probably introduce more general functionality than the specific one I'm after... I'll see if I'm up for it.

    Thanks in advance!

    EDIT:
    I might have found what I need here. Instead of adding target information (Activity) to the intent it seems I should do something like:

    startActivity(in);
    

    instead of

    in.setTarget(target); // THIS IS PROBABLY WRONG - haven't found how to add "Activity" as target.
    .
    .
    .
    this.getContext().getApplicationContext(­).sendBroadcast(in);
    

    maybe?

    Search tags: android, gadgetbridge, intent, intents, android intent, android intents, gadgetbridge intent, gadgetbridge intents, bluetooth.

  • I'm afraid I'm not sure how you'd do it myself, but it does sound as if you can't do it with Gadgetbridge as-is right now, and you would need some changes. One thing to watch out for is to make sure it'll still work when things like package/etc aren't supplied.

    If you get this working, a PR for it would be great though!

    Another option is you mention Tasker - I think you could make Tasker respond to an intent from Gadgetbridge, and then send out a new intent with all the info filled in?

  • Ok, thanks! :) I'll probably try to modify Gadgetbridge and possibly do a PR after that then.

  • Hi again @Gordon!
    I just opened a PR on codeberg. It works for opening spotify and playing a song like I wanted in the opening post. I've tried to make it reliable and useful for general use as well. I have not managed to implement targeting of background services yet, but I don't think it should be impossible.

    One thing to watch out for is to make sure it'll still work when things like package/etc aren't supplied.

    I think I've managed that.

    I've been testing my changes to Gadgetbridge with the Bangle.js 2 app attached to this reply. I've attached a gadgetbridge apk with the changes as well.

    testintents.app.js code:

    function leftTouch() { Bluetooth.println(JSON.stringify({t:"int­ent", action:"android.intent.action.VIEW", category:"android.intent.category.DEFAUL­T", package:"com.spotify.music", data:"spotify:track:7lD7gxCk2Pt4lUmCZSWi­MY", target:"Activity", extra:{key1:"asdfas"}}));
    }
    
    function middleTouch() { Bluetooth.println(JSON.stringify({t:"int­ent", action:"android.intent.action.VIEW", category:"android.intent.category.DEFAUL­T", class:"com.spotify.music", data:"spotify:track:7lD7gxCk2Pt4lUmCZSWi­MY", target:"Service", extra:{key1:"asdfas"}}));
    }
    
    function rightTouch() {
      Bluetooth.println(JSON.stringify({t:"int­ent",action:"com.junkbulk.amazfitbipbutt­onmaster.A",extra:{key1:"asdfas"}}));
    }
    
    function touchHandler(button, xy) {
    if (xy.x < Bangle.appRect.w / 3) {leftTouch();}
      else if (xy.x < Bangle.appRect.w * 2 / 3) {middleTouch();}
      else {rightTouch();}
    }
    
    g.clear();
    
    Bangle.setUI({
      mode: 'custom',
      back: () => {load();},
      touch: touchHandler
    });
    

    3 Attachments

  • Great, thanks! I just replied in that PR but this looks really good

  • I'm having problems getting startActivity() to work reliably independent of what's going on on the phone (what app is in the foreground). If anyone has knowledge of intents and could help out or give some insight, please check the PR. :)

  • I was asked this,

    @Ganblejs, how would I go about trying this? Can you please give some example of how I could test it (besides looking at the code)?
    Thank you.

    , in the comments on the PR and don't really have a good answer.

    @Gordon do you have a suggestion?

    I'm trying to understand the UART-handling to maybe be able to suggest a way to test the code without a bangle.

    EDIT: Maybe I could introduce a function testIntentsFunctionality() to the code that lets one input a string "lineDebug" to pass to "handleUartRxLine()". Making this new function reachable from inside the app would make testing possible w/o a bangle. I think.

    EDIT2: But I guess I have to fake a connection to a bangle to have the app access the code in the first place...

  • I think vanous may actually have a Bangle? So really he's just asking for some example code to run on the Bangle - which should be pretty easy to give him?

  • Ah, thanks, I'll do that then.

  • Great - thanks! I'll see about getting a new play store release out

  • Follow up PR to further extend intents functionality. If anyone can help with some insight on what I'm trying to achieve please do! :)

  • The follow up PR was just merged as well.

    The code is present in the Gadgetbridge nightlies.

    EDIT: To test this out you can load my intents test app or an initial version of a spotify remote app.

    And here are updated instructions regarding intents and Gadgetbridge.

  • Great, thanks for all your work on this! The changes to the docs help a huge amount too - very often stuff gets added and then nobody knows how to use it :)

  • Yeah, this grew a bit while working it out - scope creep is a real thing I guess 😛. But I've learnt a lot and it felt worthwhile to add as much functionality as possible when I already got going. Hopefully someone other than me will end up using it 😅.

    I feel like this is pretty much done now. But if anyone has questions or suggestions for improving intents functionality going forward I'd be happy to at least give some input or potentially implement stuff myself.

    (edit: One thing on my radar is handling of service-intents maybe will have to be done differently in the future, with workmanager instead. But I had a hard time wrapping my head around that..)

    And thanks for your help on this as well!

  • Amazing app, thanks for developing it!

  • Thank you! 😊

    Did you see it's on the official app loader now as well?

  • Yes, that is where I found it.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Android intents to launch music app on phone

Posted by Avatar for Ganblejs @Ganblejs

Actions