Capture Image From Camera using intent creates empty Image file - java

I followed this tutorial : https://developer.android.com/training/camera/photobasics .
I had some errors, but I resolved them and the app was working fine.
Once you took a picture, the picture would be saved in under this path :
Android/data/<YourAppPackageName>/files/Pictures.
However, after last OS update I'm getting an empty image file with size 0 B!
How can I solve this issue?
here is my github project : https://github.com/AlineJo/CameraGalleryImage.git
here is my code :
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.cameragalleryimage">
<!--Permission to write to storage-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!--Inform google play that your app can take pictures-->
<uses-feature
android:name="android.hardware.camera"
android:required="true" />
<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">
<!-- File provider is a generic way to store image file across different Android SDK, And it enable us to get uri-->
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.example.cameragalleryimage.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/img_file_path"></meta-data>
</provider>
<activity android:name=".activities.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
UploadImageFragment
package com.example.cameragalleryimage.fragments;
import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.content.FileProvider;
import androidx.fragment.app.Fragment;
import com.example.cameragalleryimage.R;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import static android.app.Activity.RESULT_OK;
/**
* A simple {#link Fragment} subclass.
*/
public class UploadImageFragment extends Fragment implements ChooseDialogFragment.ChooseDialogInterface {
private static final int PICK_IMAGE = 100;
private static final int CAPTURE_IMAGE = 200;
private static final int STORAGE_PERMISSION_REQUEST = 300;
private Context mContext;
private Uri mImageUri;
private ImageView ivImg;
private TextView tvProgress;
private ProgressBar progressBar;
private String mImagePath;
public UploadImageFragment() {
// Required empty public constructor
}
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
mContext = context;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View parentView = inflater.inflate(R.layout.fragment_upload_image, container, false);
ivImg = parentView.findViewById(R.id.iv_img);
tvProgress = parentView.findViewById(R.id.tv_progress);
progressBar = parentView.findViewById(R.id.progressBar);
Button btnChoose = parentView.findViewById(R.id.btn_choose);
Button btnUpload = parentView.findViewById(R.id.btn_upload);
btnChoose.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
ChooseDialogFragment dialog = new ChooseDialogFragment();
dialog.setChooseDialogListener(UploadImageFragment.this);
dialog.show(getChildFragmentManager(), ChooseDialogFragment.class.getSimpleName());
}
});
btnUpload.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mImageUri == null) {
Toast.makeText(mContext, "Please take an image", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(mContext, "Image URI Found : " + mImageUri.toString(), Toast.LENGTH_LONG).show();
}
}
});
return parentView;
}
#Override
public void onGalleryButtonClick() {
Intent i = new Intent();
i.setType("image/*"); // specify the type of data you expect
i.setAction(Intent.ACTION_GET_CONTENT); // we need to get content from another act.
startActivityForResult(Intent.createChooser(i, "choose App"), PICK_IMAGE);
}
#Override
public void onCameraButtonClick() {
if (isPermissionGranted()) {
openCamera();
} else {
showRunTimePermission();
}
}
private void openCamera() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(mContext.getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
Log.d("capture_error", ex.toString());
}
// Continue only if the File was successfully created
if (photoFile != null) {
mImageUri = FileProvider.getUriForFile(mContext,
"com.example.cameragalleryimage.fileprovider",
photoFile);
startActivityForResult(takePictureIntent, CAPTURE_IMAGE);
}
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK && data != null) {
if (requestCode == CAPTURE_IMAGE) {//img from camera
Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
ivImg.setImageBitmap(imageBitmap);
} else if (requestCode == PICK_IMAGE) {// img from gallery
try {
Uri imgUri = data.getData();
InputStream imageStream = mContext.getContentResolver().openInputStream(imgUri);//2
Bitmap selectedImageBitmap = BitmapFactory.decodeStream(imageStream);//3}
mImageUri = imgUri;
ivImg.setImageBitmap(selectedImageBitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
} else {
Toast.makeText(mContext, "Unexpected Error Happened while selecting picture!", Toast.LENGTH_SHORT).show();
}
}
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "IMG_" + timeStamp + "_";
File storageDir = mContext.getExternalFilesDir(Environment.DIRECTORY_PICTURES);// mContext.getExternalCacheDir();
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mImagePath = image.getAbsolutePath();
return image;
}
private boolean isPermissionGranted() {
return ActivityCompat.checkSelfPermission(mContext, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
}
public void showRunTimePermission() {
// Permission is not Granted !
// we should Request the Permission!
// put all permissions you need in this Screen into string array
String[] permissionsArray = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
//here we requet the permission
requestPermissions(permissionsArray, STORAGE_PERMISSION_REQUEST);
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// user grants the Permission!
// you can call the function to write/read to storage here!
openCamera();
} else {
// user didn't grant the Permission we need
Toast.makeText(mContext, "Please Grant the Permission To use this Feature!", Toast.LENGTH_LONG).show();
}
}
}
img_file_path.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-files-path
name="my_images"
path="/" />
<!-- Android/data/com.example.cameragalleryimage/files/Pictures-->
</paths>

Super thanks to #CommonsWare and #blackapps comments I was able to get uri and display the captured image
You can find the updated GitHub project here: https://github.com/AlineJo/CameraGalleryImage.git
here is the code I changed :
package com.example.cameragalleryimage.fragments;
import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.content.FileProvider;
import androidx.fragment.app.Fragment;
import com.bumptech.glide.Glide;
import com.example.cameragalleryimage.R;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import static android.app.Activity.RESULT_OK;
/**
* A simple {#link Fragment} subclass.
*/
public class UploadImageFragment extends Fragment implements ChooseDialogFragment.ChooseDialogInterface {
private static final int PICK_IMAGE = 100;
private static final int CAPTURE_IMAGE = 200;
private static final int STORAGE_PERMISSION_REQUEST = 300;
private Context mContext;
private Uri mImageUri;
private ImageView ivImg;
private TextView tvProgress;
private ProgressBar progressBar;
private String mImagePath;
private File photoFile;
public UploadImageFragment() {
// Required empty public constructor
}
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
mContext = context;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View parentView = inflater.inflate(R.layout.fragment_upload_image, container, false);
ivImg = parentView.findViewById(R.id.iv_img);
tvProgress = parentView.findViewById(R.id.tv_progress);
progressBar = parentView.findViewById(R.id.progressBar);
Button btnChoose = parentView.findViewById(R.id.btn_choose);
Button btnUpload = parentView.findViewById(R.id.btn_upload);
btnChoose.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
ChooseDialogFragment dialog = new ChooseDialogFragment();
dialog.setChooseDialogListener(UploadImageFragment.this);
dialog.show(getChildFragmentManager(), ChooseDialogFragment.class.getSimpleName());
}
});
btnUpload.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mImageUri == null) {
Toast.makeText(mContext, "Please take an image", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(mContext, "Image URI Found : " + mImageUri.toString(), Toast.LENGTH_LONG).show();
}
}
});
return parentView;
}
#Override
public void onGalleryButtonClick() {
Intent i = new Intent();
i.setType("image/*"); // specify the type of data you expect
i.setAction(Intent.ACTION_GET_CONTENT); // we need to get content from another act.
startActivityForResult(Intent.createChooser(i, "choose App"), PICK_IMAGE);
}
#Override
public void onCameraButtonClick() {
if (isPermissionGranted()) {
openCamera();
} else {
showRunTimePermission();
}
}
private void openCamera() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(mContext.getPackageManager()) != null) {
// Create the File where the photo should go
photoFile = null;
try {
photoFile = createFileInstance();
} catch (IOException ex) {
// Error occurred while creating the File
Log.d("capture_error", ex.toString());
}
// Continue only if the File was successfully created
if (photoFile != null) {
mImageUri = FileProvider.getUriForFile(mContext,
"com.example.cameragalleryimage.fileprovider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri); //this code was messing, However adding this code will make "Intent data" (in "onActivityResult") to be null
Glide.with(mContext).load(mImageUri).into(ivImg);//solution ask glide to load the image using uri
startActivityForResult(takePictureIntent, CAPTURE_IMAGE);
}
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK && data != null) {
if (requestCode == PICK_IMAGE) {// img from gallery
try {
Uri imgUri = data.getData();
InputStream imageStream = mContext.getContentResolver().openInputStream(imgUri);//2
Bitmap selectedImageBitmap = BitmapFactory.decodeStream(imageStream);//3}
mImageUri = imgUri;
ivImg.setImageBitmap(selectedImageBitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
} else {
if (requestCode == CAPTURE_IMAGE) {
if (photoFile.length() == 0) {
Toast.makeText(mContext, "You took an image, but you canceled it!", Toast.LENGTH_SHORT).show();
mImageUri = null;
}
}
}
}
private File createFileInstance() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "IMG_" + timeStamp + "_";
File storageDir = mContext.getExternalFilesDir(Environment.DIRECTORY_PICTURES);// mContext.getExternalCacheDir();
File image = new File(storageDir.toString()+"/"+imageFileName+".png");
// Save a file: path for use with ACTION_VIEW intents
mImagePath = image.getAbsolutePath();
return image;
}
private boolean isPermissionGranted() {
return ActivityCompat.checkSelfPermission(mContext, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
}
public void showRunTimePermission() {
// Permission is not Granted !
// we should Request the Permission!
// put all permissions you need in this Screen into string array
String[] permissionsArray = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
//here we requet the permission
requestPermissions(permissionsArray, STORAGE_PERMISSION_REQUEST);
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// user grants the Permission!
// you can call the function to write/read to storage here!
openCamera();
} else {
// user didn't grant the Permission we need
Toast.makeText(mContext, "Please Grant the Permission To use this Feature!", Toast.LENGTH_LONG).show();
}
}
}

If you are updated to Android10. Then use below code snippet.
<application android:requestLegacyExternalStorage="true" ... >
...
</application>

Related

Getting Cannot load null bitmap when loading images from gallery

I'm trying to load images from Camera and Gallery to load inside Tensor flow lite model.
When loading image from gallery, I'm getting following errors.
2021-01-02 11:48:03.309 9858-9858/com.example.coco_classif E/BitmapFactory: Unable to decode stream: java.io.FileNotFoundException: /storage/emulated/0/Pictures/20200714_135735 (1).jpg: open failed: EACCES (Permission denied)
2021-01-02 11:48:03.332 9858-9858/com.example.coco_classif E/ErrorĀ log: java.lang.NullPointerException: Cannot load null bitmap.
NOTE: Issues seems coming from the try catch block, loading from camera works fine
mainfest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.coco_classif">
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<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/Theme.Coco_classif">
<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>
Main Activity
package com.example.coco_classif;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import android.Manifest;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.Image;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class MainActivity extends AppCompatActivity {
private static final int CAMERA_PERMISSION_REQUEST_CODE = 1000;
private static final int CAMERA_REQUEST_CODE = 10001;
private ImageView imageView;
private ListView listView;
private ImageClassifier imageClassifier;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
inaializeUIElements();
}
private void inaializeUIElements() {
imageView = findViewById(R.id.iv_capture);
listView = findViewById(R.id.lv_probabilities);
Button takepicture = findViewById(R.id.bt_take_picture);
try {
imageClassifier = new ImageClassifier(this);
} catch (IOException e) {
Log.e("Error While Creating Image Classifier", "Error" +e);
}
takepicture.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(hasPermission()) {
selectImage();
}else{
requestPermission();
}
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == 1) {
Bitmap photo = (Bitmap) Objects.requireNonNull(Objects.requireNonNull(data).getExtras()).get("data");
imageView.setImageBitmap(photo);
List<ImageClassifier.Recognition> predictions = imageClassifier.recognizeImage(photo, 0);
final List<String> predictionList = new ArrayList<>();
for(ImageClassifier.Recognition recog: predictions){
predictionList.add("Label: " + recog.getName() + "Confidence: " + recog.getConfidance());
}
ArrayAdapter<String> predictionsAdapter = new ArrayAdapter<>(
this,R.layout.support_simple_spinner_dropdown_item,predictionList);
listView.setAdapter(predictionsAdapter);
}
else if (requestCode == 2) {
try {
Uri selectedImage = data.getData();
String[] filePath = new String[]{MediaStore.Images.Media.DATA};
Cursor c = getContentResolver().query(selectedImage,filePath, null, null, null);
c.moveToFirst();
int columnIndex = c.getColumnIndex(filePath[0]);
String picturePath = c.getString(columnIndex);
c.close();
Bitmap thumbnail = (BitmapFactory.decodeFile(picturePath));
Log.w("path of image from gallery......******************.........", picturePath+"");
Toast.makeText(this,picturePath.toString(),Toast.LENGTH_LONG).show();
imageView.setImageBitmap(thumbnail);
List<ImageClassifier.Recognition> predictions = imageClassifier.recognizeImage(thumbnail, 0);
final List<String> predictionList = new ArrayList<>();
for(ImageClassifier.Recognition recog: predictions){
predictionList.add("Label: " + recog.getName() + "Confidence: " + recog.getConfidance());
}
ArrayAdapter<String> predictionsAdapter = new ArrayAdapter<>(
this,R.layout.support_simple_spinner_dropdown_item,predictionList);
listView.setAdapter(predictionsAdapter);
}catch (Exception e){
Toast.makeText(this,e.toString(),Toast.LENGTH_LONG).show();
Log.e("Error log", e.toString());
}
}
}
super.onActivityResult(requestCode, resultCode, data);
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(hasAllPermissions(grantResults)){
openCamera();
}else {
requestPermission();
}
}
private boolean hasAllPermissions(int[] grantResults) {
for(int result : grantResults){
if (result == PackageManager.PERMISSION_DENIED)
return false;
}
return true;
}
private void requestPermission() {
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
if(shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)){
Toast.makeText(this," Permission required",Toast.LENGTH_SHORT).show();
}
requestPermissions(new String[]{Manifest.permission.CAMERA}, CAMERA_PERMISSION_REQUEST_CODE);
}
}
private void openCamera() {
Intent camerIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(camerIntent,CAMERA_REQUEST_CODE);
}
private boolean hasPermission() {
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
return checkSelfPermission(Manifest.permission.CAMERA)== PackageManager.PERMISSION_GRANTED;
}
return true;
}
private void selectImage() {
final CharSequence[] options = {"Take Photo", "Choose from Gallery", "Cancel"};
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle("Add Photo!");
builder.setItems(options, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int item) {
if (options[item].equals("Take Photo")) {
Intent camerIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(camerIntent,1);
} else if (options[item].equals("Choose from Gallery")) {
Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, 2);
} else if (options[item].equals("Cancel")) {
dialog.dismiss();
}
}
});
builder.show();
}
}
Note: This code snippet worked for only writing a text file and I used this method to solve
open failed: EACCES (Permission denied)
I know your Implementation has to deal with images and that is causing this 2021-01-02 11:48:03.332 9858-9858/com.example.coco_classif E/Error log: java.lang.NullPointerException: Cannot load null bitmap.
Also, check out this Exception 'open failed: EACCES (Permission denied)' on Android
I had the exact same problem, all I did was create a directory and write a text file in it.
Also, it is a good practice to create a new filename for images programmatically, use the Date formatter.
As I can see you are using an alert dialog to select images, I suggest you should not do it that way, alert dialog causes a lot of synchronization problems.
This code is tested on android Q One Plus 6t works fine without any errors.
public void generateNoteOnSD(Context context, String sFileName, String sBody) {
try {
File root = new File(String.valueOf(Environment.getExternalStorageDirectory())+"/sysInfoReports");
if (!root.exists()) {
root.mkdirs();
}
File gpxfile = new File(root, sFileName);
FileWriter writer = new FileWriter(gpxfile);
writer.append(sBody);
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Check you permissions
: Old storage permissions do not work on Android R.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

Trying To get text file from storage in Android Studio [duplicate]

This question already has answers here:
Create a file from a photo URI on Android
(1 answer)
Android - Get real path of a .txt file selected from the file explorer
(1 answer)
Closed 3 years ago.
I'm trying to get text file from the storage.
Here is my code. It is catching IOexception, why?
I had created a button which lets me choose the text file but as soon as click on the
file it does give me any path TOAST and it does not send the text to my text view.
Here is my code below:
package com.example.filechooser2;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.nio.BufferUnderflowException;
public class MainActivity extends AppCompatActivity {
private static final int PERMISSION_REQUEST_STORAGE = 1000;
private static final int READ_REQUEST_CODE =400 ;
Button b_load;
TextView tv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
b_load = (Button) findViewById(R.id.b_load);
tv = (TextView) findViewById(R.id.tv);
b_load.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
performFileSearch();
}
});
//requesting permission
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED)
{
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},PERMISSION_REQUEST_STORAGE);
}
}
This is where the code creates problem i think because
it shows the Exception error , please help
// Reading Content
private String readText(String input)
{
File file = new File(Environment.getExternalStorageDirectory(),input);
StringBuilder text = new StringBuilder();
try{
BufferedReader br = new BufferedReader(new FileReader(file));
String line;
while((line = br.readLine()) != null)
{
text.append(line);
text.append("\n");
} br.close();
}
catch (IOException e){
e.printStackTrace();
Toast.makeText(this,"Messed up",Toast.LENGTH_SHORT).show();
}
return text.toString();
}
// NOW TO GET FROM FILE SYSTEM
private void performFileSearch()
{
Intent i = new Intent (Intent.ACTION_OPEN_DOCUMENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("text/*");
startActivityForResult(i,READ_REQUEST_CODE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data)
{
if(requestCode == READ_REQUEST_CODE && resultCode == Activity.RESULT_OK);
{
if(data != null)
{
Uri uri = data.getData();
String Path = uri.getPath();
Path = Path.substring(Path.indexOf(":")+1);
if(Path.contains("emulated"))
{
Path = Path.substring(Path.indexOf("0")+1);
}
Toast.makeText(this,""+Path,Toast.LENGTH_SHORT);
tv.setText(readText(Path));
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if(requestCode==PERMISSION_REQUEST_STORAGE){
if (grantResults[0]==PackageManager.PERMISSION_GRANTED)
{
Toast.makeText(this,"Permisssion Granted",Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(this,"Permission Not Given",Toast.LENGTH_SHORT).show();
finish();
}
}
}
}

Nothing happens when I click "Browse Image" on my webview app

Recently I made webview app on Android Studio. And I notice weird problem: When user click on "Browse Image" link nothing happens. I am trying to make a code so user can choose file from their Gallery on mobile phone.
emulator screenshot
Here is my MainActivity.java
package com.ijust2.ijust2;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.net.Uri;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.webkit.ValueCallback;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import java.io.File;
public class MainActivity extends Activity {
private WebView webView;
private ValueCallback<Uri> mUploadMessage;
private final static int FILECHOOSER_RESULTCODE=1;
private static final int PICK_IMAGE = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
webView = (WebView) findViewById(R.id.webView);
webView.setWebViewClient(new myWebClient());
webView.getSettings().setJavaScriptEnabled(true);
webView.loadUrl("http://ijust2.com");
}
public class myWebClient extends WebViewClient
{
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
}
#Override
// This method is used to detect back button
public void onBackPressed() {
if(webView.canGoBack()) {
webView.goBack();
} else {
// Let the system handle the back button
super.onBackPressed();
}
}
}
my activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.ijust2.ijust2.MainActivity">
<WebView
android:id="#+id/webView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</RelativeLayout>
Can anyone give me some tips or suggest what should I do. I am newbie.
Thanks, Edi
I found a solution. Here is a code:
package it.floryn90.webapp;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Parcelable;
import android.provider.MediaStore;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MainActivity extends ActionBarActivity {
private static final int INPUT_FILE_REQUEST_CODE = 1;
private static final int FILECHOOSER_RESULTCODE = 1;
private static final String TAG = MainActivity.class.getSimpleName();
private WebView webView;
private WebSettings webSettings;
private ValueCallback<Uri> mUploadMessage;
private Uri mCapturedImageURI = null;
private ValueCallback<Uri[]> mFilePathCallback;
private String mCameraPhotoPath;
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (requestCode != INPUT_FILE_REQUEST_CODE || mFilePathCallback == null) {
super.onActivityResult(requestCode, resultCode, data);
return;
}
Uri[] results = null;
// Check that the response is a good one
if (resultCode == Activity.RESULT_OK) {
if (data == null) {
// If there is not data, then we may have taken a photo
if (mCameraPhotoPath != null) {
results = new Uri[]{Uri.parse(mCameraPhotoPath)};
}
} else {
String dataString = data.getDataString();
if (dataString != null) {
results = new Uri[]{Uri.parse(dataString)};
}
}
}
mFilePathCallback.onReceiveValue(results);
mFilePathCallback = null;
} else if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
if (requestCode != FILECHOOSER_RESULTCODE || mUploadMessage == null) {
super.onActivityResult(requestCode, resultCode, data);
return;
}
if (requestCode == FILECHOOSER_RESULTCODE) {
if (null == this.mUploadMessage) {
return;
}
Uri result = null;
try {
if (resultCode != RESULT_OK) {
result = null;
} else {
// retrieve from the private variable if the intent is null
result = data == null ? mCapturedImageURI : data.getData();
}
} catch (Exception e) {
Toast.makeText(getApplicationContext(), "activity :" + e,
Toast.LENGTH_LONG).show();
}
mUploadMessage.onReceiveValue(result);
mUploadMessage = null;
}
}
return;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = (WebView) findViewById(R.id.webview);
webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setLoadWithOverviewMode(true);
webSettings.setAllowFileAccess(true);
webView.setWebViewClient(new Client());
webView.setWebChromeClient(new ChromeClient());
if (Build.VERSION.SDK_INT >= 19) {
webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
}
else if(Build.VERSION.SDK_INT >=11 && Build.VERSION.SDK_INT < 19) {
webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
webView.loadUrl("http://example.com"); //change with your website
}
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
File imageFile = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
return imageFile;
}
public class ChromeClient extends WebChromeClient {
// For Android 5.0
public boolean onShowFileChooser(WebView view, ValueCallback<Uri[]> filePath, WebChromeClient.FileChooserParams fileChooserParams) {
// Double check that we don't have any existing callbacks
if (mFilePathCallback != null) {
mFilePathCallback.onReceiveValue(null);
}
mFilePathCallback = filePath;
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
takePictureIntent.putExtra("PhotoPath", mCameraPhotoPath);
} catch (IOException ex) {
// Error occurred while creating the File
Log.e(TAG, "Unable to create Image File", ex);
}
// Continue only if the File was successfully created
if (photoFile != null) {
mCameraPhotoPath = "file:" + photoFile.getAbsolutePath();
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
} else {
takePictureIntent = null;
}
}
Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
contentSelectionIntent.setType("image/*");
Intent[] intentArray;
if (takePictureIntent != null) {
intentArray = new Intent[]{takePictureIntent};
} else {
intentArray = new Intent[0];
}
Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
startActivityForResult(chooserIntent, INPUT_FILE_REQUEST_CODE);
return true;
}
// openFileChooser for Android 3.0+
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
mUploadMessage = uploadMsg;
// Create AndroidExampleFolder at sdcard
// Create AndroidExampleFolder at sdcard
File imageStorageDir = new File(
Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES)
, "AndroidExampleFolder");
if (!imageStorageDir.exists()) {
// Create AndroidExampleFolder at sdcard
imageStorageDir.mkdirs();
}
// Create camera captured image file path and name
File file = new File(
imageStorageDir + File.separator + "IMG_"
+ String.valueOf(System.currentTimeMillis())
+ ".jpg");
mCapturedImageURI = Uri.fromFile(file);
// Camera capture image intent
final Intent captureIntent = new Intent(
android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mCapturedImageURI);
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
// Create file chooser intent
Intent chooserIntent = Intent.createChooser(i, "Image Chooser");
// Set camera intent to file chooser
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS
, new Parcelable[] { captureIntent });
// On select image call onActivityResult method of activity
startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE);
}
// openFileChooser for Android < 3.0
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
openFileChooser(uploadMsg, "");
}
//openFileChooser for other Android versions
public void openFileChooser(ValueCallback<Uri> uploadMsg,
String acceptType,
String capture) {
openFileChooser(uploadMsg, acceptType);
}
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
// Check if the key event was the Back button and if there's history
if ((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()) {
webView.goBack();
return true;
}
// If it wasn't the Back key or there's no web page history, bubble up to the default
// system behavior (probably exit the activity)
return super.onKeyDown(keyCode, event);
}
public class Client extends WebViewClient {
ProgressDialog progressDialog;
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// If url contains mailto link then open Mail Intent
if (url.contains("mailto:")) {
// Could be cleverer and use a regex
//Open links in new browser
view.getContext().startActivity(
new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
// Here we can open new activity
return true;
}else {
// Stay within this webview and load url
view.loadUrl(url);
return true;
}
}
//Show loader on url load
public void onPageStarted(WebView view, String url, Bitmap favicon) {
// Then show progress Dialog
// in standard case YourActivity.this
if (progressDialog == null) {
progressDialog = new ProgressDialog(MainActivity.this);
progressDialog.setMessage("Loading...");
progressDialog.show();
}
}
// Called when all page resources loaded
public void onPageFinished(WebView view, String url) {
try {
// Close progressDialog
if (progressDialog.isShowing()) {
progressDialog.dismiss();
progressDialog = null;
}
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
}

App crashes due to java.lang.SecurityException

I am working on the project of capturing photos or picking images from gallery and show it in the recycler view, the app is working good in Android-lollipop but crashes in marshmallow one as soon as camera button is clicked giving the exception
Caused by: java.lang.SecurityException: Permission Denial: writing com.android.providers.media.MediaProvider uri content://media/external/images/media from pid=1983, uid=10060 requires android.permission.WRITE_EXTERNAL_STORAGE, or grantUriPermission()
Here is the code:
Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.urjapawar.bevypart2">
<uses-permission tools:node="replace" android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission tools:node="replace" android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-feature
android:name="android.hardware.camera"
android:required="false"/>
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme"
>
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity><!-- ATTENTION: This was auto-generated to add Google Play services to your project for
App Indexing. See https://g.co/AppIndexing/AndroidStudio for more information. -->
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
</application>
</manifest>
Images.java
public class Images {
String path;
public void setPath(String path) { this.path = path; }
public String getPath() {
return path;
}
/**
* Gets path.
*
* #return Value of path.
*/
#Override public String toString() {
return "\nPath:" + path;
}
}
MainActivity.java
import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.View;
import com.google.android.gms.appindexing.AppIndex;
import com.google.android.gms.common.api.GoogleApiClient;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
private ArrayList<Images> images;
private ImageAdapter imageAdapter;
private RecyclerView rv;
private LinearLayoutManager llm;
private Uri mCapturedImageURI;
private static final int RESULT_LOAD_IMAGE = 1;
private static final int REQUEST_IMAGE_CAPTURE = 2;
/**
* ATTENTION: This was auto-generated to implement the App Indexing API.
* See https://g.co/AppIndexing/AndroidStudio for more information.
*/
private GoogleApiClient client;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
images = new ArrayList<>();
imageAdapter = new ImageAdapter(images);
rv = (RecyclerView) findViewById(R.id.rv);
llm = new LinearLayoutManager(this);
rv.setLayoutManager(llm);
imageAdapter = new ImageAdapter(images);
rv.setAdapter(imageAdapter);
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
}
public void activeCamera(View view) {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
String fileName = "temp.jpg";
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, fileName);
mCapturedImageURI = getContentResolver()
.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
values);
takePictureIntent
.putExtra(MediaStore.EXTRA_OUTPUT, mCapturedImageURI);
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
public void activeGallery(View view) {
Intent intent = new Intent(Intent.ACTION_PICK,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, RESULT_LOAD_IMAGE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case RESULT_LOAD_IMAGE:
Uri selectedImage = null;
if (requestCode == RESULT_LOAD_IMAGE &&
resultCode == RESULT_OK && null != data) {
if (Build.VERSION.SDK_INT < 19) {
selectedImage = data.getData();
} else {
selectedImage = data.getData();
}
String[] filePathColumn = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver()
.query(selectedImage, filePathColumn, null, null,
null);
if (cursor != null && cursor.getCount() > 0) {
cursor.moveToFirst();
}
// cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String picturePath = cursor.getString(columnIndex);
cursor.close();
Images image = new Images();
image.setPath(picturePath);
images.add(image);
}
case REQUEST_IMAGE_CAPTURE:
if (requestCode == REQUEST_IMAGE_CAPTURE &&
resultCode == RESULT_OK) {
String[] projection = {MediaStore.Images.Media.DATA};
Cursor cursor =
getContentResolver().query(mCapturedImageURI, projection, null,
null, null);
int column_index_data = cursor.getColumnIndexOrThrow(
MediaStore.Images.Media.DATA);
cursor.moveToFirst();
String picturePath = cursor.getString(column_index_data);
Images image = new Images();
image.setPath(picturePath);
images.add(image);
cursor.close();
}
}
}
}
ImageAdapter.java
import android.graphics.BitmapFactory;
import android.media.ThumbnailUtils;
import android.net.Uri;
import android.support.v7.widget.*;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import java.util.List;
public class ImageAdapter extends android.support.v7.widget.RecyclerView.Adapter<ImageAdapter.ImgViewHolder> {
List<Images> images;
ImageAdapter(List<Images> img){
this.images = img;
}
public class ImgViewHolder extends android.support.v7.widget.RecyclerView.ViewHolder
{
ImageView personPhoto;
CardView cv;
public ImgViewHolder(View itemView) {
super(itemView);
cv = (CardView)itemView.findViewById(R.id.card_view);
personPhoto=(ImageView)itemView.findViewById(R.id.thumbnail);
}
}
#Override
public ImgViewHolder onCreateViewHolder(final ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.single_card, viewGroup, false);
ImgViewHolder pvh = new ImgViewHolder(v);
return pvh;
}
#Override
public int getItemCount() {
return images.size();
}
#Override
public void onBindViewHolder(ImgViewHolder holder, int i) {
Images image = images.get(i);
final int THUMBSIZE = 96;
// viewHolder.imgIcon.setImageURI(Uri.fromFile(new File(image
// .getPath())));
holder.personPhoto.setImageBitmap(ThumbnailUtils
.extractThumbnail(BitmapFactory.decodeFile(image.getPath()),
THUMBSIZE, THUMBSIZE));
// holder.personPhoto.setImageURI(Uri.parse("file://" + images.getPath() + "/" + mDataset[position]));
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
}
I have checked many answers but not able to fix it, kindly help! Also while selecting images from gallery blank card shows up in marshmallow (no image content), it says Make sure the Cursor is initialized correctly before accessing data from it. while it works fine in lollipop one.
Any suggestions will be deeply appreciated.
You need to give android.hardware.Camera permission programmatically.
manifeast permission not work on Android Marshmallow
In marshmallow,We require runtime permissions for Storage,Contacts,Camera, etc. In edition to give these permissions in manifest for older version, We need to request them from users at Runtime for marshmallow.
For more details refer this : Marshmallow permissions
You must put Camera permission in code since android 6 + version checks for runtime permission.
public void getCameraPermission(){
if (!checkPermission()) {
requestPermission();
}
}
private boolean checkPermission(){
int result = ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA);
if (result == PackageManager.PERMISSION_GRANTED){
return true;
} else {
return false;
}
}
private void requestPermission(){
if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.CAMERA)){
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CAMERA}, PERMISSION_REQUEST_CODE);
} else {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CAMERA}, PERMISSION_REQUEST_CODE);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_CODE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(MainActivity.this,"Permission granted",Toast.LENGTH_SHORT).show();
//store permission in shared pref
}
else {
Toast.makeText(MainActivity.this,"Permission denied",Toast.LENGTH_SHORT).show();
//store permission in shared pref
}
break;
}
}
You need to add
<uses-permission android:name="android.permission.CAMERA" />
Just a thought, have you allowed your app to access your phone or SD card in the Manifest?
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

How to scan QRCode in android

I found a tutorial on how to scan a barcode. But in my application I have to scan a QR code. How can I a scan QR code in Android?
try {
Intent intent = new Intent("com.google.zxing.client.android.SCAN");
intent.putExtra("SCAN_MODE", "QR_CODE_MODE"); // "PRODUCT_MODE for bar codes
startActivityForResult(intent, 0);
} catch (Exception e) {
Uri marketUri = Uri.parse("market://details?id=com.google.zxing.client.android");
Intent marketIntent = new Intent(Intent.ACTION_VIEW,marketUri);
startActivity(marketIntent);
}
and in onActivityResult():
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 0) {
if (resultCode == RESULT_OK) {
String contents = data.getStringExtra("SCAN_RESULT");
}
if(resultCode == RESULT_CANCELLED){
//handle cancel
}
}
}
2016 update
The current recommendation is to use the Android Barcode API, which works locally (offline), without requiring a server roundtrip:
The Barcode API detects barcodes in real-time, on device, in any orientation. It can also detect multiple barcodes at once.
It reads the following barcode formats:
1D barcodes: EAN-13, EAN-8, UPC-A, UPC-E, Code-39, Code-93, Code-128, ITF, Codabar
2D barcodes: QR Code, Data Matrix, PDF-417, AZTEC
It automatically parses QR Codes, Data Matrix, PDF-417, and Aztec values, for the following supported formats:
URL
Contact information (VCARD, etc.)
Calendar event
Email
Phone
SMS
ISBN
WiFi
Geo-location (latitude and longitude)
AAMVA driver license/ID
Check out the codelab - Barcode Detection with the Mobile Vision API.
You can scan QR code easily with zxing add the following dependencies in your gradle
compile 'com.journeyapps:zxing-android-embedded:3.1.0#aar'
compile 'com.google.zxing:core:3.2.0'
Then in your Activity or on Fragment
IntentIntegrator scanIntegrator = new IntentIntegrator(context);
scanIntegrator.setPrompt("Scan");
scanIntegrator.setBeepEnabled(true);
//The following line if you want QR code
scanIntegrator.setDesiredBarcodeFormats(IntentIntegrator.QR_CODE_TYPES);
scanIntegrator.setCaptureActivity(CaptureActivityAnyOrientation.class);
scanIntegrator.setOrientationLocked(true);
scanIntegrator.setBarcodeImageEnabled(true);
scanIntegrator.initiateScan();
And then capture the result in onActivityResult
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
IntentResult scanningResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
if (scanningResult != null) {
if (scanningResult.getContents() != null) {
scanContent = scanningResult.getContents().toString();
scanFormat = scanningResult.getFormatName().toString();
}
Toast.makeText(this,scanContent+" type:"+scanFormat,Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(this,"Nothing scanned",Toast.LENGTH_SHORT).show();
}
}
Take a look at this sample project , hope it helps you .
One way is using the AppCompatActivity and ZXingScannerView.ResultHandler interface.
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.hardware.Camera;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraManager;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.RelativeLayout;;
import com.android.volley.VolleyError;
import com.example.team.merchant.functional.Request;
import com.example.team.merchant.functional.ResponseListener;
import com.google.zxing.Result;
import me.dm7.barcodescanner.zxing.ZXingScannerView;
/**
* Created by Prakhar on 5/16/2016.
*/
public class MerchantScannerActivity extends AppCompatActivity implements ZXingScannerView.ResultHandler {
private ZXingScannerView mScannerView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
RelativeLayout relativeLayout = new RelativeLayout(this);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(60, 60);
params.setMargins(0, 50, 50, 0);
params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
Button switchCamera = new Button(this); //declare a button in layout for camera change option
switchCamera.setLayoutParams(params);
switchCamera.setBackgroundResource(R.drawable.switch_camera);
relativeLayout.addView(switchCamera);
final int i = getFrontCameraId();
if (i == -1) {
switchCamera.setVisibility(View.GONE);
}
mScannerView = new ZXingScannerView(this); // Programmatically initialize the scanner view
relativeLayout.addView(mScannerView);
setContentView(relativeLayout);
final int[] id = {0};
switchCamera.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mScannerView.stopCamera();
if (id[0] % 2 == 0) {
mScannerView.startCamera(i);
} else {
mScannerView.startCamera();
}
id[0]++;
}
});
mScannerView.setResultHandler(this);// Register ourselves as a handler for scan results.
mScannerView.startCamera(); // Start camera
}
#SuppressLint("NewApi")
int getFrontCameraId() {
if (Build.VERSION.SDK_INT < 22) {
Camera.CameraInfo ci = new Camera.CameraInfo();
for (int i = 0; i < Camera.getNumberOfCameras(); i++) {
Camera.getCameraInfo(i, ci);
if (ci.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) return i;
}
} else {
try {
CameraManager cManager = (CameraManager) getApplicationContext()
.getSystemService(Context.CAMERA_SERVICE);
String[] cameraId = cManager.getCameraIdList();
for (int j = 0; j < cameraId.length; j++) {
CameraCharacteristics characteristics = cManager.getCameraCharacteristics(cameraId[j]);
int cOrientation = characteristics.get(CameraCharacteristics.LENS_FACING);
if (cOrientation == CameraCharacteristics.LENS_FACING_FRONT)
return Integer.parseInt(cameraId[j]);
}
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
return -1; // No front-facing camera found
}
#Override
public void onPause() {
super.onPause();
mScannerView.stopCamera(); // Stop camera on pause
}
#Override
public void handleResult(Result rawResult) {
// rawResult.getText()
// handle your result here
// handle exceptions here
}
}
Other can be used in fragments accordingly.
import android.Manifest;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.google.zxing.ResultPoint;
import com.journeyapps.barcodescanner.BarcodeCallback;
import com.journeyapps.barcodescanner.BarcodeResult;
import com.journeyapps.barcodescanner.CompoundBarcodeView;
/**
* Created by Prakhar on 3/8/2016.
*/
public class PayWithQrCodeScannerFragment extends Fragment {
private static final int PERMISSION_REQUEST_CAMERA = 23;
public static CompoundBarcodeView barcodeScannerView;
public static BarcodeCallback callback;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.paywithqrcodescannerfragment, container, false);
barcodeScannerView = (CompoundBarcodeView) view.findViewById(R.id.zxing_barcode_scanner);
callback = new BarcodeCallback() {
#Override
public void barcodeResult(BarcodeResult result) {
// handle result and exceptions here
}
return view;
}
/**
* Check if the device's camera has a Flashlight.
*
* #return true if there is Flashlight, otherwise false.
*/
private boolean hasFlash() {
return getActivity().getApplicationContext().getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
}
#Override
public void onResume() {
super.onResume();
if (android.os.Build.VERSION.SDK_INT < 23) {
barcodeScannerView.resume();
}
}
#Override
public void onPause() {
super.onPause();
if (android.os.Build.VERSION.SDK_INT < 23) {
barcodeScannerView.pause();
}
}
}
Use below written in layout XML file to placeholder the scanner
<com.journeyapps.barcodescanner.CompoundBarcodeView
android:id="#+id/zxing_barcode_scanner"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:zxing_preview_scaling_strategy="centerCrop"
app:zxing_use_texture_view="false" />
Build.gradle
compile 'com.journeyapps:zxing-android-embedded:3.2.0#aar'
compile 'com.google.zxing:core:3.2.1'
My way is to use barcodescanner. I uses zxing for scanning bar codes and QR codes. The version 1.9 of the library utilises zxing v3.2.1. It's a wrapper for zxing so the usage is simplier.
In order to do this:
Add dependency to gradle
compile 'me.dm7.barcodescanner:zxing:1.9'
Add camera permission to manifest
<uses-permission android:name="android.permission.CAMERA"/>
Create activity, that will handle scanning
Manifest:
<activity
android:name=".view.component.ScannerActivity"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:theme="#style/AppThemeTransparent"/>
styles.xml:
<style name="AppThemeTransparent" parent="#style/Theme.AppCompat.Light">
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="colorPrimary">#color/colorPrimary</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowContentOverlay">#null</item>
</style>
Create scanner activity:
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.WindowManager;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.Result;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import me.dm7.barcodescanner.zxing.ZXingScannerView;
public class ScannerActivity extends Activity implements ZXingScannerView.ResultHandler {
public static final String EXCLUDED_FORMAT = "ExcludedFormat";
private static final String TAG = ScannerActivity.class.getSimpleName();
private ZXingScannerView mScannerView;
#Override
public void onCreate(Bundle state) {
setStatusBarTranslucent(true);
super.onCreate(state);
mScannerView = new ZXingScannerView(this);
setContentView(mScannerView);
}
protected void setStatusBarTranslucent(boolean makeTranslucent) {
if (makeTranslucent) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
} else {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}
#Override
public void onResume() {
super.onResume();
mScannerView.setResultHandler(this);
mScannerView.startCamera();
}
#Override
public void onPause() {
super.onPause();
mScannerView.stopCamera();
}
#Override
public void handleResult(Result rawResult) {
String result = rawResult.getText();
BarcodeFormat format = rawResult.getBarcodeFormat();
Log.v(TAG, "Scanned code: " + rawResult.getText());
Log.v(TAG, "Scanend code type: " + rawResult.getBarcodeFormat().toString());
//Return error
if (result == null) {
setResult(RESULT_CANCELED, returnErrorCode(result, format));
finish();
}
if (result.isEmpty()) {
setResult(RESULT_CANCELED, returnErrorCode(result, format));
finish();
}
//Return correct code
setResult(RESULT_OK, returnCorrectCode(result, format));
finish();
}
private Intent returnErrorCode(String result, BarcodeFormat format) {
Intent returnIntent = new Intent();
returnIntent.putExtra(ScannerConstants.ERROR_INFO, getResources().getString(R.string.scanner_error_message));
return returnIntent;
}
private Intent returnCorrectCode(String result, BarcodeFormat format) {
Intent returnIntent = new Intent();
returnIntent.putExtra(ScannerConstants.SCAN_RESULT, result);
if (format.equals(BarcodeFormat.QR_CODE)) {
returnIntent.putExtra(ScannerConstants.SCAN_RESULT_TYPE, ScannerConstants.QR_SCAN);
} else {
returnIntent.putExtra(ScannerConstants.SCAN_RESULT_TYPE, ScannerConstants.BAR_SCAN);
}
return returnIntent;
}
public void excludeFormats(BarcodeFormat item) {
Collection<BarcodeFormat> defaultFormats = mScannerView.getFormats();
List<BarcodeFormat> formats = new ArrayList<>();
for (BarcodeFormat format : defaultFormats) {
if (!format.equals(item)) {
formats.add(format);
}
}
mScannerView.setFormats(formats);
}
public interface ScannerConstants {
public static final String SCAN_MODES = "SCAN_MODES";
public static final String SCAN_RESULT = "SCAN_RESULT";
public static final String SCAN_RESULT_TYPE = "SCAN_RESULT_TYPE";
public static final String ERROR_INFO = "ERROR_INFO";
public static final int BAR_SCAN = 0;
public static final int QR_SCAN = 1;
}
}
Just be sure, that on API 23+ devices a permission for camera usage is granted for the application.
Open the Activity just like the normal one with result expectation:
Intent intent = new Intent(AddEquipmentActivity.this, ScannerActivity.class);
startActivityForResult(intent, SCAN_SERIAL_REQUEST);
Here is the function that scans the QR Code.
public void scanQR(View v)
{
try
{
Intent intent = new Intent(ACTION_SCAN);
intent.putExtra("SCAN_MODE", "QR_CODE_MODE");
startActivityForResult(intent, 0);
}
catch (ActivityNotFoundException anfe)
{
showDialog(ActivityUserDetails.this, "No Scanner Found",
"Download a scanner code activity?", "Yes", "No").show();
}
}
In the above code snippet, I have invoked showDialog() method from catch block, that will show an AlertDialog for asking to install "Barcode Scanner" app from Google Play. Given below is the code for showDialog method.
private static AlertDialog showDialog(final Activity act,
CharSequence title, CharSequence message, CharSequence buttonYes,
CharSequence buttonNo)
{
AlertDialog.Builder downloadDialog = new AlertDialog.Builder(act);
downloadDialog.setTitle(title);
downloadDialog.setMessage(message);
downloadDialog.setPositiveButton(buttonYes,
new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialogInterface, int i)
{
Uri uri = Uri.parse("market://search?q=pname:"
+ "com.google.zxing.client.android");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
try
{
act.startActivity(intent);
}
catch (ActivityNotFoundException anfe)
{
}
}
});
downloadDialog.setNegativeButton(buttonNo,
new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialogInterface, int i)
{
}
});
return downloadDialog.show();
}
I have used this function on Button click event. Therefore the code for Button is given below (xml file).
<Button
android:id="#+id/button_wr_scan"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:background="#drawable/button_shadow"
android:onClick="scanQR"
android:paddingRight="4dp"
android:paddingTop="4dp"
android:text="ScanQR" />
NOTE: The prerequisite for using this function is that you must have pre installed "Barcode Scanner" app in your device.
Hope it helps.
Thanks :)
Step by step to setup zxing 3.2.1 in eclipse
Download zxing-master.zip from "https://github.com/zxing/zxing"
Unzip zxing-master.zip, Use eclipse to import "android" project in zxing-master
Download core-3.2.1.jar from "http://repo1.maven.org/maven2/com/google/zxing/core/3.2.1/"
Create "libs" folder in "android" project and paste cor-3.2.1.jar into the libs folder
Click on project: choose "properties" -> "Java Compiler" to change level to 1.7. Then click on "Android" change "Project build target" to android 4.4.2+, because using 1.7 requires compiling with Android 4.4
If "CameraConfigurationUtils.java" don't exist in "zxing-master/android/app/src/main/java/com/google/zxing/client/android/camera/". You can copy it from "zxing-master/android-core/src/main/java/com/google/zxing/client/android/camera/" and paste to your project.
Clean and build project. If your project show error about "switch - case", you should change them to "if - else".
Completed. Clean and build project
Reference link: How to use Zxing in android
module gradle
dependencies {
implementation 'com.journeyapps:zxing-android-embedded:4.1.0'
}
activity.kt
package com.example.qrcode
import android.content.Intent
import android.os.Bundle
import android.widget.Button
import android.widget.ImageButton
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import com.google.android.material.internal.ContextUtils.getActivity
import com.google.zxing.integration.android.IntentIntegrator
import com.google.zxing.integration.android.IntentResult
class LicenseCheck : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.licensecheck)
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
fun checklicense(license: String){
Toast.makeText(this, license, Toast.LENGTH_SHORT).show()
}
val scanbtn = findViewById(R.id.qrscanner) as ImageButton
scanbtn.setOnClickListener {
val integrator = IntentIntegrator(this)
integrator.setDesiredBarcodeFormats(IntentIntegrator.QR_CODE)
integrator.setPrompt("Focus QRCode from App...")
integrator.setCameraId(0)
integrator.setBeepEnabled(true)
integrator.setBarcodeImageEnabled(false)
integrator.initiateScan()
}
#Override
fun onActivityResult(requestCode:Int, resultCode:Int, data: Intent) {
var result: IntentResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
if (result.getContents() == null) {
Toast.makeText(this, "Scanning failed!", Toast.LENGTH_LONG).show();
} else {
checklicense(result.getContents());
}
}
}
}

Categories

Resources