yasirkula / UnityNativeCamera

A native Unity plugin to take pictures/record videos with device camera on Android & iOS
MIT License
614 stars 71 forks source link

Android app restarts after capturing an image #73

Open CameronGoosen opened 3 years ago

CameronGoosen commented 3 years ago

Description of the bug

This issue is happening on Galaxy Tab A and Android A10 devices which a massive portion of our user base have. I've added a video of the issue but in summation after you capture an image and click 'Ok', it restarts the application instead of resuming when coming back from the Intent.

Reproduction steps

Capture an image, after clicking 'Ok' app restarts. This most of the time happens after 1 photo is taken but some times it only occurs after multiple images are captured in a row.

Platform specs

Please provide the following info if this is a Unity 3D repository.

Additional info

Video of Issue https://user-images.githubusercontent.com/20043989/125259570-b966ec00-e2ff-11eb-8409-377edf728e3c.mp4

LogCat, search for 'START NATIVE CAPTURE' in log logcat.txt

yasirkula commented 3 years ago

I've checked some logs and peeked at all occurrences of 'crash' but didn't see anything useful. This issue with A10 devices has been brought to my attention a couple of times and my assumption hasn't changed since then:

I'm guessing the same (low free memory issue). Unfortunately, I can't resolve this issue since I can't prevent Android OS from killing the background apps (in this case, Unity). In native Android apps, Activity classes have certain callback functions that lets them save their data before they are killed but it is not possible to do so in a Unity app.

You said that the app sometimes restarts after 2 shots but sometimes after only a single shot. If the issue was related to a code I wrote, the app would always restart after the first shot.

I don't think you can resolve this OS-related problem. You will have to use a solution that renders the camera inside Unity (i.e. one that doesn't launch native camera apps). One example is NatDevice (I haven't used it myself).

CameronGoosen commented 3 years ago

Thanks for the reply @yasirkula !

That's really unfortunate. Thanks for the NatDevice recommendation, we were already using it but upgraded to this addin because we needed to be able to use the device flash.

This issue is so frustrating, I've been stuck on it for many days now, and it makes no sense to me that the app is being forced closed by the OS even when there are no other apps running and I'm testing on the most basic of Unity apps. The camera intent should never be this intensive on the OS.

yasirkula commented 3 years ago

I unfortunately can't think of any other reasons. I find it unlikely that it is something else because otherwise the app would always restart after the first shot, IMHO.

Dahka commented 3 years ago

Hello, first of all thank you for the great plugin. Unfortunately I am consistently having the same issue as described above in a few phones, when coming back from the native camera the app restarts. Here is a piece of the logcat where I found where the error is happening. I can also upload the full logcat if desired:

2021-11-16 14:39:00.057 791-791/? E/lowmemorykiller: Error writing /proc/2543/oom_score_adj; errno=22 2021-11-16 14:39:00.058 2296-4778/? I/ActivityManager: Existing provider com.RadarStudio.RadarFit/com.yasirkula.unity.NativeCameraContentProvider is crashing; detaching ProcessRecord{cb87e0f 1100:com.android.camera/u0a59} 2021-11-16 14:39:00.058 2296-4778/? I/ActivityManager: Process com.RadarStudio.RadarFit (pid 2543) has died: fore BTOP

Is there any help you could provide? I saw the oom_score_adj is the value to determine if the process should be killed when low on memory, is there anywhere I could set this value? Thank you for your time

yasirkula commented 3 years ago

In my previous investigations, I didn't find a way to change that value (oom_score_adj) but can't say with full certainty that there isn't a way. The only reliable way to resolve your issue would be to use a different plugin which renders camera controls inside Unity so that you won't be leaving Unity at all. I don't know if there is such a plugin which is free.

ghoenicka commented 2 years ago

Hello Mr. Yasirkula.

Same here on take a photo:

11-25 11:58:05.641 6556 6654 I Unity : 11-25 11:58:06.019 1764 2007 I Timeline: Timeline: Activity_windows_visible id: ActivityRecord{b22b087 u0 com.erdetech.bildksuite/com.unity3d.player.UnityPlayerActivity t54278} time:314627445 11-25 11:58:16.874 1764 2189 I WindowManager: WIN DEATH: Window{7a051e3 mode=0 rootTaskId=54278 u0 com.erdetech.bildksuite/com.unity3d.player.UnityPlayerActivity} 11-25 11:58:16.874 1764 2189 W InputDispatcher: Attempted to unregister already unregistered input channel '7a051e3 com.erdetech.bildksuite/com.unity3d.player.UnityPlayerActivity (server)' 11-25 11:58:26.244 1764 2022 D Boost : hostingType=content provider, hostingName={com.erdetech.bildksuite/com.yasirkula.unity.NativeCameraContentProvider}, callerPackage=com.android.camera, isSystem=true, isBoostNeeded=false. 11-25 11:58:26.245 1764 2022 I ActivityManager: Start proc 9626:com.erdetech.bildksuite/u0a295 for content provider {com.erdetech.bildksuite/com.yasirkula.unity.NativeCameraContentProvider} caller=com.android.camera 11-25 11:58:27.379 2622 2622 D RecentsImpl: mActivityStateObserver com.unity3d.player.UnityPlayerActivity 11-25 11:58:27.379 2622 2622 W RecentsImpl: onResumed className=com.unity3d.player.UnityPlayerActivity mIsInAnotherPro=false 11-25 11:58:27.380 9626 9626 W Looper : PerfMonitor looperActivity : package=com.erdetech.bildksuite/com.unity3d.player.UnityPlayerActivity time=0ms latency=447ms running=0ms procState=2 ClientTransaction{ callbacks=[android.app.servertransaction.TopResumedActivityChangeItem] } historyMsgCount=1 (msgIndex=1 wall=448ms seq=3 running=128ms runnable=29ms io=198ms h=android.app.ActivityThread$H w=159)

Just in case...

Thank's for all your plugins :)

yasirkula commented 2 years ago

If you can't reproduce this issue at every attempt or after restarting the phone, it is also likely memory issue.

ghoenicka commented 2 years ago

If you can't reproduce this issue at every attempt or after restarting the phone, it is also likely memory issue.

Is a random behavior. Sometimes occurs at first attempt.. and others after third or fourth one.. also occurs on "Record Video" function.

image

yasirkula commented 2 years ago

Yeah when it's completely random, it's a good indication that it's a memory issue. Either device has low RAM or the game is consuming too much RAM already.

ghoenicka commented 2 years ago

Yeah when it's completely random, it's a good indication that it's a memory issue. Either device has low RAM or the game is consuming too much RAM already.

Spec phone: Redmi Note 8 / Ram: 4Gb

my app, on the moment to call "takepicture" function have 200mb use.. and the post restart. image

maybe there's a memory leak on the "crop image" function after the pictures is taken. Is there any option to avoid this method calls?

very appreciate for your feedback

yasirkula commented 2 years ago

Although your device has 4 GB RAM, it might be consumed by a lot of other apps and the OS itself. OS might also be preserving some of this 4 GB RAM for high priority OS tasks. If this issue isn't related to memory, then I have absolutely no idea what the cause of the issue is :D Native logs give no insight about the issue. I don't know the crop function you've mentioned.

ghoenicka commented 2 years ago

Although your device has 4 GB RAM, it might be consumed by a lot of other apps and the OS itself. OS might also be preserving some of this 4 GB RAM for high priority OS tasks. If this issue isn't related to memory, then I have absolutely no idea what the cause of the issue is :D Native logs give no insight about the issue. I don't know the crop function you've mentioned.

Screenshot_2021-11-26-14-11-29-187_com erdetech bildksuite

This "crop function"

yasirkula commented 2 years ago

I'm assuming this is my Image Cropper plugin (nice UI retouch BTW). After cropping the Texture retrieved via NativeCamera, you can Destroy it (the original Texture) since you no longer need it.

ghoenicka commented 2 years ago

I'm assuming this is my Image Cropper plugin (nice UI retouch BTW). After cropping the Texture retrieved via NativeCamera, you can Destroy it (the original Texture) since you no longer need it.

:) .. yes indeed. I'm big fan of yours plugins.

Ok. the thing is.. for some weird situation, this "Image Cropper" is called after a NativeCamera.TakePicture event. So I tested deleting the pluging of Image Cropper and "magic happens".. stopped showing after NativeCamera.TakePicture.

Also I also set the "maxSize" value to "512" (prev: SystemInfo.maxTextureSize) and the crashed occurs after a third attempt.

maxSize determines the maximum size of the returned image in pixels on iOS. A larger image will be down-scaled for better performance. If untouched, its value will be set to SystemInfo.maxTextureSize. Has no effect on Android

I'll keep searching how reduce memory consumption.

Thnks for all.

yasirkula commented 2 years ago

Reducing maxSize is a good optimization 👍 If your app needs an image cropper, I don't think you should delete it from the project.

Does reducing maxSize even further to 32 (for testing purposes) prevent crashes?

Dahka commented 2 years ago

Hello again, as before I still am having the issues with the app restarting after taking a picture, the problem increased a bit as our app increased in complexity and memory usage. However I came with a solution of saving the state of the app before taking the picture and if it restarts and find that save file we send the user right back to where he was. My only issue is that the image path is returned on the callback. My question is: is there any way to get the temporary path the picture was saved to outside of the callback? And if not, is there a way to set a specific path for the picture to be save to?

As always, thank you very much for the plugin and any help you can provide!

p.s.: I found this page while searching for solutions: https://dontkillmyapp.com/problem found it interesting that it might not only be memory but also battery saving issue

yasirkula commented 2 years ago

On Android, the path is probably a combination of Application.temporaryCachePath and IMG_camera.jpg: https://github.com/yasirkula/UnityNativeCamera/blob/5f57882eafcef31dfd5c9eff65200b59671c2d52/.github/AAR%20Source%20(Android)/java/com/yasirkula/unity/NativeCameraPictureFragment.java#L55

On iOS: https://github.com/yasirkula/UnityNativeCamera/blob/5f57882eafcef31dfd5c9eff65200b59671c2d52/Plugins/NativeCamera/NativeCamera.cs#L234

https://github.com/yasirkula/UnityNativeCamera/blob/5f57882eafcef31dfd5c9eff65200b59671c2d52/Plugins/NativeCamera/NativeCamera.cs#L137-L149

Dahka commented 2 years ago

Thank you very much for your quick and helpful reply! The issue only happens on Android devices so I'm only treating those cases, however I faced another issue: When trying to find the photo via Application.temporaryCachePath + Path.DirectorySeparatorChar + "IMG_camera.jpg" the path returned is: /storage/emulated/0/Android/data/(packageName)/cache/IMG_camera.jpg However the photo is actually saved on the path: /data/user/0/(packageName)/cache/IMG_camera.jpg

I'm trying to find solutions online however unity seems to have basically no documentation on temporary cache path, which seems to be the same as the persistent data path, with the difference being the last folder is called "files" instead of "cache" For now I'm checking both paths on hand and it works but it feels a bit too hardcoded

yasirkula commented 2 years ago

I see. On Android, instead of Application.temporaryCachePath, try this:

using( AndroidJavaObject unityClass = new AndroidJavaClass( "com.unity3d.player.UnityPlayer" ) )
using( AndroidJavaObject context = unityClass.GetStatic<AndroidJavaObject>( "currentActivity" ) )
{
    string cachePath = context.Call<string>( "getCacheDir" );
}
rikensonaniNB commented 2 years ago

hello yasirkula sir thank you for providing amazing plugin i am trying to pick image from gallery with maxsize 1024 it's working fine but i trying native camera to take photo with maxsize 1024, 512, 256 every time restart my app.

please check if you found any solution then let me know it's very important to me.

native gallery is working fine then why native camera creating this issue s15 s16 s17

yasirkula commented 2 years ago

Max Size unfortunately can't resolve this issue because the app is restarted before that. NativeCamera simply uses more system resources (RAM) than NativeGallery which is why it's more possible for it to trigger the app restart. Since this restart is triggered by the operating system automatically, I don't believe that it can be resolved.

rikensonaniNB commented 2 years ago

if you know another camera package or unity camera example then please share with me thank you

yasirkula commented 2 years ago

Haven't researched it recently so there may be free alternatives. A paid alternative is NatDevice, it renders the camera inside Unity so it won't suffer from this issue.

rikensonaniNB commented 2 years ago

hello @yasirkula i have one question if app is crash after take photo then not automatic open app again. but in this case take photo in android then app is automatic restart. if you have any idea about this then let me know

yasirkula commented 2 years ago

Yes app doesn't crash but restarts in this scenario. If your app doesn't restart and you see a popup saying that the app has crashed, then that's another issue and you should check logcat logs to see what happened.

rikensonaniNB commented 2 years ago

yes exactly my app is not crashing. but is restarting so i ask you any another issue or not. if you know any solution then please let me know it's very important for me. i am finding log and all last 5 days but didn't getting any proper reason for restart app after capture photo from camera thank you for support

yasirkula commented 2 years ago

That's the same issue. You can check out this discussion to learn more about it.

rikensonaniNB commented 2 years ago

please check this log i am getting from logcat. also i add permission and testing but still same issue.

E/Util: writeImageDataToRequestedUri : failed to make directory or the directory already existed. Not starting debugger since process cannot load the jdwp agent. E/SemCaptureResult: UnsupportedOperationException - CaptureResult.Key(samsung.android.control.cameraType) is not supported - java.lang.IllegalArgumentException: Could not find tag for key 'samsung.android.control.cameraType') Camera3-OutputStream: returnBufferCheckedLocked: Stream 0: Error queueing buffer to native window: No such device Camera3-Device: Can't return buffer to its stream: No such device (-19) /CameraService: onTorchStatusChangedLocked: cannot get torch status of camera 1: No such file or directory (-2) camxchinodewrapper.cpp:1717 ExecuteProcessRequest() Node::MfnrPostFilter_ChiNodeWrapper0 i=0, Output Port/Image Buffer is Null

yasirkula commented 2 years ago

If camera encounters a fatal exception, either the Unity app should crash completely or Unity app should resume as normal. When it restarts, it isn't caused by an exception, unfortunately we can't do anything to prevent this from happening. Operating system is responsible for that restart. That's how Android ecosystem's Activity lifecycle works. You can verify this by testing your app on a more powerful phone, it won't restart there.

rikensonaniNB commented 2 years ago

sometime same issue fetching on image or video pick using native Gallery. i am checking on 8GB RAM and 124GB Storage but sometime app restart after pick video or image. only on android device if you have any idea why app is restart. i have try lost of solution but didn't getting proper solution. if you have any idea then please let me help to solve this issue

yasirkula commented 2 years ago

The words "sometimes" and "restart" strongly indicate the same problem. That device must have a lot of background tasks and the OS must be reserving a very small amount of RAM per app that it encounters all those restarts. I would recommend simply accepting this limitation because it's out of our hands.

lucasroth commented 1 year ago

Hi, first of all thanks for your grate work! Some Android devices are showing low memory issues, that happens due to apps running in background, any ideas about how to give an advice to the user that has low memory before crash? In my iphone SE iOS 15.4.1 only crash in the first run of the app, on second and further works fine. Any ideas about this?

yasirkula commented 1 year ago

I haven't used this property, but: https://docs.unity3d.com/ScriptReference/Application-lowMemory.html

Also on Android, there is Adaptive Performance Package which I've also not used.

fedekilius commented 1 year ago

Hi, same situation here. It happens in every single device with Android 13 that I tried, is there any walk around? The lowMemory trigger never fires, I tried with largeHeap and is the same situation. Why it doesnt happen with other apps that are using the native camera? Thanks!

yasirkula commented 1 year ago

Then I think lowMemory requires Unity activity to have focus. There might be two cases for other apps:

Jonathan5579 commented 1 year ago

Not related to Unity, but while developing an android app using jetpack compose, launched the native camera app multiple times to collect photos and found the same app restarting. I'm testing on a Galaxy Tab Active Pro.

I was sure I wasn't doing anything wrong, really thanks yasirkula for discussing and explaining this behavior. As explained here I will change the way I handle the camera to not launch native one.

And again thanks!

pabloRadmas commented 8 months ago

I'm having the same issue, my activity restarts but my app doesn't crash, and i can't see anything in logs... I couldnt' find any other info

yasirkula commented 8 months ago

This issue is "Won't Fix" for the foreseeable future since there isn't a solution to this according to my research.