I am trying to write an app which turns on flash light when a button is pressed. The problem is the app is not detecting flash light on my phone. I have searched alot on internet. Sure others have faced the problem, I have also applied those solutions but they don't seem to work. I don't know what is causing this problem. Posting the code here:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_starting_point);
if(! getApplicationContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)) // checking if flash light is available inn android phone
{
Toast.makeText(StartingPoint.this, "Sorry this app can't work without flash light", Toast.LENGTH_LONG).show();
finish();
}
cam = Camera.open();
param = cam.getParameters();
}
#Override
public void onClick (View v)
{
if(!flashOn)
{
i=0;
flashOn=true;
param.setFlashMode(Parameters.FLASH_MODE_TORCH);
cam.setParameters(param);
cam.startPreview();
}
else{
i=0;
flashOn=false;
param.setFlashMode(Parameters.FLASH_MODE_OFF);
cam.setParameters(param);
cam.stopPreview();
}
}
I have added these permissions in Android Manifest as well.
<uses-permission android:name="android.permission.FLASHLIGHT"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
Regards
I have an app that checks the flashlight feature and it works fine. Here is the code I used for checking if the user has the light:
if (!pm.hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
new AlertDialog.Builder(this)
.setTitle("Sorry")
.setMessage("It appears that your device is incompatible with this app. Sorry for the inconvenience.")
.setNeutralButton("Close", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface arg0, int arg1) {
finish();
}
}).show();
return;
}
Now to actually make the light work, I made a toggle button and wrote the following code:
private boolean isLightOn = false;
private Camera camera;
private ToggleButton button;
public Vibrator v;
if (camera == null) {
camera = Camera.open();
}
final Parameters p = camera.getParameters();
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
if (isLightOn) {
Toast.makeText(context, "Light off!", Toast.LENGTH_SHORT).show();
v.vibrate(40);
p.setFlashMode(Parameters.FLASH_MODE_OFF);
camera.setParameters(p);
camera.stopPreview();
isLightOn = false;
} else {
Toast.makeText(context, "Light on!", Toast.LENGTH_SHORT).show();
v.vibrate(40);
p.setFlashMode(Parameters.FLASH_MODE_TORCH);
camera.setParameters(p);
camera.startPreview();
isLightOn = true;
}
}
});
And finally, here are the only permissions I used:
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
Note: All of the above code is in the onCreate method of my activity.
Hope this helps solve your problem!
I think you aren't setting your params again:
I used this to check if there is a flashlight:
public static Boolean hasFlashLight(Context context){
return context.getApplicationContext().getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
}
and to turn it off and on:
Parameters params = mCamera.getParameters();
if (!isFlashlightOn) {
params.setFlashMode(Parameters.FLASH_MODE_OFF);
} else {
params.setFlashMode(Parameters.FLASH_MODE_TORCH);
}
mCamera.setParameters(params);
Let me know if it works for you too.
I had the same problem. Use this
if(getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)) {
//Flash ok
Parameters params = mCamera.getParameters();
params.setFlashMode(Parameters.FLASH_MODE_TORCH);
} else {
//Flash not supported
}
to determinate if your device has flash.
Some cameras need surface holder, otherwise they block the flash.
SurfaceView preview = (SurfaceView) findViewById(...);
SurfaceHolder holder = preview.getHolder();
holder.addCallback(this);
Camera camera = Camera.open();
camera.setPreviewDisplay(holder);
Related
I am developing an App Locker for android. Everything works except for when you try to delete an app, the popup does not appear. I tried to force the lock-screen dialog to appear manually from within the app, but the results were crashes and ANRs.
I thought to myself that the popup is not available because the packageInstaller (System app) is using the screen at the same time, and it gets more priority.
Another thing is that when I cancel an uninstall, packageInstaller goes away and then my display appears for a fraction of a second and then disappears. Note that this is after, I need it to be present before, or even while the packageInstaller is running.
My question is if it is possible to put my window at a certain priority, so that goes even above the system app?
In my app check service, in my method that's on repeat constantly I had:
`
if (mpackageName.equals("com.google.android.packageinstaller")) {
showUnlockDialog();
}
however, this caused my lock-display to get opened a lot of times (because of the repeat), which caused the app to become irresponsive. What I now have (after omitting) is the dialog appearing after, at the end then going away on its own.
This is my show dialog method:
`
{
if (context == null) {
context = getApplicationContext();
}
LayoutInflater layoutInflater = LayoutInflater.from(context);
#SuppressLint("InflateParams") View promptsView;
promptsView = layoutInflater.inflate(R.layout.popup_unlock, null, false);
Lock9View lock9View = (Lock9View) promptsView.findViewById(R.id.lock_9_view);
Button forgetPassword = (Button) promptsView.findViewById(R.id.forgetPassword);
LinearLayout linearLayout = promptsView.findViewById(R.id.popup_background);
TextView textView = promptsView.findViewById(R.id.textView);
linearLayout.setBackgroundResource(R.drawable.gradient_list);
textView.setTextColor(getResources().getColor(R.color.colorWhite));
forgetPassword.setTextColor(getResources().getColor(R.color.colorWhite));
animateBanner1(linearLayout);
lock9View = (Lock9View) promptsView.findViewById(R.id.lock_10_view);
lock9View.setVisibility(View.VISIBLE);
lock9View.setCallBack(new Lock9View.CallBack() {
#Override
public void onFinish(String password) {
if (password.matches(sharedPreference.getPassword(context))) {
dialog.dismiss();
} else {
Toast.makeText(context, "Wrong pattern, try again", Toast.LENGTH_SHORT).show();
}
}
});
forgetPassword.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(AppCheckServices.this, PasswordRecoveryActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
dialog.dismiss();
}
});
dialog = new Dialog(context, android.R.style.Theme_Black_NoTitleBar_Fullscreen);
dialog.setCanceledOnTouchOutside(false);
dialog.setCancelable(false);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Objects.requireNonNull(dialog.getWindow()).setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
}
else {
Objects.requireNonNull(dialog.getWindow()).setType(WindowManager.LayoutParams.TYPE_PHONE);
}
dialog.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);
dialog.setContentView(promptsView);
dialog.getWindow().setGravity(Gravity.CENTER);
dialog.setOnKeyListener(new Dialog.OnKeyListener() {
#Override
public boolean onKey(DialogInterface dialog, int keyCode,
KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK
&& event.getAction() == KeyEvent.ACTION_UP) {
Intent startMain = new Intent(Intent.ACTION_MAIN);
startMain.addCategory(Intent.CATEGORY_HOME);
startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(startMain);
}
return true;
}
});
}
dialog.show();
}
As I said this works on every other app besides the packageInstaller even if I specifically lock it.
Here are my relevant Manifest Permissions:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission
android:name="android.permission.INTERNAL_SYSTEM_WINDOW"
tools:ignore="ProtectedPermissions" />
<uses-permission
android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions" />
From What I understand, the highest "setType()" for the window manager is the:
SYSTEM_ALERT_WINDOW
It allows to have the top most display. I thought that by using this, I could block the packageInstaller.
However this too requires special permission (2003 from the crashes), and does not get granted easily.
I would appreciate any help in regard to this matter and can post anything else that is relevant.
Thanks in advance!
`
Background
I had started out this project on Android Studio with the intent of creating a OpenCV application that could process frames using the camera on my OnePlus android device. After running the application, I was gratified to see it finally launch on my device. However, the application shows up with a black screen where the camera preview should be. Here is my code for my MainActivity, activity_main, and AndroidManifest files:
EDIT: While the application launched on my device, I did give the application permission to use camera
MainActivity.java
package com.example.cv;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceView;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.JavaCameraView;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.imgproc.Imgproc;
public class MainActivity extends AppCompatActivity implements CameraBridgeViewBase.CvCameraViewListener2
{
private static String TAG = "MainActivity";
JavaCameraView javaCameraView;
Mat mRGBA, mRGBAT;
BaseLoaderCallback baseLoaderCallback = new BaseLoaderCallback(MainActivity.this) {
#Override
public void onManagerConnected(int status)
{
if (status == BaseLoaderCallback.SUCCESS) {
javaCameraView.enableView();
} else {
super.onManagerConnected(status);
}
}
};
static
{
if (OpenCVLoader.initDebug())
{
Log.d(TAG, "OpenCV is Configured or Connected successfully.");
}
else
{
Log.d(TAG, "OpenCV not Working or Loaded.");
}
}
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
javaCameraView = (JavaCameraView) findViewById(R.id.my_camera_view);
javaCameraView.setVisibility(SurfaceView.VISIBLE);
javaCameraView.setCvCameraViewListener(MainActivity.this);
}
#Override
public void onCameraViewStarted(int width, int height)
{
mRGBA = new Mat(height, width, CvType.CV_8UC4);
}
#Override
public void onCameraViewStopped()
{
mRGBA.release();
}
#Override
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame)
{
mRGBA = inputFrame.rgba();
mRGBAT = mRGBA.t();
Core.flip(mRGBA.t(), mRGBAT, 1);
Imgproc.resize(mRGBAT, mRGBAT, mRGBA.size());
return mRGBAT;
}
#Override
public void onPointerCaptureChanged(boolean hasCapture) {
}
#Override
protected void onDestroy() {
super.onDestroy();
if (javaCameraView != null)
{
javaCameraView.disableView();
}
}
#Override
protected void onPause() {
super.onPause();
if (javaCameraView != null)
{
javaCameraView.disableView();
}
}
#Override
protected void onResume() {
super.onResume();
if (OpenCVLoader.initDebug())
{
Log.d(TAG, "OpenCV is Configured or Connected successfully.");
baseLoaderCallback.onManagerConnected(BaseLoaderCallback.SUCCESS);
}
else
{
Log.d(TAG, "OpenCV not Working or Loaded.");
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION, this, baseLoaderCallback);
}
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<org.opencv.android.JavaCameraView
android:id="#+id/my_camera_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</RelativeLayout>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.cv">
<uses-permission android:name="android.permission.CAMERA"/>
<uses-feature android:name="android.hardware.camera"/>
<uses-feature android:name="android.hardware.camera.autofocus"/>
<uses-feature android:name="android.hardware.camera.front"/>
<uses-feature android:name="android.hardware.camera.front.autofocus"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
The issue you are facing is actually with the camera permission check
Starting from Android Marshmallow, the CAMERA permission is considered a dangerous one and the user must explicitly agree on its usage at runtime, clicking on the system dialog
This wouldn't happen for "normal permissions" [e.g. INTERNET] that are granted by default. If you are interested in which ones are dangerous and which not you can check for the one of interest directly in the Android documentation
What's happening with your initial code is that you are mentioning you will require the camera permission in your manifest file and then you are enabling it from the Android Settings [toggling the Camera slider]. But then, when you start the app there is nothing in the code that goes and checks that toggle. Then you get a black screen because Android assumes that the user has not given explicit consent
This link from the Android documentation should help you understand more. Here the snippet that will make your code work. In a nutshell, with onCreate() you go and check if the user has already granted the permission and if not you will ask it. In onRequestPermissionResult() there is the check we were talking about before. If the user agreed the camera will start, otherwise it won't
private static final int MY_CAMERA_REQUEST_CODE = 100;
int activeCamera = CameraBridgeViewBase.CAMERA_ID_FRONT;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
javaCameraView = (JavaCameraView) findViewById(R.id.my_camera_view);
// checking if the permission has already been granted
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
== PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "Permissions granted");
initializeCamera(javaCameraView, activeCamera);
} else {
// prompt system dialog
Log.d(TAG, "Permission prompt");
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, MY_CAMERA_REQUEST_CODE);
}
}
// callback to be executed after the user has givenapproval or rejection via system prompt
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == MY_CAMERA_REQUEST_CODE) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// camera can be turned on
Toast.makeText(this, "camera permission granted", Toast.LENGTH_LONG).show();
initializeCamera(javaCameraView, activeCamera);
} else {
// camera will stay off
Toast.makeText(this, "camera permission denied", Toast.LENGTH_LONG).show();
}
}
}
private void initializeCamera(JavaCameraView javaCameraView, int activeCamera){
javaCameraView.setCameraPermissionGranted();
javaCameraView.setCameraIndex(activeCamera);
javaCameraView.setVisibility(CameraBridgeViewBase.VISIBLE);
javaCameraView.setCvCameraViewListener(this);
}
I've spent days (well, nights) trying to work this out. So many examples online are for different versions of Android Studio, different versions of Android, different versions of OpenCV and I can't get any of them to the final 'working' stage.
This example (based on a youtube tutorial, I got to the point where I needed permissions. That's fine, I added that in and a check for them, and it pops up asking the user for camera permissions. But the screen stays blank. I've put in logcat debug, all the right methods seem to be getting called. Would appreciate any assistance.
Code:
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.mytestopencvapp" >
<uses-permission android:name="android.permission.CAMERA"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme" >
<activity android:name=".MainActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
MainActivity.java
package com.example.mytestopencvapp;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceView;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.JavaCamera2View;
import org.opencv.android.JavaCameraView;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.imgproc.Imgproc;
public class MainActivity extends AppCompatActivity implements CameraBridgeViewBase.CvCameraViewListener2 {
private static String TAG = "MainActivity";
JavaCameraView javaCameraView;
Mat mRGBA, mRGBAT;
private final int PERMISSIONS_READ_CAMERA=1;
BaseLoaderCallback baseLoaderCallback = new BaseLoaderCallback(MainActivity.this) {
#Override
public void onManagerConnected(int status) {
Log.d(TAG, "callbacksuccess");
switch (status)
{
case BaseLoaderCallback.SUCCESS:
{
Log.d(TAG, "case success");
javaCameraView.enableView();
break;
}
default:
{
Log.d(TAG, "case default");
super.onManagerConnected(status);
break;
}
}
}
};
static
{
if (OpenCVLoader.initDebug())
{
Log.d(TAG, "OpenCV is intialised");
}
else
{
Log.d(TAG, "OpenCV is not initialised");
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate");
setContentView(R.layout.activity_main);
javaCameraView = (JavaCameraView)findViewById(R.id.my_camera_view);
javaCameraView.setVisibility(SurfaceView.VISIBLE);
javaCameraView.setCvCameraViewListener(MainActivity.this);
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
// Permission is not granted
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.CAMERA)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.CAMERA},
PERMISSIONS_READ_CAMERA);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
} else {
Log.d(TAG, "PERMISSIOns granted");
// Permission has already been granted
}
}
#Override
public void onCameraViewStarted(int width, int height) {
Log.d(TAG, "onCameraViewStarted");
mRGBA = new Mat(height, width, CvType.CV_8UC4);
}
#Override
public void onCameraViewStopped() {
Log.d(TAG, "onCameraViewStopped");
mRGBA.release();
}
#Override
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame)
{
Log.d(TAG, "onCameraFrame");
/* mRGBA = inputFrame.rgba();
mRGBAT = mRGBA.t();
Core.flip(mRGBA.t(), mRGBAT, 1);
Imgproc.resize(mRGBAT, mRGBAT, mRGBA.size());
return mRGBAT;*/
mRGBA = inputFrame.rgba();
Core.transpose(mRGBA, mRGBAT);
Imgproc.resize(mRGBAT, mRGBAT, mRGBAT.size(),0,0,0);
Core.flip(mRGBA.t(), mRGBA, 1);
return mRGBA;
}
#Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy");
if (javaCameraView != null)
{
javaCameraView.disableView();
}
}
#Override
protected void onPause() {
super.onPause();
Log.d(TAG, "onPause");
if (javaCameraView != null)
{
javaCameraView.disableView();
}
}
#Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume");
if (OpenCVLoader.initDebug())
{
Log.d(TAG, "OpenCV is intialised again");
baseLoaderCallback.onManagerConnected((BaseLoaderCallback.SUCCESS));
}
else
{
Log.d(TAG, "OpenCV is not working");
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION, this, baseLoaderCallback);
}
}
}
And my res layout activity_main.xml file:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<org.opencv.android.JavaCameraView
android:id="#+id/my_camera_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</RelativeLayout>
As far as I can tell, I've linked them all correctly, I can confirm OpenCV initialises, permissions are checked and granted, but then...the JavaCameraView is just black.
You need to tell the CameraView that the camera permission was granted. You can do so by calling the setCameraPermissionGranted() function. This function call should go into the 'permission granted' block in your onCreate method as shown below:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
// More code here ...
} else {
Log.d(TAG, "Permissions granted");
javaCameraView.setCameraPermissionGranted();
}
In addition you propably want call this function in onRequestPermissionsResult() for the case where the permission is not granted already. The onRequestPermissionsResult() function is located in your Activity class. It is called when the user granted or denied on of the permission requests the app made.
This could look as follows:
#Override
public void onRequestPermissionsResult(
int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
// Ensure that this result is for the camera permission request
if (requestCode == PERMISSIONS_READ_CAMERA) {
// Check if the request was granted or denied
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// The request was granted -> tell the camera view
javaCameraView.setCameraPermissionGranted();
} else {
// The request was denied -> tell the user and exit the application
Toast.makeText(this, "Camera permission required.",
Toast.LENGTH_LONG).show();
this.finish();
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
For more information about the permission system on Android have a look at the following resources:
Request App Permissions This site describes the process of requesting permissions with all necessary steps.
Permissions Overview This site has information about uses-feature in the manifest file. You probably want to add the following line to your manifest file: <uses-feature android:name="android.hardware.camera" android:required="true" /> to prevent the installation on devices without camera.
Now you'll see, that the onCameraFrame callback function is actually invoked. This will lead to a NullPointerException because mRGBAT is not initialized. To just see the camera image you can return inputFrame.rgba() directly in this function. This will at least show the camera image. All further steps are normal image processing to rotate / mirror the image.
I had the same problem in android 10. After a lot of trial and errors, I found that the following method must be implemented in the main activity:
#Override
protected List<? extends CameraBridgeViewBase> getCameraViewList() {
return Collections.singletonList(mOpenCvCameraView);
}
I am trying to ask for permission to use the Camera and Writing to External Storage.
My Main Activity is:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M)
{
if(checkSelfPermission(Manifest.permission.CAMERA)!= PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(MainActivity.this,new String[]{android.Manifest.permission.CAMERA});
}
}
if(ActivityCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(MainActivity.this,new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE},REQUEST_PERM_WRITE_STORAGE);
}
else
{
takePhoto(); // calls this method
}
}
});
}
I have included in my Manifest.xml:
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
I get this error:
cannot find symbol method requestPermissions(MainActivity,String[])
cannot find symbol method checkSelfPermission(Context,String)
What is it that I am doing wrong. Thanks
For the request camera part try this
final int RequestCameraPermissionID = 1001;
ActivityCompat.requestPermissions(this,
new String[]{android.Manifest.permission.CAMERA},RequestCameraPermissionID);
I had my camera set to this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); and it works fine but if I change it to PORTRAIT instead of LANDSCAPE then it crashes with the following error...
07-30 12:51:37.655: ERROR/AndroidRuntime(22069): FATAL EXCEPTION: main
07-30 12:51:37.655: ERROR/AndroidRuntime(22069): java.lang.RuntimeException: Fail to connect to camera service
07-30 12:51:37.655: ERROR/AndroidRuntime(22069): at android.hardware.Camera.native_setup(Native Method)
07-30 12:51:37.655: ERROR/AndroidRuntime(22069): at android.hardware.Camera.<init>(Camera.java:110)
07-30 12:51:37.655: ERROR/AndroidRuntime(22069): at android.hardware.Camera.open(Camera.java:90)
07-30 12:51:37.655: ERROR/AndroidRuntime(22069): at org.digital.com.CamLayer.surfaceCreated(CamLayer.java:3
The method it crashes in is..
public void surfaceCreated(SurfaceHolder holder) {
synchronized(this) {
mCamera = Camera.open();
Camera.Parameters p = mCamera.getParameters();
p.setPreviewSize(800, 480);
mCamera.setParameters(p);
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException e) {
Log.e("Camera", "mCamera.setPreviewDisplay(holder);");
}
mCamera.startPreview();
mCamera.setPreviewCallback(this);
}
}
It crashes at mCamera = Camera.open();
My Manifest file has <uses-permission android:name="android.permission.CAMERA"></uses-permission>
How do I fix this so I can view my app in Portrait?
There is some concurrency problem in platform: http://code.google.com/p/android/issues/detail?id=6201
The workaround is to clear callback before releasing cam, that is I would recommend following clean-up code:
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mCam != null) {
mCam.stopPreview();
mCam.setPreviewCallback(null);
mCam.release();
mCam = null;
}
}
For your reference, this is the SurfaceHolderCallBack inner class that I'm using in my app and which works fine on Nexus One 2.2 in portrait mode - hope it helps.
Edit: "which works" = "which doesn't crash". Although I haven't figured out how to rotate the preview image correctly (see my first comment above). That's why I actually had to use landscape and 'convert' UI stuff that's surrounding the preview surface into landscape mode.
Afaik preview (with correct rotation of the preview image) only works in landscape mode. Rotation & orientation params that I tried didn't help at all.
class SurfaceHolderCallback implements SurfaceHolder.Callback {
private static final int IMAGE_WIDTH = 512;
private static final int IMAGE_HEIGHT = 384;
private static final String ORIENTATION = "orientation";
private static final String ROTATION = "rotation";
private static final String PORTRAIT = "portrait";
private static final String LANDSCAPE = "landscape";
public void surfaceCreated(SurfaceHolder holder) {
try {
// This case can actually happen if the user opens and closes the camera too frequently.
// The problem is that we cannot really prevent this from happening as the user can easily
// get into a chain of activites and tries to escape using the back button.
// The most sensible solution would be to quit the entire EPostcard flow once the picture is sent.
camera = Camera.open();
} catch(Exception e) {
finish();
return;
}
//Surface.setOrientation(Display.DEFAULT_DISPLAY,Surface.ROTATION_90);
Parameters p = camera.getParameters();
p.setPictureSize(IMAGE_WIDTH, IMAGE_HEIGHT);
camera.getParameters().setRotation(90);
Camera.Size s = p.getSupportedPreviewSizes().get(0);
p.setPreviewSize( s.width, s.height );
p.setPictureFormat(PixelFormat.JPEG);
p.set("flash-mode", "auto");
camera.setParameters(p);
try {
camera.setPreviewDisplay(surfaceHolder);
} catch (Throwable ignored) {
Log.e(APP, "set preview error.", ignored);
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
if (isPreviewRunning) {
camera.stopPreview();
}
try {
camera.startPreview();
} catch(Exception e) {
Log.d(APP, "Cannot start preview", e);
}
isPreviewRunning = true;
}
public void surfaceDestroyed(SurfaceHolder arg0) {
if(isPreviewRunning && camera != null) {
if(camera!=null) {
camera.stopPreview();
camera.release();
camera = null;
}
isPreviewRunning = false;
}
}
}
Do you have this set in AndroidManifest.xml ?
uses-permission android:name="android.permission.CAMERA"
Instead of using :
<uses-permission
android:name="android.permission.FLASHLIGHT"/>
Try to use:
<uses-permission
android:name="android.permission.FLASHLIGHT"
android:permissionGroup="android.permission-group.HARDWARE_CONTROLS"
android:protectionLevel="normal" />
and don't forget to add the permission for camera:
<uses-permission android:name="android.permission.CAMERA" />
Another possibility if you're using an Android Emulator may be that the front and back cameras are defined as "none" in the Android Virtual Device settings.
I think your problem is that when you rotate the camera it is not released correctly or at all. If you switch from landscape to portrait the Intent is launched again. If then the camera is not released and reopend you try to open an already open camera, which throws an error.
this might work...
#Override public void surfaceDestroyed(SurfaceHolder holder) {
Log.d("surfaceDestroyed", "");
cameraSource.stop(); //check if you have this line
}
I see you have set your preview area set as 800 x 480. In portrait mode, this size is invalid and there might be a bug in the API which makes it crash.
Try setting a preview area of 200x200