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?
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
Related
I have a service in my app which saves files, either in onStartCommand() or after finishing, in onDestroy(). In the onCreate() I am checking if my app's directory and its subdirectory exist and if they don't, I create the path. However, I found out that the exists() method actually creates the whole path or even part of it, if it doesn't already exist. After doing that, my app actually crashes and after launching it again, it works perfect.
I've also tried surrounding the exists() method with a try-catch block but the app still crashes, without throwing any exception. This problem seems to only appear in my old device with Android 9.0, because the app doesn't have this problem on my other device, which has Android 12(API 31).
So I am wondering why is this happening and what would be a way to prevent that crash.
The code in question is:
#Override
public void onCreate() {
//some other initializations...
File dir = new File(myDirectory); /*myDirectory is the full path to my app's directory, so:
/storage/emulated/0/directory/subdirectory */
if(!dir.exists()) {
try {
if(!dir.mkdirs()) {
//handle failure
}
} catch (Exception e) {
` //handle exception
}
}
}
exits: not create new folder
if(!dir.exists()){
dir.mkdirs();// create your folder
}
//update
This question already has answers here:
Branch.io (Android SDK): 'only initialize Branch in the Launcher activity' and GDPR
(2 answers)
Closed 4 years ago.
I want my app to be GDPR compliant. It means that I want to avoid to launch any tool like Branch.io as long as the user did not give its consent.
My problem is that the Branch.io documentation https://docs.branch.io/pages/apps/android/ mentions that I have to put the following code in my launcher activity :
#Override
public void onStart() {
super.onStart();
// Branch init
Branch.getInstance().initSession(new Branch.BranchReferralInitListener() {
#Override
public void onInitFinished(JSONObject referringParams, BranchError error) {
if (error == null) {
Log.i("BRANCH SDK", referringParams.toString());
} else {
Log.i("BRANCH SDK", error.getMessage());
}
}
}, this.getIntent().getData(), this);
}
#Override
public void onNewIntent(Intent intent) {
this.setIntent(intent);
}
It is also mentioned in the doc :
Only initialize Branch in the Launcher activity
The app will open through the Launcher activity, where Branch will initialize and retrieve the deep link data from the link click.
So, I don't see how to make something GDPR compliant. Indeed, if this code really needs to be executed in the onStart of the launcher activity, I don't have time to execute it before the user gave its consent.
Is there any workaround?
In the same documentation, there is an explanation about how to disable tracking by Branch SDK, so your application is GDPR compliant, but still keep all the SDK features.
Here's the anchor to that section.
All you need to do is implement the following code right before calling the initSession():
Branch.getInstance().disableTracking(true);
You will need to build out the handling of this line based on whether the user gave a consent for tracking or not.
My IDE shows me the error even is empty project. As you can see I create the new project with empty activity. App is launched in mobile successfully and work fine. but logcat isn't working properly or any thing else I'm stuck help me out. And when I connect my mobile even I didn't build the project logcat is full of instruction/logs.
UPDATE:
First, gralloc stands for the low-level graphics buffer allocator.
The gralloc is part of the HAL (Hardware Abstraction Layer) which
means that the implementation is platform-specific. You can find the
interface definitions in
hardware/libhardware/include/hardware/gralloc.h. As expected from a
HAL component, the interface is divided into a module interface
(gralloc_module_t) and a device interface (alloc_device_t).
The error is very low level and related with OpenGLRenderer. Your device is trying to open some 64-bit library files, but if fails. Then the error occurs.
I did very deep search about this but nothing useful came up.
Try running apps on another devices and see the error occurs again.
Continue developing if the error is not causing crash or other important issue. If you find a solution, you will try again.
in my case, I tried to use Application class static context for calling new Activity and I changed it to local static Activity and problem solved.
Notice that this problem doesn't happen in all devices it just occur in some cases.
private static MainActivity u_static;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_users);
u_static = this;
}
public static void new(int id, String name){
Intent i = new Intent(u_static, NewActivity.class);
u_static.startActivity(i);
}
And something I notice that in some devices when an application stops working instead of showing error, this error happens. Trace and debug your codes.
About the crazy E/HAL: load: id=gralloc != hmi->id=gralloc
Reason for error: Generally, it is caused by the fact that the control object is not fetched, the click event of the control is executed, and the null value is related to the initialization control.
As
private Button bt;
bt.setOnclickListener(new OnClickLisenter(){....});
Is there a problem? Yes!
xml layout control
Check if the findViewById() is missing in the java code!
The above leaked bt = (Button) findViewById(R.id...);
java dynamic new control / custom control error
Check if you forgot to create the object!
The above leaked bt = new Button();
So the correct way to change the above code is:
private Button bt;
bt=(Button)findViewById(R.id...);
I encountered this issue while using runnable and passing an unassigned view.
This is caused by an empty view object where findViewById returns a null value.
Instead of passing the view object passing the value the view holds resolved the issue.
I always admired the way Android Studio operates in some aspects, like the ability to find out every thing that is not ok, like arrays that get declared and written, but never read, or functions that get never called.
The problem now is that I have an async function using along with the Parse SDK (Facebook Login) that seems just not understood by the IDE.
Button mFbParseLoginButton = (Button) findViewById(R.id.fbloginbutton);
final java.util.List<String> permissions = Arrays.asList("user_friends", "user_birthday", "user_hometown", "public_profile");
mFbParseLoginButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ParseFacebookUtils.logInWithReadPermissionsInBackground(LoginActivity.this, permissions, new LogInCallback() {
#Override
public void done(ParseUser user, ParseException err) {
if (user == null) {
Log.d("MyApp", "Uh oh. The user cancelled the Facebook login.");
} else if (user.isNew()) {
Log.d("MyApp", "User signed up and logged in through Facebook!");
// Create the user
regFacebookUser(user);
//registerFacebookUser(user);
} else {
Log.d("MyApp", "User logged in through Facebook!");
loginFacebookUser(user);
}
}
});
}
});
It just seems not to understand that this code potentially can call regFacebookUser and loginFacebookUser functions.
These buttons have been working for days of this app's development, and still do and receive the logs
06-03 15:30:54.460 1543-1543/xxxxxxxxxxxxx D/MyApp﹕ User logged in through Facebook!
But this is how actually Android Studio displays the code of regFacebookUser
If you know how Android Studio works, you'll know that when a method or a variable is grey, it means it's never used. Indeed it's the thing it says when I go hover every grey variable of this code.
At the right, in the scrollbar there are yellow squares everywhere around all the code for this. What can I do to resolve this bug?
I got Android Studio 0.9.9 and always been working fine. I wouldn't upgrade to the newer 1.2 to avoid incompatibility issues to the projects I'm working on. (When I had Eclipse the only upgrading of SDK messed up everything to me)
If my app crashes, it hangs for a couple of seconds before I'm told by Android that the app crashed and needs to close. So I was thinking of catching all exceptions in my app with a general:
try {
// ...
} catch(Exception e) {
// ...
}
And make a new Activity that explains that the application crashed instantly (and also giving users an opportunity to send a mail with the error details), instead of having that delay thanks to Android. Are there better methods of accomplishing this or is this discouraged?
Update: I am using a Nexus 5 with ART enabled and I am not noticing the delay I used to experience with apps crashing (the "hanging" I was talking about originally). I think since everything is native code now, the crash happens instantly along with getting all the crash information. Perhaps the Nexus 5 is just quick :) regardless, this may not be a worry in future releases of Android (given that ART is going to be the default runtime in Android L).
Here, check for the link for reference.
In here you create a class say ExceptionHandler that implements java.lang.Thread.UncaughtExceptionHandler..
Inside this class you will do your life saving stuff like creating stacktrace and gettin ready to upload error report etc....
Now comes the important part i.e. How to catch that exception.
Though it is very simple. Copy following line of code in your each Activity just after the call of super method in your overriden onCreate method.
Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler(this));
Your Activity may look something like this…
public class ForceClose extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler(this));
setContentView(R.layout.main);
}
}
You could just use a generic alert dialog to quickly display error messages.
For example...
//******************************************
//some generic method
//******************************************
private void doStuff()
{
try
{
//do some stuff here
}
catch(Exception e)
{
messageBox("doStuff", e.getMessage());
}
}
//*********************************************************
//generic dialog, takes in the method name and error message
//*********************************************************
private void messageBox(String method, String message)
{
Log.d("EXCEPTION: " + method, message);
AlertDialog.Builder messageBox = new AlertDialog.Builder(this);
messageBox.setTitle(method);
messageBox.setMessage(message);
messageBox.setCancelable(false);
messageBox.setNeutralButton("OK", null);
messageBox.show();
}
You could also add other error handling options into this method, such as print stacktrace
i found the "wtf" (what a terrible failure) method in the Log class. From the description:
Depending on system configuration, a report may be added to the
DropBoxManager and/or the process may be terminated immediately with
an error dialog.
http://developer.android.com/reference/android/util/Log.html