I'm writing an Android app that the user can run in the background to detect when the camera is turned on(by the user, or by other apps). This should also detect even in the scenario where other apps (like facebook, instagram) do not use the default android camera app.
I've been searching but haven't seen any broadcasts that are sent whenever the camera is activated. So far, I've seen that there's Camera.open() that throws a RuntimeException if the camera is already in use by another app. So one way is to keep polling Camera.open(), but it's really expensive. Is there a better alternative?
Thanks
Edit: Sorry i didn't mention it clearly but what I want to do is to create some kind of camera usage log: what time it was turned on/off, how long was the duration, etc..
What happens internally is Camera API talks to CameraService and CameraService has mBusy variable which tracks whether camera is busy or not. And there is no API to get this mBusy flag out of service (without calling open())
I may be wrong, because I just glanced over it.
You can download Android source code (http://source.android.com/) and take a closer look yourself.
Files which could be interesting for you are:
\frameworks\base\services\camera\libcameraservice\CameraService.cpp
\frameworks\base\libs\camera\Camera.cpp
\frameworks\base\core\java\android\hardware\Camera.java
\frameworks\base\core\jni\android_hardware_Camera.cpp
One other idea. Try to look in the logs. In the case, if logs aren't turned off for Camera services/API, you can parse the logs to check when the camera was turned on or off. However, it may not work in OS 4.1, because Google limited reading of system logs.
Related
I'm experimenting with the Camera class. During experimentation on my Samsung Galaxy Note phone (not emulator) to open the camera im getting the error Fail to connect to camera service. I'm aware this was caused by my app not previously releasing the camera object.
I've tried stopping the debugging session and removing my app from the Application Manager but still the Camera.open(myCamId) refuses to return back a valid camera object. And for the record this worked fine the first go around.
I'm confident i can get things moving again with a phone restart but is there a quicker way to release the previously opened camera object? And no i cant simply release the camera object at this stage before re-opening bc the Camera.open is not returning ANY camera object to release.
Thanks for the tip.
If you have root access, you can kill the mediaserver process. It will restart automatically, but most likely the camera will now get connected.
No, as far as I know you have to reboot your phone.
My app main usage is overlay, the overlay is running from a service.
Android Security add the nice "Screen Overlay Detected"
I want to avoid "Screen Overlay Detected" when user tries to change permissions. so... I've add an AccessiblityService that detects:
if ( event.getPackageName().equals("com.google.android.packageinstaller") ){
stopService(myServiceIntent);
}
However, even now I see this message popping. (when my service is stopped...).
I saw Twilight does it without problem.
What am I missing?
p.s. - I've also tried building a signed apk but saw exact same behavior.
It seems I've been able to resolve this.
a) stopService isn't assured your service will be stopped.
as described here :
It will not be destroyed until all of these bindings are removed. See > the Service documentation for more details on a service's lifecycle.
b) I was able to kill my service by sending intent that called stopSelf().
However process killing/starting can be slow.
c) Best resolution: so it seems Android checks for view visibility. no need to kill services or do anything more complicated.
Current way I'm doing it:
- AccessibilityService (already used by my app) monitor "com.google.android.packageinstaller" though it can be refined to class: "com.android.packageinstaller.permission.ui.ManagePermissionsActivity"
Once detected in this class, we send Intent to "duck", and when we're out, we send another intent that we're back on.
The service handles those calls by:
[ourView].setVisibility(View.INVISIBLE); // when permission settings shown
[ourView].setVisibility(View.VISIBLE); // when normal flow
As long as Android 6.x is buggy on some devices where this "overlay alert" is displayed without any reason (on 2 to 5% of the devices according to my analytics data), the best solution is to avoid the whole permission process by defining the targetSdk to 22. Take care that you can't downgrade the target sdk for a new version or this will induce a INSTALL_FAILED_PERMISSION_DOWNGRADE error when the user updates requiring an unisntall/install of the app.
I can't seem to find anything related to finding out what application got audio focus. I can correctly determine from my application what type of focus change it was, but not from any other application. Is there any way to determine what application received focus?
"What am I wanting to do?"
I have managed to record internal sound whether it be music or voice. If I am currently recording audio no matter the source, I want to determine what application took the focus over to determine what my application need's to do next.
Currently I am using the AudioManager.OnAudioFocusChangeListener for my application to stop recording internal sounds once the focus changes, but I want the application's name that gained the focus.
Short Answer: There's no good solution... and Android probably intended it this way.
Explanation:
Looking at the source code, AudioManager has no API's(even hidden APIs) for checking who has Audio Focus. AudioManager wraps calls to AudioService which holds onto the real audio state. The API that AudioService exposes through it's Stub when AudioManager binds to it also does not have an API for querying current Audio Focus. Thus, even through reflection / system level permissions you won't be able get the information you want.
If you're curious how the focus changes are kept track of, you can look at MediaFocusControl whose instance is a member variable of AudioService here.
Untested Hacky Heuristic:
You might be able to get some useful information by looking at UsageStats timestamps. Then once you have apps that were used within say ~500ms of you losing AudioFocus you can cross-check them against apps with Audio Permissions. You can follow this post to get permissions for any installed app.
This is clearly a heuristic and could require some tuning. It also requires the user to grant your app permissions to get access to the usage stats. Mileage may vary.
Looking at the MediaContorller class (new in lollipop, available in comparability library for older versions).
There are these two methods that look interesting:
https://developer.android.com/reference/android/media/session/MediaController.html#getPackageName()
https://developer.android.com/reference/android/media/session/MediaController.html#getSessionActivity()
getPackageName supposedly returns the current sessions package name:
http://androidxref.com/5.1.1_r6/xref/frameworks/base/media/java/android/media/session/MediaController.java#397
getSessionActivity gives you a PendingIntent with an activity to start (if one is supplied), where you could get the package as well.
Used together with your audio listener and a broadcast receiver for phone state to detect if the phone is currently ringing you might be able to use this in order to get a more fine grained detection than you currently have. As Trevor Carothers pointed out above, there is no way to get the general app with audio focus.
You can use dumpsys audio to find who are using audio focus. And, you can also look into the results of dumpsys media_session.
And, if you want to find who're playing music, you can choose dumpsys media.audio_flinger. For myself, I switch to this command.
I'm currently using the READ_PHONE_STATE permission in Android to pause my media player when there's a call, and to resume playback when the call is over. The permission seems to scare a lot of people, so I was wondering if there was an alternative to catching the starting and stopping of a phone call without it. Any help is appreciated. Thanks!
If you want to adjust your audio output in response to something else wanting to perform audio output (e.g., an incoming phone call), look into Android's audio focus support.
READ_PHONE_STATE, as noted, is a bit of a scary permission. Moreover, it only deals with phone calls, and not other things that might need the same capability (e.g., VOIP calls, as AFAIK those don't tie into READ_PHONE_STATE-enabled stuff).
Unfortunately, audio focus is not a substitute for READ_PHONE_STATE. My app has to use both. The standard phone app on my Galaxy S3 I9300/ Android 4.3 doesn't seem to request the audio focus at all. The TelephonyManager class gives you a way to detect the end of the phone call (by sending the CALL_STATE_IDLE state update). The AudioManager doesn't seem to do anything similar, so even if audio focus could be used, it would not be as useful. And, from what I see in the documentation, there doesn't seem to be a narrower permission than READ_PHONE_STATE that would allow the app to read the phone state but not the call information. If I'm wrong about any of this, please correct me.
Unfortunately, audio focus is not a substitute for READ_PHONE_STATE. My app has to use both. The standard phone app on my Galaxy S3 I9300/ Android 4.3 doesn't seem to request the audio focus at all. The TelephonyManager class gives you a way to detect the end of the phone call (by sending the CALL_STATE_IDLE state update). The AudioManager doesn't seem to do anything similar, so even if audio focus could be used, it would not be as useful. And, from what I see in the documentation, there doesn't seem to be a narrower permission than READ_PHONE_STATE that would allow the app to read the phone state but not the call information. If I'm wrong about any of this, please correct me.
I know this is a very broad question on how to prevent an Android app from crashing. I understand there could be many reason behind the app crashing.
Primarly my app crashed because of 2 main reasons :-
1) Out of memory while taking pictures and storing byte array in memory. I also uses bitmap to redraw the image captured.
2) Camera issues. App has a feature of autofocusing on touch events and while actually taking the pictures. These autofocus often crashes into each other. I have handled it using cancelling any existing autofocus code and discarding any further on touch events using flags once the picture is being captured. But still some time app crashes due to unknow reason.
There may be more reason behind app crashes. So my question is
1) Is there a way I can identify that app has crashed and handle that event so that instead of just showing the messsage ""UnForunately App has stopped working. Force Close." I can give a better user friendly message to user and stop the app programatically.
2) If out of memory every happens, is there a way I can identify that my App is running low on allocated memory and I can handle the scenario. OnLowMemory will give the low memory status of entire device, not just my application. I use lot of cache to store the images & heap for bitmap.
3) If the camera ever crashes (because of any reason), is there a way I can handle the scenario.
Thanks in advance.
Gagan
The android application usually crashes if there is a run time error.
You can locate and avoid the crash,using android monitor and write your code in try catch block.
Example:
try{
"your code which might give error"
}
catch(Exception e)
{
Log.e("TAG or Some text",e.toString());
finish(); //or some methods you want to do if the code inside try block fails;
}
Now, the app wont crash and you can locate the error in android monitor by searching for TAG error.