Unity C#中无法获取Activity实例

4
我一直在尝试从Unity访问Activity方法,但我无法弄清楚为什么它不起作用。我已经阅读了各种页面,例如http://forum.unity3d.com/threads/call-a-method-in-an-activity-using-androidjavaobject.219950/http://docs.unity3d.com/460/Documentation/Manual/PluginsForAndroid.html
我正在尝试为Unity创建一个相机插件。有一些插件可用,但大多数都已过时并且不起作用。我无论如何都可以使用这些知识以备将来之需。最初我只是使用常规的Java类,但是为了拍照,我发现最好的方法是使用Intent,因为它被用于快速拍照而不是个性化相机应用程序。要使用Intent,必须使用Activity。该Activity被传递给Intent,但Activity还必须覆盖一种方法才能从Intent中接收结果,如Android文档所述。我想链接到它,但我只限于2个链接。

我正在使用这个来访问活动。AndroidJavaClass成功初始化,但是当我尝试获取上下文时,在logcat中出现了空指针错误。

C#代码

    AndroidJavaClass link = new AndroidJavaClass("com.syncedsoftware.cameralink.CameraLinkActivity");
    AndroidJavaObject activity = link.Call<AndroidJavaObject>("getLinkContext"); // jni null ptr!

    activity.Call("TakePicture");

它从未达到 activity.Call("TakePicture");。

Java 类 -已更新为静态-

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输出 -使用新的静态实现进行更新-

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

我注意到的是,在onCreate()中的消息从未显示。这让我认为Activity没有被正确创建或根本没有被创建。Activity从未被“创建”,因此onCreate()也没有被调用来初始化Context字段。

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>

如果有人能解释一下为什么这不起作用,我会非常感激。我已经试图解决这个问题将近一周了,但是没有成功。这是我第一次进入Unity的本地领域,请原谅我的无知。
更新:getLinkContext()正在被调用,但问题仍然存在。
在将实现翻转为静态后,我发现我忽视了logcat消息。当将其翻转为静态时,getLinkContext()被成功调用,但是这并不能解决无法获取Activity实例的原始问题。
cameraLinkContext为空,因为onCreate()从未被调用。 Activity从未被“创建”。

请使用Unity3D标签。 - Lex Li
1
我已经有一段时间没有使用任何扩展UnityPlayerNativeActivity的Activity了(我们很久以前就切换到了完全不同的插件制作方法),所以我不确定,但我认为问题可能在于您的自定义Activity(com.syncedsoftware.....)没有在清单中标记为MainActivity。基本上,在清单中用您的Activity名称替换“com.unity3d.player.UnityPlayerNativeActivity”。 - Venkat at Axiom Studios
@VenkatatAxiomStudios 在执行此操作后,应用程序甚至无法启动。我收到了一个弹出消息,上面写着“应用程序未安装”。 - Anthony Santiago
2个回答

1
你会收到空指针异常,因为你试图在AndroidJavaClass上调用非静态方法。

如果我将实现更改为静态的,它会成功调用getLinkContext(),但仍会抛出jni null ptr。这可能是因为活动没有初始化。上下文为空,因为onCreate()从未被调用。 - Anthony Santiago
该帖子已更新以反映这一点。您的解决方案解决了其中一个问题,谢谢!然而,Activity 仍未被“创建”。 - Anthony Santiago

0

我能够根据一个YouTube教程(如果感兴趣,下面有链接)打造出一个解决方案。

问题

问题在于Unity实际上并不知道这个活动,尽管它在清单中被定义,因此它无法创建它。有人在下面指出了这一点,但当我将我的活动设置为主要活动时,应用程序会拒绝启动。这是正确的方法,但还有更多需要描述如下。

解决方案

为了使它正常工作,我不得不复制UnityPlayerActivity的原始实现,并将其粘贴到我的Java项目中。在那里,我进行了相应的自定义,并扩展了UnityPlayerActivity。我在清单中将该活动设置为主要活动。我没有直接尝试调用活动方法,而是制作了一个“桥接”类来代替我完成。这简化了事情。Java类中的UnityPlayer.currentActivity持有对正在UnityPlayer中使用的当前活动的引用。在这种情况下,就是我的自定义类。我能够使用它调用Intent,现在一切都运行得很完美。

逐步修复

第一步是复制UnityPlayerActivity.java的原始实现(在Unity安装子文件夹中找到),并进行自定义。它还扩展了UnityPlayerActivity(原始版本),以确保一切都正确地链接到Unity。原始实现定义了许多对象和方法,使Unity播放器首先能够正常工作。

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);
}
}

第二步是将该活动添加为清单中的主要活动。

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>

第三步是添加一个“桥接”类,在Unity中调用以便易于访问。

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
}

}

最后,我们在Unity中添加代码以触发ShowCamera()。 #C# 代码 AndroidJavaClass jc = new AndroidJavaClass("com.syncedsoftware.cameralink.LinkBridge"); jc.CallStatic("ShowCamera", 1);

经过数天(实际上)的寻找答案,我找到了这个视频:https://www.youtube.com/watch?v=4l64nUGt0l0 这对我有很大帮助!我相应地调整了实现,以适应我的Camera intent情况。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接