Android use device flash as torch - java

There is a need to use the built in device camera flash as a torch.
Unfortunately I don't have access to an Android device so I can only use the Android emulator.
How can I validate that my code does work?
I have been trying several times to update my app with different ways to access the camera flash and each time the app was crashed.
My app minimum OS version is 2.2,
At the moment I'm using the following code
private void turnFlashOn() {
camera = Camera.open();
Parameters p = camera.getParameters();
p.setFlashMode(Parameters.FLASH_MODE_TORCH);
camera.setParameters(p);
camera.startPreview();
}
private void turnFlashOff() {
camera = Camera.open();
Parameters p = camera.getParameters();
p.setFlashMode(Parameters.FLASH_MODE_OFF);
camera.setParameters(p);
camera.stopPreview();
}
Haven't tested it yet.
What is your way to use the camera flash?
Thanks!

The first two errors here is that you have called Camera.open() twice and never close it. You need to open it in onResume() and close it in onPause(), and in between operate on the Camera handle you obtained.

You can debug on emulator and mock camera class (with jmockit) , but you will have to be careful - not every camera on real devices supports torch mode ( or have a flash at all) - so you will have to check whether camera object supports this.
Once you got your code working correclty, you will still have to test it on real device
( hint: you can recruit testers on android developers mailing lists if you ask politely and provide signed APK somewhere on the web so people can install it )

Related

Audio Stops Recording After a Minute

I am trying to do WebRTC, all is working fine but there seems to be an issue, that is, if the screen remains off for more than a minute the audio stops recording, meaning the audio from device stops until I switch the screen on once again.
What I have tried?
1) I have tried setting webSettings.setMediaPlaybackRequiresUserGesture(false); it does no good to the problem.
2) I have also tried adding a wakelock in the activity in which I am doing WebRTC but it also didn't work.
Here are the permissions declared in Manifest:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
Here in activity, I am granting permission for the microphone in WebChromeClient:
#Override
public void onPermissionRequest(final PermissionRequest request) {
request.grant(request.getResources());
}
What I want?
I want to be able to continue call without disrupting the user to turn screen back on again. Please point me in right direction.
Thanks!
Update: I tried loading the WebRTC url in Chrome and the same thing is happening, that is, audio stops recording from my device.
Update 2: Adding log when audio stops coming from the device.
2019-08-06 17:18:47.266 4332-22405/? V/APM_AudioPolicyManager: getAudioPolicyConfig: audioParam;outDevice
2019-08-06 17:18:47.266 4332-22405/? V/APM_AudioPolicyManager: getNewOutputDevice() selected device 2
2019-08-06 17:18:47.266 4332-22405/? V/APM_AudioPolicyManager: ### curdevice : 2
2019-08-06 17:18:47.307 4332-22405/? V/APM_AudioPolicyManager: AudioPolicyManager:setRecordSilenced(uid:99066, silenced:1)
2019-08-06 17:18:47.308 4332-22405/? V/APM_AudioPolicyManager: AudioPolicyManager:setRecordSilenced(uid:11556, silenced:1)
Update 3: Tried initializing WebView in a Foreground Service still same result.
Update 4: Tried a demo call on https://appr.tc/ using Chrome(76.0.3809.132). Observed the same result.
Update 5: Tried a demo call using Firefox and it worked FLAWLESSLY which lets me thinking that is it a Chromium bug?
Update 6: Filled a bug report
Android will automatically destroy your activity on a few minutes after leaving foreground that will cause the audio recording to turn off.
I have working with webrtc on android, if you want to create call and video call with webrtc on Android, I suggest to use native webrtc and implement everything related to webrtc on foreground service. Foreground service will ensure your recorder and camera to keep running event when activity is destroyed.
For reference, here the google sample for implementing webrtc native
https://webrtc.googlesource.com/src/+/master/examples/androidapp/src/org/appspot/apprtc
You should work on keeping the screen on in that activity during the call and prevent if from dimming.
Use this:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
and after your call is done:
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
Check your Chrome/Android version due to this issue with WebRTC on Android:
Issue 513633: WebRTC call in Chrome on Android will be cut off 1 min after screen off
WebRTC is supported by default in Chrome so... it should work.
BTW, if you dont't need WebRtc or want try to implement in a background service...
Interest readings:
1 - recording-when-screen-off
As the post says, keep in mind:
To call:
startForeground();
Use START_STICKY:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
2 - how to implement a recorder
As the post says, keep in mind permissions:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Background services with Apache Cordova
With cordova and a webview you need to use a plugin to run code in background as a service too.
Take a look at this link:
cordova plugin
Another choice with Cordova is to do your own plugin like this:
custom plugin - background video recorder
Obviously, it's no usual task, because all your implementation, it's just a WebView. Which very hard to align with such long living task and lifecycle inside Android. For ex. every VoIP application we did, had services in background, to keep connection alive, with wake locks. This was only one way to ensure about stability of the call.
However, I think you could try to do the same. By managing your WebView work inside Service. For this purpose, you could consider moving some calling logic into another view, and starting new Service and creation new Window. This will ensure your Window will be alive, during all the lifecycle of the Service.
Smth like.
public class ServiceWithWebView extends Service {
#Override
public void onCreate() {
super.onCreate();
final WindowManager windowManager = (WindowManager)
getSystemService(WINDOW_SERVICE);
params = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY);
final LinearLayout view = new LinearLayout(this);
view.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout
.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT));
WebView wv = new WebView(this);
wv.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout
.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
view.addView(wv);
wv.loadUrl("http://google.com");
windowManager.addView(view, params);
}
}
It is possible that the problem is in battery optimization. The device cleans up the background processes and finds there your audio recording screen working on the background. try to add the app to the list of Battery Best Performance list. Search how to do that on your device.
For my case even important background tasks as accessibility service is forced to stop under that battery optimization algorithm. To allow my service to work all the time, the user should add the app to the whitelist of battery best performance rule.
I hope it can help you.

How to switching audio between Bluetooth audio devices on android using programmatically

It's let me confused for a long time.
I have two bt audio devices connected on android phone, and I want to switch specific bt audio device using programmatically.
I search keyword about a2dp, media router and audioManager than seems can't do this thing...
I only way found the function is:
BT devices=> A and B connected on an Android phone.
And right now the media play to A and I want to switch to B
Step1: A, B unpair on Android phone.
Step2: A pair on Android phone.
Step3: B pair on Android phone.
The media play output is B,
seems lastest pair Bluetooth device is media play output.
Can anyone give me some advice or direction?
Thanks, guys
Documentation says it can only be connected to a single A2DP device at a time, so you should be able to switch between devices by connecting to device you want to use.
You can connect to device by using BluetoothSockets.
EDIT:
I found other solutions, one which I find reliable. Both of them rely on method reflections.
First one is from this post.
1. Get BluetoothA2dp proxy from serviceListener
bluetoothManager.adapter.getProfileProxy(this, serviceListener, BluetoothProfile.A2DP)
private val serviceListener = object : BluetoothProfile.ServiceListener {
override fun onServiceDisconnected(profile: Int) {
if (profile == BluetoothProfile.A2DP) {
bluetoothA2dp = null
}
}
override fun onServiceConnected(profile: Int, proxy: BluetoothProfile?) {
if (profile == BluetoothProfile.A2DP) {
handler.post(btSearchRunnable)
bluetoothA2dp = proxy as BluetoothA2dp
}
}
}
Get "connect" method from reflection.
private val connect = BluetoothA2dp::class.java.getDeclaredMethod("connect",BluetoothDevice::class.java)
Invoke method with proxy as first argument and device as second.
connect.invoke(bluetoothA2dp,device)
Other method used reflection to get createRfcommSocket to circumvent issue with one parameter which you can't normally access. I can post link to it, but problem I had with it is that always lagged main thread, always threw me an error and connected unpredictably.

How to speed up the connection to IP camera in Android app?

I'm developing an Android app (Android 5.1) for playing the video stream from IP camera using the RTSP protocol.
I receive and display video stream using the Android VideoView's standard methods:
videoView.setVideoURI(Uri.parse("rtsp://192.168.1.13:8888/test"));
try {
videoView.start();
}
catch (Exception ex) {
ex.printStackTrace();
}
Everything works fine, but the connection to the camera takes too long.
It takes about 5-7 seconds (too long for my needs) before video starts playing.
Is there any way to speed up the connection time?
Finally found a solution.
The problem was that Android' MediaPlayer, that is a part of VideoView, has fixed buffer size that cannot be changed.
So i used Google' ExoPlayer, which provides such feature.
Making buffer size smaller resolved my problem.
P.S.
Maintaining the resource/connection with VideoView.suspend() or VideoView.pause() to resume stream later doesn't make a thing.

Android GPS does not work until restart on new phones

I have posted about this issue before, and found a few other people who have had the same issue with no solutions found.
I am developing an Android app that submits a JSON query to a server with the obtained GPS coordinates and geocoded Zip Code. For brand new users that have never downloaded the app, GPS does not work whatsoever. It is not until rebooting the phone that GPS will work. After installing the app and then rebooting, the GPS will work every time without problem, even if they restart again.
There is precious little information on this issue, and the only issue I have found refers to using Google Play Location Services, with no further details. Has anyone else had this issue? My development is completely halted until this issue can be resolved.
EDIT:
Here is the link to the MainActivity.java file that calls the geopositioning functions.
Here is the link to the MyLocation.java file that contains the actual logic for multiple sources of geolocation
I have no doubt that there are much better ways of doing GPS. I'm very new to Android development, so any help on this front is very much appreciated.
EDIT 2:
I have wiped my phone with a factory reset, and started from scratch. I still cannot replicate the issue on this device, only on phones using the app for the very first time prior to a restart.
Looks like you're registering both the GPS and NETWORK providers to listen for a location for 10 seconds, and when the timer goes off after 10 seconds you try to get the most recent location from both providers.
There are a few things going on here.
First, you seem to be listening for updates in the wrong method. Your two listeners should look like:
LocationListener locationListenerGps = new LocationListener() {
// This will never be called, its not part of the LocationListener interface - http://developer.android.com/reference/android/location/LocationListener.html
/* public void onStatusChanged(Location location) {
timer1.cancel();
locationResult.gotLocation(location);
lm.removeUpdates(this);
lm.removeUpdates(locationListenerNetwork);
} */
public void onProviderEnabled(String provider) {}
public void onProviderDisabled(String provider) {}
public void onLocationChanged(Location location) {
// This is the correct method to receive location callbacks
timer1.cancel();
locationResult.gotLocation(location);
lm.removeUpdates(this);
lm.removeUpdates(locationListenerNetwork);
}
public void onStatusChanged(String provider, int status, Bundle extras) {}
};
Second, I'd use the ScheduledThreadPoolExecutor or Handler instead of Timer.
From the Timer docs:
Prefer ScheduledThreadPoolExecutor for new code...This class does not offer guarantees about the real-time nature of task scheduling.
If a reboot is required to get the app working, its likely something to do with the Timer not firing after 10 seconds. Note that this doesn't necessarily mean that GPS itself isn't working.
Handler should do the job and it's designed for Android, so I'd suggest using it. It looks like:
Handler handler = new Handler();
handler.postDelayed(getLastLocation, 10000);
...and your GetLastLocation would change to:
Runnable getLastLocation = new Runnable() {
#Override
public void run() {
...
}
}
...and your cancel() and other methods would need to reference the Handler.
Also, note that you're declaring the Location object in your MainActivity with a provider type of NETWORK_PROVIDER, and then setting the lat/long in that object.
public Location mUserCoordinates = new Location(LocationManager.NETWORK_PROVIDER);
So, the location type in MainActivity will always appear to be of NETWORK_PROVIDER, no matter the actual source.
Also, doesn't look like your MainActivity needs to implement LocationListener, as its never registered with the LocationManager.
Finally, instead of using two listeners for GPS and NETWORK, I would suggest using the Fused location provider in Google Play Services, as discussed here:
http://developer.android.com/training/location/receive-location-updates.html
You'll be limited to devices Android 2.2 and up with Google Play Services installed, but in my opinion its worth it to avoid dealing with some of the eccentricities of location in the platform and managing more than one provider. For more about Fused location provider and how it differs from listening directly to GPS and NETWORK providers, see this 2013 Google I/O presentation - Beyond the Blue Dot: New Features in Android Location
Why do you use Google Play Services Location API?
The only new feature provided by Play Services is Geofencing. From your answer i assume that you don't want to use Geofencing but just "usual" location requests.
The Android platform provides a great API for such requests which does not requires Google Play Services. I never had the problem you described when using it.
Note that although Google claims the Play Services to be better than the Android API, this is not true since API 9 (Android 2.3), as long as you use the newer LocationManager.requestLocationUpdates methodes that don't require a provider to be specified.
See: http://developer.android.com/guide/topics/location/strategies.html
I had the same issue with the regular Location API earlier. I swiched to Play Services, and it seemed to work. Lately sometimes I experience this issue again with Google Play Services. It is really strange, and based on my experience the probelem is system-wide, so when my app couldn't find location, than the Google Maps app couldn't eather. Note that I use Cyanogenmod, so it can be some bug within it.

Checking android emulator is in Silent Ringer Mode or not

I am developing an android application for which i want to know whether the android phone is silent or not. I need to know how can I check this thing on android emulator by code.
You can use AudioManager class for your requirement,
AudioManager am = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
if (am.getRingerMode() == AudioManager.RINGER_MODE_SILENT)
{
// silent mode
}

Categories

Resources