Search code examples
c#androidandroid-intentunity-game-engineandroid-implicit-intent

Read Android intent extra data on Unity app launch


I am launching an Unity application from another Android application using a custom implicit intent. This is working fine, but I cannot figure out how to read the intent extra data in Unity?

ANDROID INTENT TO LAUNCH UNITY APP

i=new Intent();
i.setAction("com.company.unityapp.MyMethod");
i.putExtra("KEY","This is the message string");
startActivity(i);

UNITY APP AndroidManifest.xml

<intent-filter>
     <action android:name="com.company.unityapp.MyMethod" />
     <category android:name="android.intent.category.DEFAULT" />
</intent-filter>

I have a GameObject in my scene with a script attached. Inside the start method I have this code to try and read the extra data that was passed along with the intent

AndroidJavaClass UnityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); 
AndroidJavaObject currentActivity = UnityPlayer.GetStatic<AndroidJavaObject>("currentActivity");

AndroidJavaObject intent = currentActivity.Call<AndroidJavaObject>("getIntent");
bool hasExtra = intent.Call<bool> ("hasExtra", "arguments");

if (hasExtra) {
 AndroidJavaObject extras = intent.Call<AndroidJavaObject> ("getExtras");
 arguments = extras.Call<string> ("getString", "arguments");
}

This is not working and arguments is always empty. Any help would be appreciated.


Solution

  • It took me quite some time to figure this out. All solutions found online were only partly complete. Below is the full solution for launching a Unity application from another android application using a custom implicit Intent and also how to access the extra data sent with the Intent inside Unity.

    To accomplish this you need to create a Android plugin that will be used by Unity to access the Intent extra data.

    ANDROID PLUGIN:


    You need to copy the classes.jar from Unity installation folder to the android plugin folder /lib/classes.jar

    public class MainActivity extends UnityPlayerActivity {
    
      @Override
      protected void onNewIntent(Intent intent) {
          super.onNewIntent(intent);
          handleNewIntent(intent);
      }
    
      private void handleNewIntent(Intent intent){
          String text = intent.getStringExtra("KEY");
          UnityPlayer.UnitySendMessage("AccessManager","OnAccessToken", text);
      }
    }
    

    AndroidManifest.xml

    Important here is the package name used: com.company.plugin

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.company.plugin">
        <application
            android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name"
            android:supportsRtl="true" android:theme="@style/AppTheme">
            <activity
                android:name=".MainActivity"
                android:label="@string/app_name"
                android:theme="@style/AppTheme.NoActionBar">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    </manifest>
    

    Gradle build file:

    Add the following to the app gradle build file to be able to create a .jar to be used with Unity

    android {
        compileSdkVersion 23
        buildToolsVersion "23.0.2"
        sourceSets {
            main {
                java {
                    srcDir 'src/main/java'
                }
            }
        }       
    ...
    ...
    
    dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar'])
        compile 'com.android.support:appcompat-v7:23.2.1'
        compile 'com.android.support:design:23.2.1'
        compile files('libs/classes.jar')
    }
    
    //task to delete the old jar
    task deleteOldJar(type: Delete) {
        delete 'release/AndroidPlugin.jar'
    }
    
    //task to export contents as jar
    task exportJar(type: Copy) {
        from('build/intermediates/bundles/release/')
        into('release/')
        include('classes.jar')
        ///Rename the jar
        rename('classes.jar', 'AndroidPlugin.jar')
    }
    
    exportJar.dependsOn(deleteOldJar, build)
    

    Copy the created AndroidPlugin.jar to Unity Assets/Plugins/Android

    UNITY APP:


    Set the bundle identifier in PlayerSettings to be the same as set in the Android Plugin - com.company.plugin

    Create custom AndroidManifest.xml file in Assets/Plugins/Android

    Important here is to use the same package name as used in the plugin. Also note the Intent name: com.company.plugin.do

    AndroidManifest.XML

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.company.plugin"
          android:versionCode="1" android:versionName="1.0">
        <uses-sdk android:minSdkVersion="9" />
        <application android:label="@string/app_name">
            <activity android:name=".MainActivity" android:label="@string/app_name"
              android:launchMode="singleTask" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" android:screenOrientation="sensor">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
                <intent-filter>
                    <action android:name="com.company.plugin.do" />
                    <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="text/plain"/>
                </intent-filter>
            </activity>
        </application>
    </manifest>
    

    Create a unity script named AccessManager and attach the script to a game object in the scene. OnAccessToken is the method that will receive the message sent from the android plugin and will contain the extra data sent from the intent.

    public class accessManager : MonoBehaviour {
    
        public void OnAccessToken(string accessToken)
        {
            Debug.Log("Message Received!!!! :" + accessToken);
        }
    }
    

    ANDROID APP:

    Create a standard Android application that will launch the Unity Application and send the Intent extra data

    public void LaunchUnityApp(){
        Intent i=new Intent();
        i.setAction("com.company.plugin.do");
        i.setType("text/plain");
        i.putExtra("KEY","This is the text message sent from Android");
        startActivity(i);
    }