Titanium Community Questions & Answer Archive

We felt that 6+ years of knowledge should not die so this is the Titanium Community Questions & Answer Archive

Custom URL Scheme - iPhone & Android

Hi,

I am looking on how to implement the Custom URL Scheme feature (i.e launch the mobile app when clicking on a link in safari or e-mail) for both iPhone and Android.

My goal is to send an e-mail with an HTML link

<a href="myapp://" />

Such that when the user clicks on it, the device starts the app with url attributes (if they exist)

But I couldn't find anything about it in the docs, neither in the Q&A…

Did anyone already do/implement this ??

How to do it ??
What file to complete or configure in order to do it ??
Hints, ideas ??

Thanks in advance !!

— asked May 31st 2011 by abbdoul ab
  • android
  • click
  • custom
  • iphone
  • launch
  • link
  • scheme
  • url
0 Comments

5 Answers

  • For iOS, check the Info.plist file in the (project)/build/iphone folder and look for the CFBundleURLSchemes key. The value it lists under the array element is the name assigned for the custom URL. You can change that if necesary, but just knowing it may be sufficient for you. I think the default is basically your project name in lowercase.

    Once you have that name, use it in a URL and add :// followed by whatever you want:

    mybundleurlscheme://foobar?attribute=value&another_attribute=value2

    In your app, use Ti.App.getArguments() to find out what was passed into the program. The caveat here is detecting the difference between a launch and pause/resume activity.

    Last I played with this, a pause/resume would end up still leaving the same value in Ti.App.getArguments() making it harder to correctly detect a new launch vs resume activity.

    A couple of pointers here:

    • Save a copy of Ti.App.getArgumets() for later comparison

    • Add a app listener for the 'resumed' event (NOT the 'resume' event) and check Ti.App.getArguments(). The value is not yet available during the 'resume' event (when app is preparing to resume) but is during the 'resumed' event (when app has resumed).

    • When 'resumed' event has the same value you originally saved, either the user did a pause/resume or the same custom URL was launched a second time. In my scenario, I could get by treating both the same but YMMV.

    Here is a code snippet from a project where I experimented with this. It is from a few SDK versions back, so perhaps there is a better way now:

    // Save initial launch command line arguments
    Ti.App.launchURL = '';
    Ti.App.pauseURL = '';
    var cmd = Ti.App.getArguments();
    if ( (getTypeOf(cmd) == 'object') && cmd.hasOwnProperty('url') ) {
        Ti.App.launchURL = cmd.url;
        Ti.API.info( 'Launched with url = ' + Ti.App.launchURL );
    }
    
    // Save launch URL at the time last paused
    Ti.App.addEventListener( 'pause', function(e) {
        Ti.App.pauseURL = Ti.App.launchURL;
    });
    
    // After app is fully resumed, recheck if launch arguments
    // have changed and ignore duplicate schemes.
    Ti.App.addEventListener( 'resumed', function(e) {
        Ti.App.launchURL = '';
        cmd = Ti.App.getArguments();
        if ( (getTypeOf(cmd) == 'object') && cmd.hasOwnProperty('url') ) {
            if ( cmd.url != Ti.App.pauseURL ) {
                Ti.App.launchURL = cmd.url;
                Ti.API.info( 'Resumed with url = ' + Ti.App.launchURL );
            }
        }
    });
    

    At this point I can check Ti.App.launchURL and deal with it as I like.

    — answered May 31st 2011 by Doug Handy
    permalink
    5 Comments
    • Hi, thanks for your help.

      Your solution worked fine, but I would like to add a few improvemens:

      • the name to use in your URL to call your application has to be in a special form….If the ID of your project in tiapp.xml is com.MyApp, the your URL has to be Myapp (first letter in uppercase, and all the others in lower case) other it won't work.

      • you have to copy and paste the Info.plist in your build/iphone directory to the your application main directory.
        Moreover here is what you have to write in Info.plist :

        <key> CFBundleURLTypes </key>
        <array>
        <dict>
          <key> CFBundleURLName </key>
          <string> com.MyApp </string>
          <key> CFBundleURLSchemes </key>
          <array>
              <string> MyApp </string>
          </array>
        </dict>
        </array>
        

      and call your app using < a href="Myapp://" > in any web page.

      — commented June 9th 2011 by abbdoul ab
    • If anyone is interested in the solution for Android version (a little bit different), let me know…

      And by the way I think that this has to be added in next Kitchen Sink version (when updated with the 1.7.0 features)

      — commented June 9th 2011 by abbdoul ab
    • Hi,

      I would be interested in how we can use custom URL scheme on Android.

      Thanks

      — commented June 21st 2011 by Gerome Bovet
    • OK, so here is the recipe for URL scheme on Android…

      But if you prefer, post a proper & different question, so that I answer to it rather than with these small comments (who doesn't support lists…), but as you wish…

      The first thing you have to do is to create a "custom" AndroidManifest.xml file.
      in order to do it
      create a folder in your application project folder (<MyMobileApp>) name platform, and inside it another folder named 'android', and inside this create a folder named android(platform&#x2F;android) copy the AndroidManifest.xml that you can find in your build/android/.

      If we resume simply with unix commands :

      cd MyAppHome
      mkdir platform
      mkdir platform/android
      cp build/android/AndroidManifest.xml platform/android/
      

      such that you get the following project structure

      <MyAppHome>
       - Resources/
       - ...
       - platform/
          - android/
             - AndroidManifest.xml
      

      Then the next step is to edit the AndroidManifest.xml.
      Open it, and go to the lines between the <!– TI_MANIFEST –> and <!– TI_APPLICATION –> .

      There you should find a the main <activity> of your mobile app.

      There you should add lines such that you have (some lines can already be there, so just add the lines you do not already have)

      <application
              android:icon="@drawable/appicon"
                android:label="MobileApp"
                android:name="MobileappApplication"
                android:debuggable="false"
          >
              <activity
                  android:name=".MobileappActivity"
                  android:label="MobileApp"
                  android:theme="@style/Theme.Titanium"
                  android:configChanges="keyboardHidden|orientation"
              >
                  <intent-filter>
                      <action android:name="android.intent.action.VIEW" />
                           <category android:name="android.intent.category.DEFAULT" />
                           <category android:name="android.intent.category.BROWSABLE" />
                      <category android:name="android.intent.category.LAUNCHER" />
                           <data  android:scheme="Mobileapp" />
                  </intent-filter>
              </activity>
      
                   <!-- TI_APPLICATION -->
      

      And to call your app from an URL, use Mobileapp:&#x2F;&#x2F;

      Be careful with UPPERCASE and LOWERCASE letters in AndroidManifest.xml….I banged my head to walls for 1-2 days because of this….

      Wherever you see 'Mobileapp' instead of 'MobileApp', it is not a mistake…..Android cannot handle the uppercase letters except for the first one…

      This is also the case with the URL, if you use 'MobileApp://' nothing will happen, but it will work with 'Mobileapp://' .

      (At least, when I first did the URL schemes, I was with SDK 1.6.2, so I had to be careful with letter cases…I don't know if it is still relevant with 1.7.0, but all I know is that my URL schemes still continue to work :) :) )

      Hope that this will help you.

      Tell me if it is ok for you.

      — commented June 24th 2011 by abbdoul ab
    • When I am implementing above for iOS version I am getting error "Can't find variable: getTypeOf";

      Can you help me, how are resolve this ?

      — commented November 21st 2013 by mahesh pet
  • OK, so here is the recipe for URL scheme on Android…

    But if you prefer, post a proper & different question, so that I answer to it rather than with these small comments (who doesn't support lists…), but as you wish…

    The first thing you have to do is to create a "custom" AndroidManifest.xml file. in order to do it create a folder in your application project folder () name platform, and inside it another folder named android, and inside this create a folder named android ( platform&#x2F;android ) copy the AndroidManifest.xml that you can find in your build&#x2F;android&#x2F;.

    If we resume simply with unix commands :

    cd MyAppHome
    mkdir platform
    mkdir platform/android
    cp build/android/AndroidManifest.xml platform/android/
    

    such that you get the following project structure

    <MyAppHome>
     - Resources/
     - ...
     - platform/
        - android/
           - AndroidManifest.xml
    

    Then the next step is to edit the AndroidManifest.xml. Open it, and go to the lines between the and .

    There you should find a the main of your mobile app.

    There you should add lines such that you have (some lines can already be there, so just add the lines you do not already have)

    <application
            android:icon="@drawable/appicon"
            android:label="MobileApp"
            android:name="MobileappApplication"
            android:debuggable="false"
        >
            <activity
                android:name=".MobileappActivity"
                android:label="MobileApp"
                android:theme="@style/Theme.Titanium"
                android:configChanges="keyboardHidden|orientation"
            >
                <intent-filter>
                    <action android:name="android.intent.action.VIEW" />
                         <category android:name="android.intent.category.DEFAULT" />
                         <category android:name="android.intent.category.BROWSABLE" />
                    <category android:name="android.intent.category.LAUNCHER" />
                         <data  android:scheme="Mobileapp" />
                </intent-filter>
            </activity>
    
                 <!-- TI_APPLICATION -->
    

    And to call your app from an URL, use Mobileapp:&#x2F;&#x2F;

    Be careful with UPPERCASE and LOWERCASE letters in AndroidManifest.xml….I banged my head to walls for 1-2 days because of this….

    Wherever you see 'Mobileapp' instead of 'MobileApp', it is not a mistake…..Android cannot handle the uppercase letters except for the first one…

    This is also the case with the URL, if you use 'MobileApp://' nothing will happen, but it will work with 'Mobileapp://' .

    (At least, when I first did the URL schemes, I was with SDK 1.6.2, so I had to be careful with letter cases…I don't know if it is still relevant with 1.7.0, but all I know is that my URL schemes still continue to work :) :) )

    Hope that this will help you.

    Tell me if it is ok for you.

    — answered July 5th 2011 by abbdoul ab
    permalink
    4 Comments
    • hi,

      i tried following the above steps for android and iphone.. works good in iphone but android is not working… couldn't form the email link using gmail app or default android mail app.. also couldnt open the app through the browser by just typing in Appname://

      Please give some inputs and if possible share your tiapp.xml, so that it could provide some insight…

      thanks

      asghar ali

      — commented September 1st 2011 by asghar ali
      • asghar ali you would need an html link element with the href attribute set to "Appname://".

      • From my experience I am adding a bit of a correction to the posters code block, although I must thank him for showing how to use your own custom AndroidManifest.xml file.

      • You don't need the LAUNCHER category in the intent-filter that you want to use to be able to launch the app from an intent or web browser.

      • With that configuration you might not see the App show up in the App Launcher, so if you wan the user to be able to launch it normally you would need to include another intent filter as shown (which is the original intent filter from when you copy the file).

      For more information on what you can do with the scheme see the documentation

      <application
              android:icon="@drawable/appicon"
              android:label="MobileApp"
              android:name="MobileappApplication"
              android:debuggable="false"
          >
          <!-- TI_APPLICATION -->
      
              <activity
                  android:name=".MobileappActivity"
                  android:label="MobileApp"
                  android:theme="@style/Theme.Titanium"
                  android:configChanges="keyboardHidden|orientation"
              >
                  <intent-filter>
                      <action android:name="android.intent.action.VIEW" />
                      <category android:name="android.intent.category.DEFAULT" />
                      <category android:name="android.intent.category.BROWSABLE" />
                      <data  android:scheme="Mobileapp" />
                  </intent-filter>
                  <intent-filter>
                     <action android:name="android.intent.action.MAIN" />
                     <category android:name="android.intent.category.LAUNCHER" />
                  </intent-filter>
              </activity>
      </application>
      

      — commented January 8th 2013 by Matthew Orlando
    • I've been trying to so the same though the url should be example: myapp:&#x2F;&#x2F; all lowercase, would it be possible for the url to call the app all be in lowercase?

      — commented February 17th 2013 by Joseph Sachs
    • I need to get parameters from the url.

      I have the above working and I can get parameters when the app is initially launched from the url (accessed by data property of currentActivity.getIntent()) . However, if the app is in the background and the url is clicked, the app receives focus, but the url is null.

      The scenario is that a user clicks an emailed link with a transactionId included as a query string parameter. The app responds according to the transactionId. However, if the app is already opened on the user's device and they click on the email link, I can't get the transactionId. Any help would be greatly appreciated.

      — commented May 7th 2014 by Rick White
  • In SDK 3.0, there is No need to create a Custom AndroidManifest.xml, but rather simply open your tiapp.xml and find your <android> <application> node, and make sure this is added in there:

    <activity
                android:name=".MobileappActivity"
                android:label="MobileApp"
                android:theme="@style/Theme.Titanium"
                android:configChanges="keyboardHidden|orientation"
            >
                <intent-filter>
                    <action android:name="android.intent.action.VIEW" />
                         <category android:name="android.intent.category.DEFAULT" />
                         <category android:name="android.intent.category.BROWSABLE" />
                    <category android:name="android.intent.category.LAUNCHER" />
                         <data  android:scheme="Mobileapp" />
                </intent-filter>
            </activity>
    
    — answered February 17th 2013 by Joseph Sachs
    permalink
    4 Comments
    • This is not working for me, Please see below my tiapp.xml

      Can you please correct me if i missed something

      <?xml version="1.0" encoding="UTF-8"?>
      <ti:app xmlns:ti="http://ti.appcelerator.org">
          <id>com.samy.laumch</id>
          <name>LaunchApp</name>
          <version>1.0</version>
          <publisher>a</publisher>
          <url>http://</url>
          <description>not specified</description>
          <copyright>2013 by a</copyright>
          <icon>appicon.png</icon>
          <persistent-wifi>false</persistent-wifi>
          <prerendered-icon>false</prerendered-icon>
          <statusbar-style>default</statusbar-style>
          <statusbar-hidden>false</statusbar-hidden>
          <fullscreen>false</fullscreen>
          <navbar-hidden>false</navbar-hidden>
          <analytics>true</analytics>
          <guid>cd762d49-ed16-4355-b0f7-7922255c0287</guid>
      
          <iphone>
              <orientations device="iphone">
                  <orientation>Ti.UI.PORTRAIT</orientation>
              </orientations>
              <orientations device="ipad">
                  <orientation>Ti.UI.PORTRAIT</orientation>
                  <orientation>Ti.UI.UPSIDE_PORTRAIT</orientation>
                  <orientation>Ti.UI.LANDSCAPE_LEFT</orientation>
                  <orientation>Ti.UI.LANDSCAPE_RIGHT</orientation>
              </orientations>
          </iphone>
          <android xmlns:android="http://schemas.android.com/apk/res/android">
              <activity
              android:name=".LaunchApp">
                  <intent-filter>
                      <action android:name="android.intent.action.MAIN" />
                      <category android:name="android.intent.category.LAUNCHER" />
                  </intent-filter>
                  <intent-filter>
                      <action android:name="android.intent.action.VIEW" />
                      <category android:name="android.intent.category.DEFAULT" />
                      <category android:name="android.intent.category.BROWSABLE" />
                      <category android:name="android.intent.category.LAUNCHER" />
                      <data  android:scheme="http" android:host="com.samy.laumch"/>
                  </intent-filter>
              </activity>
          </android>
          <mobileweb>
              <precache/>
              <splash>
                  <enabled>true</enabled>
                  <inline-css-images>true</inline-css-images>
              </splash>
              <theme>default</theme>
          </mobileweb>
          <modules/>
          <deployment-targets>
              <target device="iphone">false</target>
              <target device="ipad">false</target>
              <target device="blackberry">false</target>
              <target device="android">true</target>
              <target device="mobileweb">true</target>
          </deployment-targets>
          <sdk-version>3.0.2.v20130215134659</sdk-version>
      </ti:app>
      

      — commented March 6th 2013 by Saamy
    • After i create xml in below location its working. But not from tiapp.xml

      <MyAppHome>
       - Resources/
       - ...
       - platform/
          - android/
             - AndroidManifest.xml
      

      — commented March 7th 2013 by Saamy
    • Hi Saamy, I think (I haven't verified) you missed <manifest> and <application> tags in tiapp.xml.
      Please, refer this document.

      <android>
          <manifest>
              <application>
                  <activity>
                     ...
                  </activity>
              </application>
          </manifest>
      </android>
      

      — commented February 13th 2014 by Kanji Furuhashi
    • It doesn't work for me . When i hit my app name in browser it by default searches in google and open the web version of my app. Please help me.

      — commented August 13th 2014 by ajit jati
  • It doesn't work for me . When i hit my app name in browser it by default searches in google and open the web version of my app. Please help me.

    — answered August 13th 2014 by ajit jati
    permalink
    0 Comments
  • For open link in android you have to write following code:

    <application android:icon="@drawable/appicon" android:label="Buddy Drinks" android:name="BuddyDrinksApplication">
    <activity android:name="Application_Activity_Name" android:label="@string/app_name" android:configChanges="keyboardHidden|orientation|screenSize">
    <intent-filter>
    <action android:name="android.intent.action.MAIN"/>
    <action android:name="android.intent.action.VIEW"/>
    </intent-filter>
    </activity>
    <activity android:name="Package _Name.Application_Activity_Name" android:label="@string/app_name" android:configChanges="keyboardHidden|orientation|screenSize">
    <intent-filter android:label="@string/app_name">
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="Schema_name _As_you_want" android:host="As_you_want"/>
    </intent-filter>
    </activity>

    Now got to the terminal write command(Mac terminal command)
    ./adb shell am start -a android.intent.action.VIEW -d "Schema_name://Host_Name" Package_Name

    run this command your application will start
    You can check this via create a link also.
    For create the link follow this link
    https://developers.google.com/app-indexing/webmasters/test

    — answered April 23rd 2015 by Alok Gupta
    permalink
    0 Comments
The ownership of individual contributions to this community generated content is retained by the authors of their contributions.
All trademarks remain the property of the respective owner.