Hey folks,
I have an issue that I couldn’t solve in the last two days (I tried various suggestions found with google…), so I hope you guys can help me with that ![]()
I’m trying to implement a service which is started by Unity when a button is pushed. If the button is pushed again the service shall stop. Since I need to communicate (tracking steps of the user, but only call amount when needed for further computation) I wanted to use the bindService() function, so I have easy access to the service.
What I tried to accomplish that (I will post the customized AndroidManifest as I used it):
At first I created a new Activity “TActivity” which extends the UnityPlayerActivity with two test method getInt (static) and getFixedInt(non-static)
TActivity
package com.tracker;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity;
public class TActivity extends UnityPlayerActivity {
private TService mBoundService;
private boolean mServiceBound = false;
public static Context sContext;
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder service) {
TService.MyBinder myBinder = (TService.MyBinder) service;
mBoundService = myBinder.getService();
mServiceBound = true;
Log.d("Unity", "Service connected");
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
mBoundService = null;
mServiceBound = false;
}
};
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
sContext = this;
}
public void startTracking() {
Intent intent = new Intent(this, TService.class);
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
Log.d("Unity", "Service bound");
}
public int getPowerValue() {
return mBoundService.getPower();
}
public void getPower() {
UnityPlayer.UnitySendMessage("Canvas", "ReceivePowerInfo", String.valueOf(mBoundService.getPower()));
}
public static int getInt() {
return 123;
}
public int getFixedInt() {
return 999;
}
public void stopTracking() {
if (mServiceBound) {
unbindService(mServiceConnection);
mServiceBound = false;
}
}
}
Here I got the first problem: The onCreate-Method is never called at all → sContext will not be set and I get NullPtr exception via logcat when I use the following code:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.tracker" android:versionName="1.0" android:versionCode="1" android:installLocation="preferExternal">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
<application android:theme="@android:style/Theme.NoTitleBar.Fullscreen" android:icon="@drawable/app_icon" android:label="@string/app_name" android:debuggable="false" android:isGame="true" android:banner="@drawable/app_banner">
<activity android:name="com.tracker.TActivity" android:label="@string/app_name" android:screenOrientation="reverseLandscape" android:launchMode="singleTask" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
<service
android:name="com.tracker.TService"
android:enabled="true"
android:exported="true">
</service>
</application>
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="22" />
<uses-feature android:glEsVersion="0x00020000" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="false" />
</manifest>
var javaClass = new AndroidJavaClass("com.tracker.TActivity");
Debug.Log(javaClass.CallStatic<int>("getInt")); // works perfectly fine
var activity = javaClass.GetStatic<AndroidJavaObject>("sContext"); // NullPtr exception in Android (logcat)
Debug.Log(activity.Call<int>("getFixedInt")); // not called at all
Then I tried to use the UnityPlayer class:
var javaClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
Debug.Log(javaClass.CallStatic<int>("getInt")); // Method not found exception
var activity = javaClass.GetStatic<AndroidJavaObject>("currentActivity"); // No NullPtr exception :)
Debug.Log(activity.Call<int>("getFixedInt")); // Method not found exception
Finally I tried a mixture of both:
var javaClass = new AndroidJavaClass("com.tracker.UnityPlayer");
Debug.Log(javaClass.CallStatic<int>("getInt")); // Perfectly fine
var activity = javaClass.GetStatic<AndroidJavaObject>("currentActivity"); // Field not found exception
Debug.Log(activity.Call<int>("getFixedInt")); // Method not called
Since all of that failed I thought “fine… you don’t really need to extend the base class, just use a bridge
”. So I changed my Code to a more or less static variant (w/o the int test methods due to the absence of an object):“static” TActivity
package com.tracker;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity;
public class TActivity {
private static TService mBoundService;
private static boolean mServiceBound = false;
private static ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder service) {
TService.MyBinder myBinder = (TService.MyBinder) service;
mBoundService = myBinder.getService();
mServiceBound = true;
Log.d("Unity", "Service connected: " + mBoundService);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
mBoundService = null;
mServiceBound = false;
}
};
public static void startTracking(Activity unity) {
Intent intent = new Intent(unity, TService.class);
unity.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
}
public static int getPowerValue() {
return mBoundService.getPower();
}
public static void getPower() {
UnityPlayer.UnitySendMessage("Canvas", "ReceivePowerInfo", String.valueOf(mBoundService.getPower()));
}
public static void stopTracking(Activity unity) {
if (mServiceBound) {
unity.unbindService(mServiceConnection);
mServiceBound = false;
}
}
}
So far so good. To bind the service to unity I now need the activity. Easy going since it’s already provided:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.tracker" android:versionName="1.0" android:versionCode="1" android:installLocation="preferExternal">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
<application android:theme="@android:style/Theme.NoTitleBar.Fullscreen" android:icon="@drawable/app_icon" android:label="@string/app_name" android:debuggable="false" android:isGame="true" android:banner="@drawable/app_banner">
<activity android:name="com.unity3d.player.UnityPlayerActivity" android:label="@string/app_name" android:screenOrientation="reverseLandscape" android:launchMode="singleTask" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
<service
android:name="com.tracker.TService"
android:enabled="true"
android:exported="true">
</service>
</application>
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="22" />
<uses-feature android:glEsVersion="0x00020000" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="false" />
</manifest>
var javaClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
var activity = javaClass.GetStatic<AndroidJavaObject>("currentActivity"); // Unity Activity
var bridge = new AndroidJavaClass("com.tracker.TActivity"); // My bridge class
bridge.CallStatic("startTracking", activity); // Is called!
At this point the second problem arrived. Now when I finally want to bind the service to the Unity Activity I get:
Normally I would say “alright, I messed something up with the paths. Let’s recheck them all and try again.” But I can’t find the problem here… (TActivity and TService are in the same package, provided via .jar file in Assets/Plugins/Android → here lies the AndroidManifest too). After that I tried it with startService(intent), but that throws the same error. Maybe someone of you has any ideas?
Help is much appreciated! ![]()
Thanks