AndroidJavaClass/AndroidJavaObject 导致构建的应用程序崩溃
AndroidJavaClass/AndroidJavaObject causing built application to crash
我有一个 Android 应用程序,它在将以下代码引入我场景中的对象之前构建并运行 find 。我的目标是为我的应用程序以不同的长度振动,而不是仅仅使用默认的 Handheld.Vibrate()
函数。添加此代码后,我的应用程序仍然可以很好地构建到我的设备上,但在启动时崩溃。
我使用的是 Unity 2019.2.9f1,我的最低 API 级别设置为 25,使用 Mono 和 .NET 2.0。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HapticController : Singleton<HapticController> {
#if UNITY_ANDROID && !UNITY_EDITOR
public static AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
public static AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
public static AndroidJavaObject vibrator = currentActivity.Call<AndroidJavaObject>("getSystemService", "vibrator");
#else
public static AndroidJavaClass unityPlayer;
public static AndroidJavaObject currentActivity;
public static AndroidJavaObject vibrator;
#endif
bool isVibrating;
...
// Update is called once per frame
void Update()
{
if(!isVibrating && ( *other condition* ) ){
isVibrating = true; //this will later be changed, just trying to get it to vibrate once
Vibrate(200);
}
}
public static void Vibrate(long milliseconds)
{
if(isAndroid() && vibrator != null){
print("vibrating");
vibrator.Call("vibrate", milliseconds);
} else {
Handheld.Vibrate();
}
}
private static bool isAndroid()
{
#if UNITY_ANDROID && !UNITY_EDITOR
return true;
#else
return false;
#endif
}
}
我知道是顶部的 AndroidJavaClass/AndroidJavaObject 调用导致了崩溃。我已经在 Android Studio 中检查了 logcat 中的日志,但是没有明显的输出与崩溃有任何关系。有什么我没有考虑到的会导致这种情况吗?
编辑:我应该补充一点,我使用的是一个 SDK (Mapbox),它有自己的 AndroidManifest.xml。它指示您重命名它并将其移动到 Plugins/Android 文件夹。你可以在这里看到它:
<!--
Android Manifest for UniAndroid Permission (2016/03/19 sanukin39)
--- if already have AndroidManifest file at Assets/Plugins/Android/ ----
Copy the activity and meta-data sentence to your AndroidManifest.xml
--- if not ---
Rename this file to AndroidManifest.xml and add permission you want to add And move the file to Assets/Plugins/Android
-->
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.company.product">
<application android:icon="@drawable/app_icon" android:label="@string/app_name">
<activity android:name="net.sanukin.OverrideUnityActivity"
android:label="@string/app_name"
android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data android:name="unityplayer.SkipPermissionsDialog" android:value="true" />
</application>
</manifest>
您应该在{项目位置}\Assets\Plugins\Android\AndroidManifest中添加以下振动权限。xml
<uses-permission android:name="android.permission.VIBRATE"/>
所以你最终的 AndroidManifest 变成了。
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.unity3d.player"
android:versionCode="1"
android:versionName="1.0">
<uses-permission android:name="android.permission.VIBRATE"/>
<application
android:theme="@style/UnityThemeSelector"
android:icon="@drawable/app_icon"
android:label="@string/app_name"
android:debuggable="true">
<activity android:name="com.unity3d.player.UnityPlayerActivity"
android:label="@string/app_name">
<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" />
</activity>
</application>
对于其他为此苦苦挣扎的人,我能够结合 Farhan 的回答并执行以下操作来解决此问题:
我没有在顶部初始化 AndroidJavaClass 和 AndroidJavaObjects,而是创建了一个负责执行此操作的初始化函数。我添加了行
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
在它上面是为了强制它在场景加载之前初始化它们。我不确定为什么需要这样做,但它为我修复了它。您可以在下面看到完整的功能:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HapticController : Singleton<HapticController> {
public static AndroidJavaClass unityPlayer = null;
public static AndroidJavaObject currentActivity = null;
public static AndroidJavaObject vibrator = null;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void Initialize(){
#if UNITY_ANDROID && !UNITY_EDITOR
if (Application.platform == RuntimePlatform.Android) {
unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
vibrator = currentActivity.Call<AndroidJavaObject>("getSystemService", "vibrator");
}
#endif
}
...
}
我有一个 Android 应用程序,它在将以下代码引入我场景中的对象之前构建并运行 find 。我的目标是为我的应用程序以不同的长度振动,而不是仅仅使用默认的 Handheld.Vibrate()
函数。添加此代码后,我的应用程序仍然可以很好地构建到我的设备上,但在启动时崩溃。
我使用的是 Unity 2019.2.9f1,我的最低 API 级别设置为 25,使用 Mono 和 .NET 2.0。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HapticController : Singleton<HapticController> {
#if UNITY_ANDROID && !UNITY_EDITOR
public static AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
public static AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
public static AndroidJavaObject vibrator = currentActivity.Call<AndroidJavaObject>("getSystemService", "vibrator");
#else
public static AndroidJavaClass unityPlayer;
public static AndroidJavaObject currentActivity;
public static AndroidJavaObject vibrator;
#endif
bool isVibrating;
...
// Update is called once per frame
void Update()
{
if(!isVibrating && ( *other condition* ) ){
isVibrating = true; //this will later be changed, just trying to get it to vibrate once
Vibrate(200);
}
}
public static void Vibrate(long milliseconds)
{
if(isAndroid() && vibrator != null){
print("vibrating");
vibrator.Call("vibrate", milliseconds);
} else {
Handheld.Vibrate();
}
}
private static bool isAndroid()
{
#if UNITY_ANDROID && !UNITY_EDITOR
return true;
#else
return false;
#endif
}
}
我知道是顶部的 AndroidJavaClass/AndroidJavaObject 调用导致了崩溃。我已经在 Android Studio 中检查了 logcat 中的日志,但是没有明显的输出与崩溃有任何关系。有什么我没有考虑到的会导致这种情况吗?
编辑:我应该补充一点,我使用的是一个 SDK (Mapbox),它有自己的 AndroidManifest.xml。它指示您重命名它并将其移动到 Plugins/Android 文件夹。你可以在这里看到它:
<!--
Android Manifest for UniAndroid Permission (2016/03/19 sanukin39)
--- if already have AndroidManifest file at Assets/Plugins/Android/ ----
Copy the activity and meta-data sentence to your AndroidManifest.xml
--- if not ---
Rename this file to AndroidManifest.xml and add permission you want to add And move the file to Assets/Plugins/Android
-->
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.company.product">
<application android:icon="@drawable/app_icon" android:label="@string/app_name">
<activity android:name="net.sanukin.OverrideUnityActivity"
android:label="@string/app_name"
android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data android:name="unityplayer.SkipPermissionsDialog" android:value="true" />
</application>
</manifest>
您应该在{项目位置}\Assets\Plugins\Android\AndroidManifest中添加以下振动权限。xml
<uses-permission android:name="android.permission.VIBRATE"/>
所以你最终的 AndroidManifest 变成了。
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.unity3d.player"
android:versionCode="1"
android:versionName="1.0">
<uses-permission android:name="android.permission.VIBRATE"/>
<application
android:theme="@style/UnityThemeSelector"
android:icon="@drawable/app_icon"
android:label="@string/app_name"
android:debuggable="true">
<activity android:name="com.unity3d.player.UnityPlayerActivity"
android:label="@string/app_name">
<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" />
</activity>
</application>
对于其他为此苦苦挣扎的人,我能够结合 Farhan 的回答并执行以下操作来解决此问题:
我没有在顶部初始化 AndroidJavaClass 和 AndroidJavaObjects,而是创建了一个负责执行此操作的初始化函数。我添加了行
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
在它上面是为了强制它在场景加载之前初始化它们。我不确定为什么需要这样做,但它为我修复了它。您可以在下面看到完整的功能:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HapticController : Singleton<HapticController> {
public static AndroidJavaClass unityPlayer = null;
public static AndroidJavaObject currentActivity = null;
public static AndroidJavaObject vibrator = null;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void Initialize(){
#if UNITY_ANDROID && !UNITY_EDITOR
if (Application.platform == RuntimePlatform.Android) {
unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
vibrator = currentActivity.Call<AndroidJavaObject>("getSystemService", "vibrator");
}
#endif
}
...
}