英文:
How to fix crash handling in android 10
问题
以下是您提供的内容的翻译部分:
我在Unity中创建了一个使用Cardboard SDK构建的场景,并将其导出为Android库。该库用于在Android应用程序中以卡片板模式播放视频。它不是整个应用程序,而只是其中的一部分。其余的Android应用程序是使用Kotlin和Java构建的。
我已经实现了所有函数,都能按预期工作,但是退出场景会导致Android崩溃。
我们尝试了多种方法来清除player prefs,甚至在关闭场景之前清除内存。但在Android上它总是崩溃。我有两部装有Android 9和10的Android手机用于测试。
在Android应用程序中,我已经这样设计,一旦应用程序崩溃,我就尝试恢复。我的崩溃是某些“lateinit var”变量被销毁。它们的值变为null,并且恢复上一个活动会导致崩溃。因此,在退出Unity场景后,我将取消引用的变量重新加载到内存中,一切又恢复正常。
> 注意:我尝试在Unity中使用Application.Quit();
,但它会关闭整个应用程序。另一方面,我只想关闭正在运行的场景。
在Unity中[我在Android部分调用一个名为goBack
的函数来关闭应用程序]:
public void GoToHome()
{
Pause();
Stop();
Resources.UnloadUnusedAssets();
PlayerPrefs.DeleteAll();
AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
jo.Call("goBack");
}
在应用程序中:
public void goBack()
{
UnityPlayer.currentActivity.finish();
finish();
loadDerereferencedVars();
}
这在Android 9上运行得很完美。但在另一部装有Android 10的手机上,在我关闭场景后,应用程序继续正常运行,但会出现一条消息:
当我点击关闭应用程序后,应用程序继续工作。
我已经检查了日志,崩溃的原因是在Unity Main > ...
中出现了null指针取消引用
。
如果您想查看来自Android Studio中LogCat的Unity崩溃日志
因此,既然应用程序仍在运行,我认为最好只是隐藏崩溃报告,让用户不知道这个崩溃,但仍然报告它。
我尝试将我的应用程序封装在Application
中,并添加一个方法来捕获未捕获的异常。
这是我的应用程序类:
public class MyApp extends Application {
private static final String TAG = "MyAPP";
@Override
public void onCreate() {
super.onCreate();
Thread.setDefaultUncaughtExceptionHandler(
new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException (Thread thread, Throwable e) {
handleUncaughtException (thread, e);
}
});
}
/**
* 处理未捕获的异常
*/
private void handleUncaughtException (Thread thread, Throwable e) {
// 以下内容显示了我想要的,尽管它不会像这样工作。
Toast.makeText(getApplicationContext(), "看起来我今天过得不太好!", Toast.LENGTH_LONG).show();
Log.e("UncaughtException", "我发现了一个异常!");
// 根据您的要求,根据需要添加一些代码逻辑
}
}
同样,在Android 9上运行得很完美,我也收到了错误报告。然而,在装有Android 10的手机上,我只收到了像上面的图像一样的崩溃报告,没有报告错误。
我想知道为什么崩溃处理不起作用,以及如何修复它?
英文:
I have a Unity Scene built with Cardboard SDK and exported as a library for Android. The library is used to play videos in cardboard mode on the android app. it's not the whole app, but a part in it. The rest of the android app is built with Kotlin and Java.
I have implemented that and all the functions work as expected, but, exiting the scene crashes the android.
We tried various ways to clear player prefs and even clear memory before closing the scene. But on android it always crashes. I have two android phones with android 9 and 10 for testing.
In the android app, I have made it such that as soon as the app crashes, I try to recover. My crash is that some lateinit var
variables are destroyed. Their value becomes null and recovering the previous activity crashes it. So right after I exit the unity scene, I load the dereferenced variables back into memory and everything works again.
> Note: I have tried using Application.Quit();
in unity, but it just closes the whole app. On the other hand, I only want to close the running scene
In unity [I call a function goBack
in android part to close the app]:
public void GoToHome()
{
Pause();
Stop();
Resources.UnloadUnusedAssets();
PlayerPrefs.DeleteAll();
AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
jo.Call("goBack");
}
In App:
public void goBack()
{
UnityPlayer.currentActivity.finish();
finish();
loadDerereferencedVars();
}
This goes perfectly on android 9. On the other phone with android 10, after I close the scene, the app continues to function, but, there comes a message
When I click close app, the app continues to work.
I have checked the logs and there is a null pointer dereference
cause for the crash in Unity Main >...
If you'd like to see the Unity Crash Log from LogCat in Android Studio
So, since the app is still running, I thought, it would be better to just hide the crash report and just let the user not know about this crash, but still report it.
I tried enclosing my app in Application
and added a method to catch uncaughtException.
here is my application class:
public class MyApp extends Application {
private static final String TAG = "MyAPP";
@Override
public void onCreate() {
super.onCreate();
Thread.setDefaultUncaughtExceptionHandler(
new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException (Thread thread, Throwable e) {
handleUncaughtException (thread, e);
}
});
}
/**
* Handles Uncaught Exceptions
*/
private void handleUncaughtException (Thread thread, Throwable e) {
// The following shows what I'd like, though it won't work like this.
Toast.makeText(getApplicationContext(), "Looks like I am having a bad day!", Toast.LENGTH_LONG).show();
Log.e("UncaughtException", "I found an exception!");
// Add some code logic if needed based on your requirement
}
}
Again, this works perfectly in Android 9 and I also got the error reported. However in the phone with android 10, I just get the crash report like the image above and no error is reported.
I want to know why the crash handling is not working and how can I fix it?
答案1
得分: 0
我不会完成你所来自的*Activity*,而只会打开一个新的意图(在UnityActivity上)。当你结束这个意图时,应用程序会回到*上一个活动*。
我将以我的脚本作为示例:
public void sendJobToUnity(String fileName, boolean isNewJob){
// 创建一个新的作业。它存在于JobSelector Activity中
isUnityLoaded = true;
// 这是你正在寻找的部分之一
Intent i = new Intent(JobSelector.this, MainUnityActivity.class); // 与 (CurrentActivity.this, UnityActivity.this) 相同
// 这些是我在整个应用程序中发送一些数据的方式。只需忽略它
// i.putExtra("jobName", fileName);
// i.putExtra("isNewJob", isNewJob);
// i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivityForResult(i, 1); // 这是你正在寻找的部分之二
}
要关闭它,在**MainUnityActivity**中我有一个覆盖方法,Unity发送给Android以便卸载**Activity**(不是完全退出,因为如果完全退出,你就无法再次加载它),像这样:
@Override
protected void receiveJobAndUnloadUnity(String data){
saveCurrentJob(data); // 保存从Unity接收到的作业
mUnityPlayer.unload(); // 这是你正在寻找的部分之三
}
如果你想从Android中卸载Unity,你可以随时放置**"mUnityPlayer.unload();"**,前提是你已经以我展示的方式启动了Activity。
请注意,*"mUnityPlayer"* 是一个默认的Unity变量,不能被重命名。
英文:
I would not finish the Activity you came from, instead just open a new intent (on UnityActivity). When you end this intent the app will come back to the last active Activity.
I will give you my script as an example:
public void sendJobToUnity(String fileName, boolean isNewJob){
//creates a new job. It exists inside the JobSelector Activity
isUnityLoaded = true;
//this is what you are looking for part1
Intent i = new Intent(JobSelector.this, MainUnityActivity.class); //same as (CurrentActivity.this, UnityActivity.this)
//those are how I send some data across the app. just ignore it
//i.putExtra("jobName", fileName);
//i.putExtra("isNewJob",isNewJob);
//i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivityForResult(i, 1); //this is what you are looking for part2
}
For closing it, in the MainUnityActivity Activity I have an override that Unity sends to Android in order to Unload the activity (not quit it completely cause you cannot load it again if you do it) like this:
@Override
protected void receiveJobAndUnloadUnity(String data){
saveCurrentJob(data); //saves the job it receives from Unity
mUnityPlayer.unload(); //this is what you are looking for part3
}
If you want to unload Unity from android you can put "mUnityPlayer.unload();" wherever you want, provided you have started the Activity the way I've shown you.
Note that "mUnityPlayer" is a default Unity variable and cannot be renamed
专注分享java语言的经验与见解,让所有开发者获益!
评论