I am trying to create a webView for my web application in which i also can upload pictures using camera, i get the option to choose between camera or file manager and the file manager works perfect. With the camera option it opens the camera but when i then click on capture and send it does not return anything and does not load the img into the input field.
After doing some research i figured out that response.getData().getDataString() does not return anything when using the camera to capture a picture but does return something when using the file explorer to send a picture
Here is my MainActivity.java
package com.webview.android;
import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.webkit.PermissionRequest;
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 com.karan.churi.PermissionManager.PermissionManager;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MainActivity extends AppCompatActivity {
private WebView webView;
PermissionManager permissionManager;
private static final String TAG = MainActivity.class.getSimpleName();
private String mCM;
private ValueCallback<Uri> mUM;
private ValueCallback<Uri[]> mUMA;
private ActivityResultLauncher<Intent> imgFinished = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
#Override
public void onActivityResult(ActivityResult response) {
if (Build.VERSION.SDK_INT >= 21) {
Uri[] results = null;
//Check if response is positive
if (response.getResultCode() == Activity.RESULT_OK) {
if (null == mUMA) {
return;
}
if (response.getData() == null) {
//Capture Photo if no image available
if (mCM != null) {
results = new Uri[]{Uri.parse(mCM)};
}
} else {
Log.e(TAG, "TEST5");
String dataString = response.getData().getDataString();
Log.e(TAG, String.valueOf(response.getData().getDataString()));
if (dataString != null) {
Log.e(TAG, "TEST6");
results = new Uri[]{Uri.parse(dataString)};
}
}
}
mUMA.onReceiveValue(results);
mUMA = null;
} else {
if (null == mUM) return;
Uri result = response == null || response.getResultCode() != RESULT_OK ? null : response.getData().getData();
mUM.onReceiveValue(result);
mUM = null;
}
}
}
);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = findViewById(R.id.webView);
webView.getSettings().setJavaScriptEnabled(true);
webView.loadUrl("https://hbwfc-acc.9knots.nl/app");
WebSettings MyWebviewSettings = webView.getSettings();
MyWebviewSettings.setAllowFileAccessFromFileURLs(true);
MyWebviewSettings.setAllowUniversalAccessFromFileURLs(true);
MyWebviewSettings.setJavaScriptCanOpenWindowsAutomatically(true);
MyWebviewSettings.setJavaScriptEnabled(true);
MyWebviewSettings.setDomStorageEnabled(true);
MyWebviewSettings.setJavaScriptCanOpenWindowsAutomatically(true);
MyWebviewSettings.setBuiltInZoomControls(true);
MyWebviewSettings.setAllowFileAccess(true);
MyWebviewSettings.setSupportZoom(true);
MyWebviewSettings.setAllowContentAccess(true);
MyWebviewSettings.setMediaPlaybackRequiresUserGesture(false);
webView.setWebChromeClient(new WebChromeClient() {
#Override
public void onPermissionRequest(final PermissionRequest request) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
request.grant(request.getResources());
}
}
//For Android 3.0+
public void openFileChooser(ValueCallback<Uri> uploadMsg){
mUM = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
imgFinished.launch(Intent.createChooser(i,"File Chooser"));
}
// For Android 3.0+, above method not supported in some android 3+ versions, in such case we use this
public void openFileChooser(ValueCallback uploadMsg, String acceptType){
mUM = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
imgFinished.launch(Intent.createChooser(i, "File Browser"));
}
//For Android 4.1+
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){
mUM = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
imgFinished.launch(Intent.createChooser(i, "File Chooser"));
}
//For Android 5.0+
public boolean onShowFileChooser(
WebView webView, ValueCallback<Uri[]> filePathCallback,
WebChromeClient.FileChooserParams fileChooserParams){
if(mUMA != null){
mUMA.onReceiveValue(null);
}
mUMA = filePathCallback;
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if(takePictureIntent.resolveActivity(MainActivity.this.getPackageManager()) != null){
File photoFile = null;
try{
photoFile = createImageFile();
takePictureIntent.putExtra("PhotoPath", mCM);
}catch(IOException ex){
Log.e(TAG, "Image file creation failed", ex);
}
if(photoFile != null){
mCM = "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("*/*");
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);
imgFinished.launch(chooserIntent);
return true;
}
});
webView.setWebViewClient(new WebViewClient());
webView.setWebContentsDebuggingEnabled(true);
permissionManager = new PermissionManager() {};
permissionManager.checkAndRequestPermissions(this);
}
public class Callback extends WebViewClient{
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl){
Toast.makeText(getApplicationContext(), "Failed loading app!", Toast.LENGTH_SHORT).show();
}
}
// Create an image file
private File createImageFile() throws IOException{
#SuppressLint("SimpleDateFormat") String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "img_"+timeStamp+"_";
File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File tempFile = File.createTempFile(imageFileName,".jpg",storageDir);
return tempFile;
}
here is my manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.webview.android">
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO"/>
<queries>
<intent>
<action android:name="android.media.action.IMAGE_CAPTURE" />
</intent>
</queries>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true">
<activity android:name=".MainActivity"
android:exported="true"
android:theme="#style/Theme.AppCompat.DayNight">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths"/>
</provider>
</application>
</manifest>
I expect it loads a img file into the input field
I solved the problem by replacing
Uri.fromfile(photoFile)
with
FileProvider.getUriForFile(MainActivity.this, BuildConfig.APPLICATION_ID, photoFile)
this creates a url tot he taken image in the same way as when you open a image from the file explorer
Related
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 make a web view app for a site. although everything works fine, unable to resolve few errors that are popping up while I add this "file download" code.
Here's the android code :
Activity Main:
<?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">
<WebView
android:id="#+id/webview_sample"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
Main Activity.java
package com.appgrep.urstudymate;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.annotation.SuppressLint;
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.os.Parcelable;
import android.provider.MediaStore;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
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 AppCompatActivity {
private final static int FCR = 1;
WebView webView;
private String mCM;
private ValueCallback<Uri> mUM;
private ValueCallback<Uri[]> mUMA;
private ValueCallback<Uri> mUploadMessage;
private Uri mCapturedImageURI = null;
private ValueCallback<Uri[]> mFilePathCallback;
private String mCameraPhotoPath;
private static final int INPUT_FILE_REQUEST_CODE = 1;
private static final int FILECHOOSER_RESULTCODE = 1;
private static final String TAG = MainActivity.class.getSimpleName();
#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;
}
#SuppressLint({"SetJavaScriptEnabled", "WrongViewCast"})
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = findViewById(R.id.webview_sample);
if (Build.VERSION.SDK_INT >= 23 && (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA}, 1);
}
assert webView != null;
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setAllowFileAccess(true);
webView.getSettings().setSupportZoom(true);
webView.getSettings().setBuiltInZoomControls(true);
if (Build.VERSION.SDK_INT >= 21) {
webSettings.setMixedContentMode(0);
webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
} else if (Build.VERSION.SDK_INT >= 19) {
webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
} else if (Build.VERSION.SDK_INT < 19) {
webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
webView.setWebViewClient(new Callback());
webView.loadUrl("https://urstudymate.com/");
webView.setWebChromeClient(new WebChromeClient() {
private File createImageFile() throws IOException {
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 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;
}
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);
}
public void openFileChooser(ValueCallback<Uri> uploadMsg,
String acceptType,
String capture) {
openFileChooser(uploadMsg, acceptType);
}
});
}
webView.setDownloadListener(new DownloadListener(){
#Override
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
DownloadManager.Request myRequest = new DownloadManager.Request(Uri.parse(url));
myRequest.allowScanningByMediaScanner();
myRequest.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
DownloadManager myManager = (DownloadManager)getSystemService(DOWNLOAD_SERVICE);
myManager.enqueue(myRequest);
Toast.makeText(getApplicationContext(), "File is Downloading...", Toast.LENGTH_SHORT).show();
}
});
public class Callback extends WebViewClient {
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
Toast.makeText(getApplicationContext(), "Failed loading app!", Toast.LENGTH_SHORT).show();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater myMenuInflater = getMenuInflater();
myMenuInflater.inflate(R.menu.super_menu, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.myMenuOne:
onBackPressed();
break;
case R.id.myMenuTwo:
GoForward();
break;
}
return true;
}
private void GoForward() {
if (webView.canGoForward()) {
webView.goForward();
} else {
Toast.makeText(this, "Can't go further!", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onBackPressed() {
if (webView.canGoBack()) {
webView.goBack();
}
}
}
Super Menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu 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" tools:context="com.filechooser.file.MainActivity">
<item android:id="#+id/myMenuOne" android:icon="#drawable/ic_arrow_back_black_24dp" android:title="Item" app:showAsAction="always" />
<item android:id="#+id/myMenuTwo" android:icon="#drawable/ic_arrow_back_black_24dp" android:title="Item" app:showAsAction="always" />
</menu>
Android Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.appgrep.urstudymate">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.INTERNET" />
<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:usesCleartextTraffic="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>
However the piece of code I added is :
webView.setDownloadListener(new DownloadListener(){
#Override
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
DownloadManager.Request myRequest = new DownloadManager.Request(Uri.parse(url));
myRequest.allowScanningByMediaScanner();
myRequest.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
DownloadManager myManager = (DownloadManager)getSystemService(DOWNLOAD_SERVICE);
myManager.enqueue(myRequest);
Toast.makeText(getApplicationContext(), "File is Downloading...", Toast.LENGTH_SHORT).show();
}
});
(which i added already for which I got error at "setDownloadListener", "DownloadListener", "DownloadManager" and so on. almost all words in that piece.)
SCREENSHOT :
Any help is greatly appreciated.
However, I try only when my app has a launcher property will the activity detect the NFC intent. Even if I have a intent filter in another application. Here is my manifest and both the activities. I even have foreground dispatch managed.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.melin.vustudentattendence">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.NFC" />
<uses-feature
android:name="android.hardware.nfc"
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">
<activity android:name=".AddStudentsActivity"></activity>
<activity android:name=".AddClassesActivity" />
<activity android:name=".AddTeachersActivity" />
<activity android:name=".TestActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED" />
</intent-filter>
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="#xml/nfc_tech_filter" />
</activity>
<activity android:name=".ClassAttendenceActivity">
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED" />
</intent-filter>
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="#xml/nfc_tech_filter" />
</activity>
<activity
android:name=".LecutererClassesListActivity"
android:theme="#style/AppTheme.NoActionBar" />
<activity android:name=".InstituteDashboardActivity" />
<activity android:name=".TodaysClassesActivity" />
<activity
android:name=".LecturerDashboardActivity"
android:theme="#style/AppTheme.NoActionBar" />
<activity
android:name=".LoginActivity"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
This is my TestActivity.java
package com.melin.vustudentattendence;
import androidx.appcompat.app.AppCompatActivity;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.ClipDescription;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.Ndef;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
public class TestActivity extends AppCompatActivity {
public static final String TAG="NFCDemo";
private TextView mTextView;
private NfcAdapter mNfcAdapter;
public class NdefReaderTask extends AsyncTask<Tag,Void,String> {
#Override
protected String doInBackground(Tag... params) {
Tag tag = params[0];
Ndef ndef = Ndef.get(tag);
if (ndef == null) {
// NDEF is not supported by this Tag.
return null;
}
NdefMessage ndefMessage = ndef.getCachedNdefMessage();
NdefRecord[] records = ndefMessage.getRecords();
for (NdefRecord ndefRecord : records) {
if (ndefRecord.getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_TEXT)) {
try {
return readText(ndefRecord);
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "Unsupported Encoding", e);
}
}
}
return null;
}
private String readText(NdefRecord record) throws UnsupportedEncodingException {
/*
* See NFC forum specification for "Text Record Type Definition" at 3.2.1
*
* http://www.nfc-forum.org/specs/
*
* bit_7 defines encoding
* bit_6 reserved for future use, must be 0
* bit_5..0 length of IANA language code
*/
byte[] payload = record.getPayload();
// Get the Text Encoding
String textEncoding = ((payload[0] & 128) == 0) ? "UTF-8" : "UTF-16";
// Get the Language Code
int languageCodeLength = payload[0] & 0063;
// String languageCode = new String(payload, 1, languageCodeLength, "US-ASCII");
// e.g. "en"
// Get the Text
return new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncoding);
}
#Override
protected void onPostExecute(String result) {
if (result != null) {
mTextView.setText("Read content: " + result);
}
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
mTextView=(TextView)findViewById(R.id.textView_explanation);
mNfcAdapter= NfcAdapter.getDefaultAdapter(this);
if(mNfcAdapter==null){
Toast.makeText(this,"This device doesn't support NFC",Toast.LENGTH_LONG).show();
finish();
return;
}
if(!mNfcAdapter.isEnabled()){
mTextView.setText("Nfc is disabled");
}else{
mTextView.setText(R.string.explanation);
}
handleIntent(getIntent());
}
#Override
protected void onResume() {
super.onResume();
setupForegroundDispatch(this, mNfcAdapter);
}
#Override
protected void onPause() {
stopForegroundDispatch(this,mNfcAdapter);
super.onPause();
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
handleIntent(intent);
}
public static void setupForegroundDispatch(final Activity activity, NfcAdapter adapter) {
final Intent intent = new Intent(activity.getApplicationContext(), activity.getClass());
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
final PendingIntent pendingIntent = PendingIntent.getActivity(activity.getApplicationContext(), 0, intent, 0);
IntentFilter[] filters = new IntentFilter[1];
String[][] techList = new String[][]{};
// Notice that this is the same filter as in our manifest.
filters[0] = new IntentFilter();
filters[0].addAction(NfcAdapter.ACTION_NDEF_DISCOVERED);
filters[0].addCategory(Intent.CATEGORY_DEFAULT);
try {
filters[0].addDataType(ClipDescription.MIMETYPE_TEXT_PLAIN);
} catch (IntentFilter.MalformedMimeTypeException e) {
throw new RuntimeException("Check your mime type.");
}
adapter.enableForegroundDispatch(activity, pendingIntent, filters, techList);
}
public static void stopForegroundDispatch(final Activity activity, NfcAdapter adapter) {
adapter.disableForegroundDispatch(activity);
}
private void handleIntent(Intent intent){
String action = intent.getAction();
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
String type = intent.getType();
if (ClipDescription.MIMETYPE_TEXT_PLAIN.equals(type)) {
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
new NdefReaderTask().execute(tag);
} else {
Log.d(TAG, "Wrong mime type: " + type);
}
} else if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) {
// In case we would still use the Tech Discovered Intent
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
String[] techList = tag.getTechList();
String searchedTech = Ndef.class.getName();
for (String tech : techList) {
if (searchedTech.equals(tech)) {
new NdefReaderTask().execute(tag);
break;
}
}
}
}
}
and this is my ClassesAttendenceActivity
package com.melin.vustudentattendence;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.ClipDescription;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.Ndef;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.QueryDocumentSnapshot;
import com.google.firebase.firestore.QuerySnapshot;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
public class ClassAttendenceActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private ClassAttendenceRowAdapter adapter;
private List<Student> students=new ArrayList<>();
private FirebaseFirestore fs;
private String incomingIntentData;
private NfcAdapter mNfcAdapter;
private static String TAG="Attendence Activity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_class_attendence);
//check nfc first
mNfcAdapter=NfcAdapter.getDefaultAdapter(this);
if(mNfcAdapter==null){
Toast.makeText(this,"This device doesn't support NFC",Toast.LENGTH_LONG).show();
finish();
return;
}
if(!mNfcAdapter.isEnabled()){
Toast.makeText(this,"NFC is disabled.Please enable it",Toast.LENGTH_LONG).show();
}else{
Toast.makeText(this, "NFC is in reader mode", Toast.LENGTH_SHORT).show();
}
//incomingIntentData=getIntent().getExtras().getString("document");
//fs=FirebaseFirestore.getInstance();
//Toast.makeText(this,incomingIntentData,Toast.LENGTH_LONG).show();
//recyclerView=(RecyclerView)findViewById(R.id.attendenceListRecyclerView);
// LinearLayoutManager layoutManager=new LinearLayoutManager(ClassAttendenceActivity.this);
// recyclerView.setLayoutManager(layoutManager);
// populateStudentList(incomingIntentData);
handleIntent(getIntent());
}
private void populateStudentList(String url){
fs.collection(url+"/students")
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
Map<String,Object> data=document.getData();
Student student=new Student();
student.setStatus("ABSENT");
for (Map.Entry<String,Object> entry : data.entrySet()){
if(entry.getKey().equals("name")){
student.setName(entry.getValue().toString());
}
if(entry.getKey().equals("student_id")){
student.setStudent_id(entry.getValue().toString());
}
}
students.add(student);
Log.d("List", document.getId() + " => " + document.getData());
}
} else {
Log.d("List", "Error getting documents: ", task.getException());
}
adapter=new ClassAttendenceRowAdapter(students);
recyclerView.setAdapter(adapter);
}
});
}
public void simulatingAnIntent(){
String student_id="101";
for(Student student:students){
if(student.getStudent_id().equals(student_id)){
student.setStatus("PRESENT");
Toast.makeText(ClassAttendenceActivity.this,"Student ID"+student.getStudent_id()+"Detected",Toast.LENGTH_LONG).show();
}
}
adapter=new ClassAttendenceRowAdapter(students);
recyclerView.setAdapter(adapter);
}
#Override
protected void onResume() {
super.onResume();
setupForegroundDispatch(this, mNfcAdapter);
}
#Override
protected void onPause() {
stopForegroundDispatch(this,mNfcAdapter);
super.onPause();
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
handleIntent(intent);
}
public static void setupForegroundDispatch(final Activity activity, NfcAdapter adapter) {
final Intent intent = new Intent(activity.getApplicationContext(), activity.getClass());
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
final PendingIntent pendingIntent = PendingIntent.getActivity(activity.getApplicationContext(), 0, intent, 0);
IntentFilter[] filters = new IntentFilter[1];
String[][] techList = new String[][]{};
// Notice that this is the same filter as in our manifest.
filters[0] = new IntentFilter();
filters[0].addAction(NfcAdapter.ACTION_NDEF_DISCOVERED);
filters[0].addCategory(Intent.CATEGORY_DEFAULT);
try {
filters[0].addDataType(ClipDescription.MIMETYPE_TEXT_PLAIN);
} catch (IntentFilter.MalformedMimeTypeException e) {
throw new RuntimeException("Check your mime type.");
}
adapter.enableForegroundDispatch(activity, pendingIntent, filters, techList);
}
public static void stopForegroundDispatch(final Activity activity, NfcAdapter adapter) {
adapter.disableForegroundDispatch(activity);
}
private void handleIntent(Intent intent){
String action = intent.getAction();
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
String type = intent.getType();
if (ClipDescription.MIMETYPE_TEXT_PLAIN.equals(type)) {
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
new NdefReaderTask().execute(tag);
} else {
Log.d(TAG, "Wrong mime type: " + type);
}
} else if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) {
// In case we would still use the Tech Discovered Intent
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
String[] techList = tag.getTechList();
String searchedTech = Ndef.class.getName();
for (String tech : techList) {
if (searchedTech.equals(tech)) {
new NdefReaderTask().execute(tag);
break;
}
}
}
}
public class NdefReaderTask extends AsyncTask<Tag,Void,String> {
#Override
protected String doInBackground(Tag... params) {
Tag tag = params[0];
Ndef ndef = Ndef.get(tag);
if (ndef == null) {
// NDEF is not supported by this Tag.
return null;
}
NdefMessage ndefMessage = ndef.getCachedNdefMessage();
NdefRecord[] records = ndefMessage.getRecords();
for (NdefRecord ndefRecord : records) {
if (ndefRecord.getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_TEXT)) {
try {
return readText(ndefRecord);
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "Unsupported Encoding", e);
}
}
}
return null;
}
private String readText(NdefRecord record) throws UnsupportedEncodingException {
/*
* See NFC forum specification for "Text Record Type Definition" at 3.2.1
*
* http://www.nfc-forum.org/specs/
*
* bit_7 defines encoding
* bit_6 reserved for future use, must be 0
* bit_5..0 length of IANA language code
*/
byte[] payload = record.getPayload();
// Get the Text Encoding
String textEncoding = ((payload[0] & 128) == 0) ? "UTF-8" : "UTF-16";
// Get the Language Code
int languageCodeLength = payload[0] & 0063;
// String languageCode = new String(payload, 1, languageCodeLength, "US-ASCII");
// e.g. "en"
// Get the Text
return new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncoding);
}
#Override
protected void onPostExecute(String result) {
if (result != null) {
Toast.makeText(ClassAttendenceActivity.this,"Student ID"+result+"Detected",Toast.LENGTH_LONG).show();
// for(Student student:students){
// if(student.getStudent_id().equals(result)){
// student.setStatus("PRESENT");
// Toast.makeText(ClassAttendenceActivity.this,"Student ID"+student.getStudent_id()+"Detected",Toast.LENGTH_LONG).show();
// }
// }
//
// adapter=new ClassAttendenceRowAdapter(students);
// recyclerView.setAdapter(adapter);
}
}
}
}
As you can see both the activities are almost identical
while one reads the data another doesn't
It turns out that using emulated nfc tag was the error.Using real nfc tag worked well.Though no one answered the question I am answering my own question so that when someone encounters this problem they can see this answer.Thank you.
I searched the web for examples displaying pdf documents within a app. Additionally i searched for a Downloader class because i want to load the pdf from the internet. After execution it just displays blank PDF page.
MainActivity.java just sends the pdf link to the DisplayPDF.java Activity:
package com.example.pdfviewevaluation;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
public final static String EXTRA_MESSAGE = "com.example.pdfviewevaluation.MESSAGE";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, DisplayPDF.class);
String url = "pdf link";
intent.putExtra(EXTRA_MESSAGE, url);
startActivity(intent);
}
}
DisplayPDF.java creates the Folder and PDF in the cache directory. Then it starts the Downloader with the pdf link and directory. Finally it should just show the pdf:
package com.example.pdfviewevaluation;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.ExecutionException;
public class DisplayPDF extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_pdf);
String pdfURL = getIntent().getStringExtra(MainActivity.EXTRA_MESSAGE);
File folder = new File(this.getCacheDir(), "pdf");
folder.mkdir();
File file = new File(folder, "Read.pdf");
try {
file.createNewFile();
} catch (IOException e1) {
e1.printStackTrace();
}
Downloader dl = new Downloader(pdfURL, file);
try {
dl.execute().get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
showPdf();
}
public void showPdf() {
File file = new File(this.getCacheDir()+"/pdf/Read.pdf");
PackageManager packageManager = getPackageManager();
Intent testIntent = new Intent(Intent.ACTION_VIEW);
testIntent.setType("application/pdf");
List list = packageManager.queryIntentActivities(testIntent, PackageManager.MATCH_DEFAULT_ONLY);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
Uri uri = FileProvider.getUriForFile(this.getApplicationContext(), this.getApplicationContext().getPackageName() + ".provider", file);
intent.setDataAndType(uri, "application/pdf");
startActivity(intent);
}
}
Downloader.java connects to the pdf page and download the pdf from the given link to the desired directory:
package com.example.pdfviewevaluation;
import android.os.AsyncTask;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Downloader extends AsyncTask<Void,Void,Void> {
private String fileURL;
private File directory;
public Downloader(String fileURL, File directory)
{
this.fileURL = fileURL;
this.directory = directory;
}
protected Void doInBackground(Void... params) {
try {
FileOutputStream f = new FileOutputStream(directory);
URL u = new URL(fileURL);
HttpURLConnection c = (HttpURLConnection) u.openConnection();
c.setRequestMethod("GET");
c.setDoOutput(true);
c.connect();
InputStream in = c.getInputStream();
byte[] buffer = new byte[1024];
int len1 = 0;
int i = 0;
while ((len1 = in.read(buffer)) > 0) {
f.write(buffer, 0, len1);
}
f.close();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
After many hours spending on my problem i searched for another solution on YouTube. These one are showing the solution:
https://www.youtube.com/watch?v=pGlqHeB5hdk
https://www.youtube.com/watch?v=8YPJCOxiklQ
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.downloadingfiles">
<uses-sdk android:minSdkVersion="21"
android:targetSdkVersion="22" />
<uses-permission android:name="android.permission.INTERNET"/>
<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">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
MainActivity.java:
import android.app.DownloadManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.pdf.PdfRenderer;
import android.net.Uri;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.webkit.MimeTypeMap;
import android.webkit.URLUtil;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.File;
public class MainActivity extends AppCompatActivity {
String myUrl = "http://www.orimi.com/pdf-test.pdf";
private ImageView imageView;
private int currentPage = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(myUrl));
request.setTitle("File download.");
request.setDescription("File is being downloaded...");
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
String nameOfFile = URLUtil.guessFileName(myUrl, null, MimeTypeMap.getFileExtensionFromUrl(myUrl));
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, nameOfFile);
DownloadManager manager = (DownloadManager) this.getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);
}
BroadcastReceiver onComplete=new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
render();
}
};
/**Called when the user clicks the "Next" button defined in activity_main.xml */
public void nextPage(View view) {
currentPage++;
render();
}
/**Called when the user clicks the "Previous" button defined in activity_main.xml */
public void previousPage(View view) {
currentPage--;
render();
}
private void render(){
try{
imageView = (ImageView) findViewById(R.id.image);
int REQ_WIDTH = imageView.getWidth();
int REQ_HEIGHT = imageView.getHeight();
Bitmap bitmap = Bitmap.createBitmap(REQ_WIDTH, REQ_HEIGHT, Bitmap.Config.ARGB_4444);
String nameOfFile = URLUtil.guessFileName(myUrl, null, MimeTypeMap.getFileExtensionFromUrl(myUrl));
File file = new File("/sdcard/Download/"+nameOfFile);
PdfRenderer renderer = new PdfRenderer(ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY));
if(currentPage < 0){
currentPage = 0;
}else if(currentPage >= renderer.getPageCount()){
currentPage = renderer.getPageCount() - 1;
}
Matrix m = imageView.getImageMatrix();
Rect rect = new Rect(0, 0, REQ_WIDTH, REQ_HEIGHT);
renderer.openPage(currentPage).render(bitmap, rect, m, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
imageView.setImageMatrix(m);
imageView.setImageBitmap(bitmap);
imageView.invalidate();
} catch (Exception e){
e.printStackTrace();
}
}
}
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" />