Android Camera2 api, Swap cameras quickly on the go - java

I'm making an Android app using the Camera2 api.
I want to be able to switch between the front and back camera, but it takes an awful lot of time to do so no matter how i try to implement it.
After what i understand, you can't open both cameras at once(i've tried that also), so you have to stop the first one before opening the second.
The problem is it takes me 1.5seconds to stop the first camera.
How does for instance snapchat manage to swap the cameras in a few hundred milliseconds?
The code i'm using is the camera2basic from google that can be found here:
https://github.com/googlesamples/android-Camera2Basic/blob/master/Application/src/main/java/com/example/android/camera2basic/Camera2BasicFragment.java
I've added a simple method to stop the camera:
public void stopCamera(){
Log.i("yoyo","Stopcamera() begin");
mCameraDevice.close();
//stopBackgroundThread();
Log.i("yoyo","Stopcamera() end");
}
Android Monitor:
08-01 15:13:01.478 10020-10020/com.example.android.camera2basic I/yoyo: Stopcamera() begin
08-01 15:13:02.852 10020-10020/com.example.android.camera2basic I/yoyo: Stopcamera() end
08-01 15:13:02.853 10020-10020/com.example.android.camera2basic I/Choreographer: Skipped 81 frames! The application may be doing too much work on its main thread.
08-01 15:13:02.855 10020-10207/com.example.android.camera2basic I/yoyo: Cameradevice - onClosed() callback running
-UPDATE 07 aug 2017-
It seems that the camera2 api just takes longer to shut down than the old camera api.
I tried using the old camera api and I achieved the same speed as snapchat/instagram, so i'm guessing they are using the old camera api.

You should be able to run both capture sessions concurrently. You can even have both "previews" on the UI at the same time.
Here's what you have to do:
create device 1 (i.e. back camera) with cameraManager.openCamera("1", ...)
create device 2 (i.e. front camera) cameraManager.openCamera("2", ...)
Once you have a CameraDevice instance for each camera, start their capture session
cameraDevice1.createCaptureSession(surface1, ...)
cameraDevice1.createCaptureSession(surface2, ...)
When the capture sessions are created successfully, you should be at to call captureSession.setRepeatingRequest(...).
As you've noticed, there's a huge overhead in switching cameras from "scratch". If you only want to show one preview at a time. You can still call openCamera() for each camera, call createCaptureRequest for each camera, and use setRepeatingRequest or stopRepeating to control when the captureSession is actually processing frames.
Hope this helps!

William Guedes
Here's what you have to do:
create device 1 (i.e. back camera) with
cameraManager.openCamera("1", ...)
create device 2 (i.e. front camera) cameraManager.openCamera("2", ...)
I've written some simple code below for opening both cameras using manager.openCamera().
The monitor only logs "camera 0 onOpened() callback" though, and i assumed this ment you could only open one camera at the time?
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e("yoyo", "onCreate() begin");
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
String[] cameraIdList = manager.getCameraIdList();
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 123);
return;
}
manager.openCamera(cameraIdList[0], new CameraDevice.StateCallback() {
#Override
public void onOpened(#NonNull CameraDevice cameraDevice) {
Log.e("yoyo", "camera 0 onOpened() callback");
}
#Override
public void onDisconnected(#NonNull CameraDevice cameraDevice) {
}
#Override
public void onError(#NonNull CameraDevice cameraDevice, int i) {
}
}, null);
manager.openCamera(cameraIdList[1], new CameraDevice.StateCallback() {
#Override
public void onOpened(#NonNull CameraDevice cameraDevice) {
Log.e("yoyo", "camera 1 onOpened() callback");
}
#Override
public void onDisconnected(#NonNull CameraDevice cameraDevice) {
}
#Override
public void onError(#NonNull CameraDevice cameraDevice, int i) {
}
}, null);
}catch (CameraAccessException e) {e.printStackTrace();}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == 123) {
if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
// close the app
Toast.makeText(this, "Sorry!!!, you can't use this app without granting permission", Toast.LENGTH_LONG).show();
finish();
}
}
}
}

Related

Android AppUpdateManager not initializing the auto update

I want to update my app immediately every time I publish an update. I followed the instructions from the official android documentation on how to test the auto update feature , but nothing happens. I placed some logs in order to check whether these functions initialize, but the logcat shows nothing either. Is this a problem in my syntax, or should I place these functions somewhere else? Currently, all my update code is written inside the main, starting class of the app.
On create method of the class
private static final int REQUEST_APP_UPDATE = 560;
private AppUpdateManager appUpdateManager;
private InstallStateUpdatedListener installStateUpdatedListener;
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
appUpdateManager = AppUpdateManagerFactory.create(this);
installStateUpdatedListener = new
InstallStateUpdatedListener() {
#Override
public void onStateUpdate(InstallState state) {
if (state.installStatus() == InstallStatus.DOWNLOADED){
} else if (state.installStatus() == InstallStatus.INSTALLED){
if (appUpdateManager != null){
appUpdateManager.unregisterListener(installStateUpdatedListener);
}
} else {
Log.i(TAG, "InstallStateUpdatedListener: state: " + state.installStatus());
}
}
};
appUpdateManager
.getAppUpdateInfo()
.addOnSuccessListener(
appUpdateInfo -> {
Log.d("TAG", "here");
// Checks that the platform will allow the specified type of update.
if ((appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE)
&& appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE))
{
// Request the update.
try {
Log.d("TAG", "here");
appUpdateManager.startUpdateFlowForResult(
appUpdateInfo,
AppUpdateType.IMMEDIATE,
this,
REQUEST_APP_UPDATE);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
}
});
appUpdateManager.registerListener(installStateUpdatedListener);
...
On resume and on stop handling methods:
#Override
protected void onResume() {
super.onResume();
appUpdateManager
.getAppUpdateInfo()
.addOnSuccessListener(
appUpdateInfo -> {
if (appUpdateInfo.updateAvailability()
== UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS) {
// If an in-app update is already running, resume the update.
try {
appUpdateManager.startUpdateFlowForResult(
appUpdateInfo,
AppUpdateType.IMMEDIATE,
this,
REQUEST_APP_UPDATE);
Log.d("TAG", "tu");
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
}
});
}
#Override
protected void onStop() {
super.onStop();
if (appUpdateManager != null) {
appUpdateManager.unregisterListener(installStateUpdatedListener);
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_APP_UPDATE) {
if (resultCode != RESULT_OK) {
Log.d("TAG", "Update flow failed! Result code: " + resultCode);
// If the update is cancelled or fails,
// you can request to start the update again.
}
}
}
I suggest you to move all your AppUpdateInfo retrieving to onResume() since it is more reliable entry point of an activity (for example, if Activity has came to background and then was opened again by user). OnCreate method will be called only if activity was destroyed, since that, you may not see update dialog after reopening application if it was minimized.
#Override
public void onResume() {
super.onResume();
appUpdateManager.getAppUpdateInfo().addOnSuccessListener( info -> {
boolean isStalledUpdate = info.updateAvailability() == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS;
boolean isReadyForUpdate =
info.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
&& info.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE;
if (isReadyForUpdate || isStalledUpdate) {
appUpdateManager.startUpdateFlowForResult(
info,
AppUpdateType.IMMEDIATE,
this,
REQ_CODE
);
}
}
Sometimes app is not automatically synchronized with Play Store updates, so you need to do the following:
Make sure you have an update available manually - go to Play Store, check for updates and make sure that you have an update available for your application.
After that open your app (your activity, that calls update manager in onResume) and you will see immediate update dialog.
Also, one tip for you - make your Activity implement InstallStateUpdateListener and override method onStateUpdate like this to handle different events.
#Override
public void onResume() {
// All previous logic
// If update is available or was stalled call this
appUpdateManager.registerListener(this);
}
#Override
public void onStateUpdate(InstallState state) {
if (state == null) return;
switch (state.installStatus()) {
case InstallStatus.INSTALLED:
appUpdateManager.unregisterListener(this)
return;
case InstallStatus.FAILED:
appUpdateManager.unregisterListener(this)
return;
case InstallStatus.CANCELED:
appUpdateManager.unregisterListener(this)
return;
default:
// provide your own logic
return;
}
}
This will help you to avoid calling separate instance of listener in activity lifecycle methods.
The code that I provided was working, the problem of not updating was a matter of the device itself not knowing whether an update is available. After refreshing the update list on the Play Store, the app update manager initialized the auto update window when starting the app.

Android 9 background location tracking using foreground service

I am using an android fused location client for background location tracking which will run even if the app is cleared from the memory. I am using foreground service for this. It is running perfectly for most of the devices except the Samsung Galaxy devices with power saver modes. I have also added the permission for ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS on app runtime but still, the Samsung devices do not track perfectly. I am also using geofencing intent service along with a partial wake lock. This app is working fine on all other devices. Please check the code that I am using for background locations. This is not the full code.
Also when I enable location toasts then the distance is tracking perfectly even on Samsung. But when toasts are disabled then it only works for the first time in Samsung.
/**********LocationUpdatesService class********/
public class LocationUpdatesService extends Service {
#Override
public void onCreate() {
Log.i(TAG, "Service onCreate");
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
mLocationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
super.onLocationResult(locationResult);
onNewLocation(locationResult.getLastLocation());
}
};
createLocationRequest();
if (checkPermissions()) {
getLastLocation();
}
powerManager = (PowerManager) getSystemService(POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"myapp::MyWakelockTag");
wakeLock.acquire();
}
public void requestLocationUpdates() {
Log.i(TAG, "Requesting location updates");
//Utils.setRequestingLocationUpdates(this, true);
startService(new Intent(getApplicationContext(), LocationUpdatesService.class));
try {
mFusedLocationClient.requestLocationUpdates(mLocationRequest,
mLocationCallback, Looper.myLooper());
} catch (SecurityException unlikely) {
//Utils.setRequestingLocationUpdates(this, false);
Log.e(TAG, "Lost location permission. Could not request updates. " + unlikely);
}
}
public void removeLocationUpdates() {
Log.i(TAG, "Removing location updates");
removeActivityUpdatesButtonHandler();
try {
mFusedLocationClient.removeLocationUpdates(mLocationCallback);
wakeLock.release();
stopForeground(true);
stopSelf();
} catch (SecurityException unlikely) {
//Utils.setRequestingLocationUpdates(this, true);
Log.e(TAG, "Lost location permission. Could not remove updates. " + unlikely);
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "Service started");
boolean startedFromNotification = intent.getBooleanExtra(EXTRA_STARTED_FROM_NOTIFICATION,
false);
// We got here because the user decided to remove location updates from the notification.
if (startedFromNotification) {
//removeLocationUpdates();
//stopSelf();
}
startForeground(NOTIFICATION_ID, getNotification());
// Tells the system to not try to recreate the service after it has been killed.
return START_STICKY;
}
}
I am using this Bound service in my main activity.
The above is just a sample code for anyone's reference. Please let me know if anyone knows the solution. I am just having trouble in the case of Samsung devices with a power saver. Otherwise, my service is working fine and tracking the distance perfectly.

Is it possible to have an hidden recording of camera device with ID0 and a possible preview stream also ID 0 at the same time?

I build an app where the user has an FAB to start some hidden image recording with camera2 API and some other location stuff - now the user has the option to open a preview with an item from navigation drawer. The problem is that if I start hidden recording over FAB and then click to open the preview, the statecallback onDisconnected from CameraDevice is called and the hidden recording is disabled due to CameraDevice with ID 0 is no longer available.
My code is like the sample Camera2Video from Google:
https://github.com/googlesamples/android-Camera2Video
private CameraDevice mCameraDevice;
private CaptureRequest.Builder mPreviewBuilder;
private CameraCaptureSession mPreviewSession;
/**
* A {#link Semaphore} to prevent the app from exiting before closing the camera.
*/
private Semaphore mCameraOpenCloseLock = new Semaphore(1);
/**
* {#link CameraDevice.StateCallback} is called when {#link CameraDevice} changes its status.
*/
private CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
#Override
public void onOpened(#NonNull CameraDevice cameraDevice) {
mCameraDevice = cameraDevice;
Log.d(TAG, "onOpened: ");
File dir = new File(mNextVideoDirPath);
if(dir.mkdirs()) {
startRecordingVideo();
}
else {
Toast.makeText(context,
"Error: Could not start recording. Directory for saved files could not be created", Toast.LENGTH_SHORT).show();
}
mCameraOpenCloseLock.release();
}
#Override
public void onDisconnected(#NonNull CameraDevice cameraDevice) {
mCameraOpenCloseLock.release();
cameraDevice.close();
mCameraDevice = null;
}
#Override
public void onError(#NonNull CameraDevice cameraDevice, int error) {
mCameraOpenCloseLock.release();
cameraDevice.close();
mCameraDevice = null;
}
};
If I do at first the preview and then start the hidden recording the preview freezes and hidden recording starts.
I have an Huawei P30 pro and tried to just change the ID of camera device but instead of front camera it's crashing.
So is there a differnt approach for some use case like this or isn't it even possible to do so OR how can I prevent some disconnection?
UPDATE
I found an article about multiple streams from on e device on medium from android developers
https://medium.com/androiddevelopers/using-multiple-camera-streams-simultaneously-bf9488a29482
Maybe I can add those targets before I do the stuff..
Something like this:
https://gist.github.com/owahltinez/f615e13bfc3497a0bd5d1427eae6c54f#file-using-multiple-camera-streams-01-kt
UPDATE END
If necessary I can provide some more code, but it's most like the sample from google.
Thank you for your time!

Unable to check if an app is using camera through service

I'm trying to check if an app is accessing the camera (even in the background) in Android, and I'm using a service to do that.
That's my service code:
public class BackgroundService extends Service {
#Nullable
Context context;
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
Toast.makeText(this, "Service started!", Toast.LENGTH_LONG).show();
if (isCameraUsedbyApp()){
Toast.makeText(this, "Camera is used!", Toast.LENGTH_LONG).show();
}
}
#Override
public void onDestroy() {
Toast.makeText(this, "Service stopped!", Toast.LENGTH_LONG).show();
}
public boolean isCameraUsedbyApp() {
Camera camera = null;
try {
camera = Camera.open();
} catch (RuntimeException e) {
return true;
} finally {
if (camera != null) camera.release();
}
return false;
}
}
I've followed the answers to these questions:
How to check if camera is opened by any application
How to check if android.hardware.Camera is released?
But without success, in fact the service always says that camera is used, also when it isn't.
In addition, I'm trying to get the app that is using camera (if it is used), but I cannot find some references to that in Android developers docs (official one).
Can you please help me? If you need further information you've only to ask
Regards,
F.

Enabling Camera Flash While Recording Video

I need a way to control the camera flash on an Android device while it is recording video. I'm making a strobe light app, and taking videos with a flashing strobe light would result in the ability to record objects that are moving at high speeds, like a fan blade.
The flash can only be enabled by starting a video preview and setting FLASH_MODE_TORCH in the camera's parameters. That would look like this:
Camera c = Camera.open();
Camera.Parameters p = c.getParameters();
p.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
c.setParameters(p);
c.startPreview();
Once the preview has started, I can flip that parameter back and forth to turn the light on and off. This works well until I try to record a video. The trouble is that in order to give the camera to the MediaRecorder, I first have to unlock it.
MediaRecorder m = new MediaRecorder();
c.unlock(); // the killer
m.setCamera(c);
After that unlock, I can no longer change the camera parameters and therefore have no way to change the flash state.
I do not know if it is actually possible to do this since I'm not the best at java-hacking, but here is what I do know:
Camera.unlock() is a native method, so I can't really see the mechanism behind the way it locks me out
Camera.Parameter has a HashMap that contains all of its parameters
Camera.setParameters(Parameters) takes the HashMap, converts it to a string, and passes it to a native method
I can eliminate all the parameters but TORCH-MODE from the HashMap and the Camera will still accept it
So, I can still access the Camera, but it won't listen to anything I tell it. (Which is kind of the purpose of Camera.unlock())
Edit:
After examining the native code, I can see that in CameraService.cpp my calls to Camera.setParameters(Parameters) get rejected because my Process ID does not match the Process ID the camera service has on record. So it would appear that that is my hurdle.
Edit2:
It would appear that the MediaPlayerService is the primary service that takes control of the camera when a video is recording. I do not know if it is possible, but if I could somehow start that service in my own process, I should be able to skip the Camera.unlock() call.
Edit3:
One last option would be if I could somehow get a pointer to the CameraHardwareInterface. From the looks of it, this is a device specific interface and probably does not include the PID checks. The main problem with this though is that the only place that I can find a pointer to it is in CameraService, and CameraService isn't talking.
Edit4: (several months later)
At this point, I don't think it is possible to do what I originally wanted. I don't want to delete the question on the off chance that someone does answer it, but I'm not actively seeking an answer. (Though, receiving a valid answer would be awesome.)
I encountered a similar issue. The user should be able to change the flash mode during recording to meet their needs depending on the light situation. After some investigative research i came to the following solution:
I assume, that you've already set up a proper SurfaceView and a SurfaceHolder with its necessary callbacks. The first thing i did was providing this code (not declared variables are globals):
public void surfaceCreated(SurfaceHolder holder) {
try {
camera = Camera.open();
parameters = camera.getParameters();
parameters.setFlashMode(Parameters.FLASH_MODE_OFF);
camera.setParameters(parameters);
camera.setPreviewDisplay(holder);
camera.startPreview();
recorder = new MediaRecorder();
} catch (IOException e) {
e.printStackTrace();
}
}
My next step was initializing and preparing the recorder:
private void initialize() {
camera.unlock();
recorder.setCamera(camera);
recorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
recorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
recorder.setVideoFrameRate(20);
recorder.setOutputFile(filePath);
try {
recorder.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
finish();
} catch (IOException e) {
e.printStackTrace();
finish();
}
}
It's important to note, that camera.unlock() has to be called BEFORE the whole initialization process of the media recorder. That said also be aware of the proper order of each set property, otherwise you'll get an IllegalStateException when calling prepare() or start(). When it comes to recording, i do this. This will usually be triggered by a view element:
public void record(View view) {
if (recording) {
recorder.stop();
//TODO: do stuff....
recording = false;
} else {
recording = true;
initialize();
recorder.start();
}
}
So now, i finally can record properly. But what's with that flash? Last but not least, here comes the magic behind the scenes:
public void flash(View view) {
if(!recording) {
camera.lock();
}
parameters.setFlashMode(parameters.getFlashMode().equals(Parameters.FLASH_MODE_TORCH) ? Parameters.FLASH_MODE_OFF : Parameters.FLASH_MODE_TORCH);
camera.setParameters(parameters);
if(!recording) {
camera.unlock();
}
}
Everytime i call that method via an onClick action i can change the flash mode, even during recording. Just take care of properly locking the camera. Once the lock is aquired by the media recorder during recording, you don't have to lock/unlock the camera again. It doesn't even work. This was tested on a Samsung Galaxy S3 with Android-Version 4.1.2. Hope this approach helps.
After preparing media recorder, use camera.lock(), and then set whatever parameters you want to set to camera.
But before starting recording you need to call camera.unlock(), and after you stop media recorder you need to call camera.lock() to start preview.
Enjoy!!!
Try this.. hopefully it will work.. :)
private static Torch torch;
public Torch() {
super();
torch = this;
}
public static Torch getTorch() {
return torch;
}
private void getCamera() {
if (mCamera == null) {
try {
mCamera = Camera.open();
} catch (RuntimeException e) {
Log.e(TAG, "Camera.open() failed: " + e.getMessage());
}
}
}
public void toggleLight(View view) {
toggleLight();
}
private void toggleLight() {
if (lightOn) {
turnLightOff();
} else {
turnLightOn();
}
}
private void turnLightOn() {
if (!eulaAgreed) {
return;
}
if (mCamera == null) {
Toast.makeText(this, "Camera not found", Toast.LENGTH_LONG);
button.setBackgroundColor(COLOR_WHITE);
return;
}
lightOn = true;
Parameters parameters = mCamera.getParameters();
if (parameters == null) {
button.setBackgroundColor(COLOR_WHITE);
return;
}
List<String> flashModes = parameters.getSupportedFlashModes();
if (flashModes == null) {
button.setBackgroundColor(COLOR_WHITE);
return;
}
String flashMode = parameters.getFlashMode();
Log.i(TAG, "Flash mode: " + flashMode);
Log.i(TAG, "Flash modes: " + flashModes);
if (!Parameters.FLASH_MODE_TORCH.equals(flashMode)) {
if (flashModes.contains(Parameters.FLASH_MODE_TORCH)) {
parameters.setFlashMode(Parameters.FLASH_MODE_TORCH);
mCamera.setParameters(parameters);
button.setBackgroundColor(COLOR_LIGHT);
startWakeLock();
} else {
Toast.makeText(this, "Flash mode (torch) not supported",
Toast.LENGTH_LONG);
button.setBackgroundColor(COLOR_WHITE);
Log.e(TAG, "FLASH_MODE_TORCH not supported");
}
}
}
private void turnLightOff() {
if (lightOn) {
button.setBackgroundColor(COLOR_DARK);
lightOn = false;
if (mCamera == null) {
return;
}
Parameters parameters = mCamera.getParameters();
if (parameters == null) {
return;
}
List<String> flashModes = parameters.getSupportedFlashModes();
String flashMode = parameters.getFlashMode();
if (flashModes == null) {
return;
}
Log.i(TAG, "Flash mode: " + flashMode);
Log.i(TAG, "Flash modes: " + flashModes);
if (!Parameters.FLASH_MODE_OFF.equals(flashMode)) {
if (flashModes.contains(Parameters.FLASH_MODE_OFF)) {
parameters.setFlashMode(Parameters.FLASH_MODE_OFF);
mCamera.setParameters(parameters);
stopWakeLock();
} else {
Log.e(TAG, "FLASH_MODE_OFF not supported");
}
}
}
}
private void startPreview() {
if (!previewOn && mCamera != null) {
mCamera.startPreview();
previewOn = true;
}
}
private void stopPreview() {
if (previewOn && mCamera != null) {
mCamera.stopPreview();
previewOn = false;
}
}
private void startWakeLock() {
if (wakeLock == null) {
Log.d(TAG, "wakeLock is null, getting a new WakeLock");
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
Log.d(TAG, "PowerManager acquired");
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKE_LOCK_TAG);
Log.d(TAG, "WakeLock set");
}
wakeLock.acquire();
Log.d(TAG, "WakeLock acquired");
}
private void stopWakeLock() {
if (wakeLock != null) {
wakeLock.release();
Log.d(TAG, "WakeLock released");
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Eula.show(this)) {
eulaAgreed = true;
}
setContentView(R.layout.main);
button = findViewById(R.id.button);
surfaceView = (SurfaceView) this.findViewById(R.id.surfaceview);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
disablePhoneSleep();
Log.i(TAG, "onCreate");
}
To access the device camera, you must declare the CAMERA permission in your Android Manifest. Also be sure to include the <uses-feature> manifest element to declare camera features used by your application. For example, if you use the camera and auto-focus feature, your Manifest should include the following:
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
A sample that checks for torch support might look something like this:
//Create camera and parameter objects
private Camera mCamera;
private Camera.Parameters mParameters;
private boolean mbTorchEnabled = false;
//... later in a click handler or other location, assuming that the mCamera object has already been instantiated with Camera.open()
mParameters = mCamera.getParameters();
//Get supported flash modes
List flashModes = mParameters.getSupportedFlashModes ();
//Make sure that torch mode is supported
//EDIT - wrong and dangerous to check for torch support this way
//if(flashModes != null && flashModes.contains("torch")){
if(flashModes != null && flashModes.contains(Camera.Parameters.FLASH_MODE_TORCH)){
if(mbTorchEnabled){
//Set the flash parameter to off
mParameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
}
else{
//Set the flash parameter to use the torch
mParameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
}
//Commit the camera parameters
mCamera.setParameters(mParameters);
mbTorchEnabled = !mbTorchEnabled;
}
To turn the torch on, you simply set the camera parameter Camera.Parameters.FLASH_MODE_TORCH
Camera mCamera;
Camera.Parameters mParameters;
//Get a reference to the camera/parameters
mCamera = Camera.open();
mParameters = mCamera.getParameters();
//Set the torch parameter
mParameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
//Comit camera parameters
mCamera.setParameters(mParameters);
To turn the torch off, set Camera.Parameters.FLASH_MODE_OFF

Categories

Resources