Failed to get Activity instance in Unity C #
I'm trying to access Activity method from Unity and can't figure out how it works, why it doesn't work. I read various pages like http://forum.unity3d.com/threads/call-a-method-in-an-activity-using-androidjavaobject.219950/ and http://docs.unity3d.com/460/ Documentation / Manual / PluginsForAndroid.html
I am trying to create a camera plugin for Unity. There are some plugins available, but most of them are outdated and do not work. In any case, I could use this knowledge for future use. I originally just used a regular Java class, but to take a picture, I found that the best route was to use intent due to the fact that it is used for quick photos and not for a personalized camera app. To use intent, you need to use an action. The Activity is passed to the Intent, but the Activity must also override the method to get the result from the Intent, as described in the Android documentation. I would link to him, but I am limited to two links.
I am using this to access the activity. However AndroidJavaClass initializes successfully, when I try to get the context I get a null ptr error in the logcat.
C # code
AndroidJavaClass link = new AndroidJavaClass("com.syncedsoftware.cameralink.CameraLinkActivity");
AndroidJavaObject activity = link.Call<AndroidJavaObject>("getLinkContext"); // jni null ptr!
activity.Call("TakePicture");
He never achieves activity. Call ("TakePicture");
Java class - UPDATED WITH STATICS -
public class CameraLinkActivity extends UnityPlayerActivity {
private static Context cameraLinkContext;
public static Context getLinkContext(){
Log.v("Unityx", "GetLinkContext()");
return cameraLinkContext;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.v("Unity", "OnCreate");
cameraLinkContext = this;
}
public void TakePicture(){
Log.v("Unity", "TakePicture()");
}
}
Logcat Output - UPDATED WITH NEW STATIC IMPLEMENTATION -
05-29 12:32:50.560 3408-3498/? V/Unityx﹕ GetLinkContext()
05-29 12:32:50.810 3408-3498/? I/Unity﹕ Exception: JNI: Init'd AndroidJavaObject with null ptr!
at UnityEngine.AndroidJavaObject..ctor (IntPtr jobject) [0x00000] in <filename unknown>:0
at UnityEngine.AndroidJavaObject.AndroidJavaObjectDeleteLocalRef (IntPtr jobject) [0x00000] in <filename unknown>:0
at UnityEngine.AndroidJavaObject._CallStatic[AndroidJavaObject] (System.String methodName, System.Object[] args) [0x00000] in <filename unknown>:0
at UnityEngine.AndroidJavaObject.CallStatic[AndroidJavaObject] (System.String methodName, System.Object[] args) [0x00000] in <filename unknown>:0
at AndroidCameraLink.Start () [0x00000] in <filename unknown>:0
I noticed that the message in onCreate () is never displayed. This makes me think that the activity is not being created properly and is not being created at all. The activity is never created ",", so onCreate () is never called to initialize the Context field.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.syncedsoftware.cameralink" android:theme="@android:style/Theme.NoTitleBar" 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:icon="@drawable/app_icon" android:label="@string/app_name" android:debuggable="false">
<activity android:name="com.unity3d.player.UnityPlayerNativeActivity" android:label="@string/app_name" android:screenOrientation="portrait" 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" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
<meta-data android:name="unityplayer.ForwardNativeEventsToDalvik" android:value="false" />
</activity>
<activity android:name="com.syncedsoftware.cameralink.CameraLinkActivity" />
</application>
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="18" />
<uses-feature android:glEsVersion="0x00020000" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
</manifest>
If anyone can explain why this doesn't work, I would be very grateful. I've been trying to figure this out for almost a week, but to no avail. This is my first time stepping into my home territory with Oneness, please excuse my ignorance.
UPDATE: getLinkContext () is called but the problem persists.
After migrating the implementation to static, I found that I hadn't noticed the logcat message. If you turn it static, getLinkContext () is called successfully, however, this does not fix the original problem of not being able to get an Activity instance.
cameraLinkContext is null because onCreate () is never called. Activity is never created.
source to share
I was able to fake a solution based on the YouTube tutorial (link below if interested).
Problem
The problem was that Unity was technically unaware of the activity, despite being defined in the manifest, so it couldn't create it. Someone pointed this out below, but when I made my activity the main activity, the application will refuse to launch. This was the correct approach, but there was more, as described below.
Decision
To get it to work, I had to copy the original UnityPlayerActivity implementation and paste it into my Java project. There I configured it accordingly and extended the UnityPlayerActivity. I have set activity as main activity in manifest. Instead of trying to call the activity method directly, I made a "bridge" class to do this for me. These are simplistic questions. UnityPlayer.currentActivity in Java classes contains a reference to the current activity that is used by UnityPlayer. In this case, my individual class. I was able to use this intent and now everything works flawlessly.
Step by step Fix
The first step was to copy the original UnityPlayerActivity.java implementation (found in the Unity installation subfolder) and customize it. It also extends UnityPlayerActivity (original) to make sure everything is properly linked to Unity. The original implementation defines many objects and methods that make the Unity player work in the first place.
UnityPlayerActivity.java
package com.syncedsoftware.player; // changed package name
import android.content.Intent;
import android.os.Bundle;
import com.unity3d.player.UnityPlayer;
public class UnityPlayerActivity extends com.unity3d.player.UnityPlayerActivity // extends the ORIGINAL implementation
{
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Process intent data
}
// Setup activity layout
@Override protected void onCreate (Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
}
}
The second step was to add the activity as the main activity in the manifest.
AndroifManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.syncedsoftware.inventory" android:theme="@android:style/Theme.NoTitleBar" 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:icon="@drawable/app_icon" android:label="@string/app_name" android:debuggable="false" android:isGame="false" android:banner="@drawable/app_banner">
<activity android:name="com.syncedsoftware.player.UnityPlayerActivity" android:label="@string/app_name" android:screenOrientation="sensorLandscape" 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" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="18" />
<uses-feature android:glEsVersion="0x00020000" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
</manifest>
The third step was to add a "bridge" to the class to call into Unity for easy access.
LinkBridge.java
package com.syncedsoftware.cameralink;
import android.content.Intent;
import android.provider.MediaStore;
import com.unity3d.player.UnityPlayer;
/**
* Created by Anthony on 5/30/2015.
*/
public class LinkBridge {
public static void ShowCamera(int requestCode){
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
UnityPlayer.currentActivity.startActivityForResult(cameraIntent, requestCode); // Gets custom activity and uses the callback accordingly
}
}
Finally, we add code to Unity to run ShowCamera (). # C # code AndroidJavaClass jc = new AndroidJavaClass ("com.syncedsoftware.cameralink.LinkBridge"); jc.CallStatic ("ShowCamera", 1);
After days (literally) searching for an answer, I came across this video: https://www.youtube.com/watch?v=4l64nUGt0l0 It helped a lot! I've flipped the implementations accordingly to suit my camera situation.
source to share