Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

startApp not finding other app even though its installed #148

Open
rolinger opened this issue Sep 2, 2020 · 5 comments
Open

startApp not finding other app even though its installed #148

rolinger opened this issue Sep 2, 2020 · 5 comments

Comments

@rolinger
Copy link

rolinger commented Sep 2, 2020

I have two apps I am designing.

I want a button in the primary app to call a the secondary app.

In the secondary app I installed cordova-plugin-customurlscheme and defined the app name as: mySecondaryApp
and added `<allow-intent href="mySecondaryApp: />

But the button in the primary app can't find the secondary app name mySecondaryApp

I know the startApp does work though because the Primary app is opening other apps like Uber, FB etc.

@lampaa
Copy link
Owner

lampaa commented Sep 3, 2020

Hi, @rolinger!

You can call you app by package name, exam:

var sApp = startApp.set({
	"application":"com.application.name"
}).start();

@rolinger
Copy link
Author

rolinger commented Sep 3, 2020

Hi @lampaa -

I first use to determine if the app is available on the device:

  var v = { scheme: "mySecondaryApp://" ; } // iOS
  var v = { scheme: "com.mySecondaryApp" ; }  // android

  appAvailability.check(
    v.scheme,
    function() {  // success callback
      hasAppSuccess(v,params,urlInfo,schemeType) ;
    }, function () {  // Error callback
      hasAppFail(v) ;
    }
  );

function hasAppSuccess(v,params,urlInfo,schemeType) {
  if (device.platform == "iOS") {
    var str = Object.keys(params).map(function(key) {
      return key + '=' + params[key];
      }).join('&');
    var sApp = startApp.set(v.scheme + urlInfo + str) ;
  } else if (schemeType == 1) {
    var str = Object.keys(params).map(function(key) {
      return key + '=' + params[key];
      }).join('&');        
    var sApp = startApp.set({
      "action" : "ACTION_VIEW",
      "uri" : v.altScheme + urlInfo + str
    }) ;
  } else {
    var sApp = startApp.set({
      "intentstart" : "startActivity",
      "package" : v.scheme
    },params) ;
  }
  sApp.start(function() {  // success
    errMgmt("index/externalApp",120.1,"external app: " +v.scheme+ " opened") ;
  }, function(error) { // fail
    // add popup window explaining failure
    errMgmt("index/externalApp",120.2, "external app: " +v.scheme+ " failed, directing to: " +v.store+ ", " +error) ;
    window.open(v.store,'_system','location=no') ;
  }) ;
}

The above successfully opens other apps like FB and Uber and such, but on my own isn't opening. The appAvailability function does see the secondary app, which in turn is calling the function that will open the app, but the startApp is unable to open it. This is the error I am getting in the primary app:

class android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=com.mySecondaryApp:// }

Whats the difference between package and application ? My end goal is to open the secondaryApp AND pass parameters to it on both iOS and Android.

@rolinger
Copy link
Author

rolinger commented Sep 3, 2020

@lampaa - well, not certain what I did wrong...or what I did to correct it...but the secondary app is now opening - at least on Android. Haven't tested yet on iOS.

Question - the params{} that are passed to the secondaryApp, how do I retrieve them in the app? I tried using :

    function handleOpenURL(url) {
      console.log("received url: " + url);
    } 

But it that function never fires, so I am not certain how to get the passed in parameters?

@lampaa
Copy link
Owner

lampaa commented Sep 3, 2020

@rolinger

application - simple parameter for open app by package name (if application defined, script finding Activity of application in device by package manager)
package - parameter of Intent for complex setting for start application in device.

To get extras on android, use the method:

startApp.extraFields(function(fields) { /* success */
	console.log(fields);
}, function() { /* fail */

});

Unfortunately, I don’t know how to get parameters from another application on ios :-(

@rolinger
Copy link
Author

rolinger commented Sep 4, 2020

@lampaa - Ok, I have been doing a lot of testing. The following three methods all work at opening and passing vars into the external app for both iOS and Android - however for Method 2, the only outstanding issue is getting the app to open into a new window - currently the external app is opening within the Primary calling app. Maybe someone can help figure out how to get it to open to a new window.

In the Primary calling App:

  var appScheme = "externalAppScheme://" ;
  var schemeType = 0/1 ;

  function openApp (schemeType,appScheme,urlInfo,params) {
    // Method 1 -iOS only - iOS forces external apps to a new window
    // this opens and passes the vars to the external app  - works perfect.
    if (device.platform == "iOS") {
      var str = Object.keys(params).map(function(key) {
        return key + '=' + params[key];
    }).join('&');
    var sApp = startApp.set(appScheme + urlInfo + str) ;

    // Method 2 - Android Only - opens & passes vars to external app
    // BUT, this method opens external app in same window as the calling/primary app
    // This causes issues when trying to navigate back and forth between Primary & Secondary app
    } else if (schemeType == 1) {   
      var str = Object.keys(params).map(function(key) {
        return key + '=' + params[key];
      }).join('&');        
      var sApp = startApp.set({
        "intentstart" : "startActivity",
        "uri" : appScheme + urlInfo + str,
      }) ; 

    // Method 3 - Android only - opens external app & passes vars in NEW window - works perfect
    } else {
      var sApp = startApp.set({
        "intentstart" : "startActivity",
        "application" : "com.externalAppName"
      },params) ;
    }
    sApp.start(function() {  
      // success 
    }, function()  {
      // fail
    }
  }

Then in the external Secondary called app - to retrieve the vars, both of these functions are placed in the deviceReady() section of app. For Primary app to successfully launch the external app (for Methods 1 & 2) with a URL/URI type call, ie: externalAppScheme:// , the plugin cordova-plugin-customurlscheme --varaible URL_SCHEME=externalAppScheme must be installed on the secondary app. As well, both Primary and Secondary app, obviously, need to be installed on the same device:

    // Get Vars Method 1
    // this handles being opened by a URI call: ie:  externalApp://url?var1=value1&var2=value2 
    window.handleOpenURL = function(url) {
      setTimeout(_ => {
        var parsed = new URL(url); 
        var search = parsed.search.substring(1);
        var inObj = JSON.parse('{"' + search.replace(/&/g, '","').replace(/=/g,'":"') + '"}', function(key, value) { return key===""?value:decodeURIComponent(value) }) ;       
        // URL vars are now in an Object
      }) ;
    }
    
    // Get Vars Method 2
    // this handles app being opened from com.lampaa.startApp passing an object
    startApp.getExtras(function (inObj) {
      // incoming object is stored to "inObj"
    }, function (fail) { /* fail */
        console.log(fail);
    });

@lampaa - I think if you adapted Get Vars Method 1 into your standard startApp.getExtras you could be able to retrieve vars in iOS.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants