It is necessary for my application to keep the camera captured until released manually by an Activity (I realize this is bad practice, as no other applications will be able to use the camera). I used to be able to do this by avoiding the camera.release() call in the surfaceDestroyed function from CameraPreview, but this no longer works after 2.1.
Is there any way to keep the camera in captivity, without it being automatically released after surfaceDestroyed?
As a workaround question to answer instead of the previous one, is there any way to take a picture from within a service, without the preview view inflated?
You may be able to call camera.lock() to re-obtain the lock on the camera hardware. Failing that you can reopen the camera.
However, the drawback to this is much worse than preventing other apps from accessing the camera. This will also rapidly drain the battery, because it keeps the camera sensor and DSP powered. According to this thread, that could potentially kill a battery dead in two hours.
Related
This question is for Android developers who are familiar with the Activity Lifecycle.
I'm developing an app that performs face detection and facial landmark recognition.
The according machine learning models take a long time to be parsed from the SD storage and loaded into memory. On current average Android devices, it easily takes up to 20 seconds. By the way, all of this face analysis stuff and model loading happens in C++ native code, which is integrated using the Android NDK + JNI.
Because the model loading takes a long time, the actual parsing and loading is scheduled early in the background via AsyncTasks, so that the user does not notice a huge delay.
Before the actual face analysis is performed, the user can take a selfie via the MediaStore.ACTION_IMAGE_CAPTURE. This will call a separate camera app installed on the device and receive the picture via onActivityResult.
Now the problem starts: Almost always the whole app process will be killed while the user is in the separate camera Activity/App. Mostly it seems to happen right before returning from the Camera app (the timing seems odd). I did another test to confirm that it happens when the capture button is pressed inside the camer app. At that moment, my app is killed. When pressing the 'Accept image' button, the app is recreated. The reason given in logcat by the ActivityManager for the process kill is 'prev LAST' (I've found nothing via Google on the meaning of this, but I saw that many other apps are also killed with this reason, so it seems to happen quite often).
Thus, all of the Activities of my app need to be recreated by Android (fine by me, because it happens fast), but also the face analysis models must be loaded again from scratch, and the user will notice a huge delay before his selfie can be processed.
My question is: Is there any possibility to tell Android that an Activity/App has a legitimate reason to not be killed while being in the background temporarily to get a camera picture? After all, the ActivityManager makes a wrong decision to kill the app. Having to reload the models so frequently takes up a lot of CPU and memory resources.
It seems like an oversight in the Android lifecycle architecture. I know that few apps have the specific requirements of my app, but still, it seems stupid. The only way I can think of to 'fix' this issue is to implement my own camera Activity inside the app, but this goes counter Android's own best practices.
There is also some 'android:persistent' flag that you can stick to your Activity via AndroidManifest.xml, but the docs are totally unclear about the implications of this. See the docs on this.
By the way: onDestroy is not called when the app process is killed. I've read somewhere that there is no guarantee that onDestroy will be called, and this is actually not a problem for me. Although I wonder why the Android docs do not state this clearly.
Almost always the whole app process will be killed while the user is in the separate camera Activity/App
This is not surprising. A camera app can consume quite a bit of memory, so Android needs to free up memory by terminating background apps' processes.
After all, the ActivityManager makes a wrong decision to kill the app
Given that a likely alternative is the OS crashing, I suspect the user would agree with the OS decision to terminate your process.
Having to reload the models so frequently takes up a lot of CPU and memory resources.
Then perhaps you should not be starting another app from yours. Take the photo yourself. Use the camera APIs directly, or use libraries like Fotoapparat and CameraKit-Android as simpler wrappers around those APIs.
The only way I can think of to 'fix' this issue is to implement my own camera Activity inside the app, but this goes counter Android's own best practices.
By that argument, no devices would ever have a camera app, as writing any camera app "goes counter Android's own best practices".
Any app that needs a camera must use the camera APIs (directly or indirectly) to have any shot at reliable behavior. You are assuming that thousands of camera apps are all properly written and will correctly honor your ACTION_IMAGE_CAPTURE Intent (e.g., putting the results in the place that you designate with EXTRA_OUTPUT). Many camera apps have buggy ACTION_IMAGE_CAPTURE implementations. ACTION_IMAGE_CAPTURE is not unreasonable for cases where you and the user can live without the picture being taken (e.g., a note-taker app that has an "attach photo" feature), but that would not seem to be the case with your app.
If I run an image processing app on Android, which will be better in terms of memory/cpu usage and heating issue?
Run camera with the preview.
Run camera in a background service. This says background service takes up a lot of memory( I used to think opposite ).
The reason I ask this is because I want to run the app 24/7, but I'm not sure which approach will be better with my purpose. I did test my app running camera with the preview and it stop due to heat after like 1 week.
Thanks.
The screen uses a lot of power, so leave it off if at all possible.
The camera API itself doesn't care if you're in a foreground app or in a background service, but the more simultaneous outputs you request, the higher the power consumption will likely be. Similarly, the higher the output resolutions you ask for are, the higher the power consumption.
You can have a foreground app with no preview, if you're using camera2; even with camera1, you can just add a dummy SurfaceTexture member to your activity/etc and set it as the preview target, so that you don't pay the cost of actual GPU activity.
That still has the overhead of the camera API pushing pointless images to that SurfaceTexture, which you can only avoid with camera2.
Obviously running camera continuously for a long time in preview mode made your device warm even if U have a high configuration device.In my suggestion You can tolerate the memory issue but not heating issue because it leads to many other harmful issue in your device(due to over heating).So go for background service,hope this will not heated your device as comparison to preview mode .
I'm trying to open camera and display using SurfaceView. This delays the loading of the activity for a really long time. So I'm wondering what are the best practices of opening camera.
From http://developer.android.com/training/camera/cameradirect.html :
Getting an instance of the Camera object is the first step in the
process of directly controlling the camera. As Android's own Camera
application does, the recommended way to access the camera is to open
Camera on a separate thread that's launched from onCreate(). This
approach is a good idea since it can take a while and might bog down
the UI thread. In a more basic implementation, opening the camera can
be deferred to the onResume() method to facilitate code reuse and keep
the flow of control simple.
So the official recommendation is to use a separate thread. This will mean modifying the activity to be able to deal with a state where the camera isn't open yet, and could even fail to open entirely.
If you aren't comfortable with multithreading and Android app development, it's probably best to just let the Activity start stall. On most devices the camera opens very quickly.
While it's very difficult to make the camera start faster, you can make the Activity start faster by offloading camera.open() onto a background thread via an AsyncTask or some other method. You can also delay the camera.open() call by some arbitrary number of milliseconds after onResume(), so that the Activity is already visible before camera loading happens.
I don't recommend the AsyncTask method -- making camera loading an asynchronous operation is very prone to errors.
The latter method is also pretty useless as the camera won't be usable until after it loads anyway.
I have an object sitting in memory on the application that I'm using, and on a button press I do a startActivityForResult and launch the camera application, so I can attach a photo to that object. On every phone/tablet I've ever tested with (somewhere around 15 or so) it works completely fine, but for some reason with the Motorola Droid 3 (CDMA version) once the camera application starts, it's like onDestroy is called... even though it returns to my app after the photograph is snapped, all of the variables held in memory are erased. Can someone direct me as to how I can fix this please?
I'm guessing what's happening is that the camera app uses a big enough chunk of memory that android needs to destroy the paused activity. If you look at this page,
http://developer.android.com/reference/android/app/Activity.html
It shows that possibility pretty clearly.
You are seeing differing behavior on different devices because different devices have different apps loaded into memory and different amounts of memory to begin with.
If you need to save state in your app, you can hook in at onSaveInstanceState() and onRestoreInstanceState(). Here's a post that talks about it in more detail.
How to save an activity state using save instance state?
In summary, don't depend on the state being the same when you resume an activity. If you depend on that happening, you need to handle it yourself.
How do you prevent the screen from going off when recording is in process. If recording is in process, and there's no other activity like using arrow keys, or the keypad, the screen goes off and when it's brought back to life, the preview is corrupted.
What do you mean with "recording in progress"? You have an app that is recording something?
The easiest way (which doesn't require any additional permissions) is to give any of your views android:keepScreenOn=true (there's also setKeepScreenOn()).
If you want to be hardcore, you can request a wakelock permission, but that should not be necessary - if you have a UI, keepScreenOn is a much more elegant solution.