Android N FileUriExposedException - camera

Guys My app uses the stock camera to take a picture I use the following code to take a picture
public void takepic(View view) {
TextView schtitle = (TextView) findViewById(R.id.Sitename);
String schname = schtitle.getText().toString();
String[] tokens = schname.split(" ");
String timeStamp = new SimpleDateFormat("dd-MM-yyyy-HH-mm-ss").format(new Date());
String imageFileName = tokens[0] + "-" + timeStamp + ".jpg";
TextView myAwesomeTextView = (TextView)findViewById(R.id.filetext);
//in your OnCreate() method
myAwesomeTextView.setText(imageFileName);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
String name = imageFileName;
File file = new File(path, name );
outputFileUri = Uri.fromFile(file);
intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(intent, TAKE_PICTURE);
}
This works fine in all but Nougat
I understand as they did in marshmallow you now need permissions and cant use file URI anymore
I cant find any sample code on how to take a picture in nougat could someone please point me in the right direction as to how I modify my code to allow this to happen?
Any help appreciated
Mark

The problem is the file:// uri is not permited anymore.
Instead of this you must use FileProvider.
Take a look here: https://inthecheesefactory.com/blog/how-to-share-access-to-file-with-fileprovider-on-android-nougat/en

Just quoting this here for reference.
We now have an updated documentation on how to use camera intent with a file uri to store the taken picture under the training section of android.
https://developer.android.com/training/camera/photobasics.html

public void openShare(View view) {
// save bitmap to cache directory
try {
bitmap = ((BitmapDrawable) iv.getDrawable()).getBitmap();
File cachePath = new File(getCacheDir(), "images");
if (!cachePath.exists())
cachePath.mkdirs();
FileOutputStream stream = new FileOutputStream(cachePath + "/" + imageName);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
stream.close();
shareImage();
} catch (Exception e) {
e.printStackTrace();
}
}
private void shareImage() {
File imagePath = new File(getCacheDir(), "images");
File newFile = new File(imagePath, imageName);
Uri contentUri = MyFileProvider.getUriForFile(this, "com.example.kushaalsingla.contentsharingdemo", newFile);
if (contentUri != null) {
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // temp permission for receiving app to read this file
shareIntent.setDataAndType(contentUri, getContentResolver().getType(contentUri));
shareIntent.putExtra(Intent.EXTRA_STREAM, contentUri);
startActivity(Intent.createChooser(shareIntent, "Choose an app"));
}
}
################## Add in Manifest
<provider
android:name=".MyFileProvider"
android:authorities="com.example.kushaalsingla.contentsharingdemo"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/filepaths" />
</provider>
################## filepaths.xml ########################
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<cache-path name="shared_images" path="images/"/>
</paths>

Related

ImageView.setImageBitmap(bla) function is not working on Android One Nougat 7.1.1

i have an app which takes photo then shows that on imageView, but the problem is on Android one or 7.1.1 Nougat phones do not shows the image on the screen, the other phones are working perfectly.(It works on Samsung S7 Edge Nougat 7.0.0 and also Nexus 5X Marshmallow 6.0.0 perfect.) Note : It is not crashes on 7.1.1, just doesn't shows and image on the screen.
Code sample after taking a photo :
if (requestCode == REQUEST_TAKE_PHOTO && resultCode == RESULT_OK) {
// Show the thumbnail on ImageView
Uri imageUri = Uri.parse(mCurrentPhotoPath);
File file = new File(imageUri.getPath());
try {
InputStream ims = new FileInputStream(file);
binding.ivPhoto.setImageBitmap(BitmapFactory.decodeStream(ims));
} catch (FileNotFoundException e) {
return;
}
}
I found the problem, the problem is that when I am trying to save file to directory it could not find a directory in External drive, the solution is, if you have no such a directory you need to create new one.
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String path = Environment.getExternalStorageDirectory() + "/" + "AdoptPet/";
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = new File(Environment.getExternalStoragePublicDirectory(
path), "Camera");
if (!storageDir.exists()) {
storageDir.mkdirs();
}
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = "file:" + image.getAbsolutePath();
return image;
}

inserting image into mongo from java result in a strange error

I have the following code for saving image in mongodb:
public static void insertImage() throws Exception {
String newFileName = "mkyong-java-image";
File imageFile = new File("c:\\JavaWebHosting.png");
GridFS gfsPhoto = new GridFS(db, "photo");
GridFSInputFile gfsFile = gfsPhoto.createFile(imageFile);
gfsFile.setFilename(newFileName);
gfsFile.save();
}
And I got this from this link:
link for code
But when I use that I get the following error and I do not know how to fix it ... Can anyone help?
Exception in thread "main" java.lang.NullPointerException
at com.mongodb.gridfs.GridFS.<init>(GridFS.java:97)
for more explanation the error is at exactly this line:
GridFS gfsPhoto = new GridFS(db, "photo");
Update:
Here is the code for creating db connection
public static DB getDBConnection() {
// If it's not connected to the database, make connection
if (db == null) {
initialize();
makeConnections();
}
return db;
}
private static void makeConnections() {
MongoCredential credential = MongoCredential.createMongoCRCredential(dbUser, dbName, dbPass.toCharArray());
MongoClient mongoClient;
try {
mongoClient = new MongoClient(new ServerAddress(dbHost, Integer.parseInt(dbPort)), Arrays.asList(credential));
db = mongoClient.getDB(dbName);
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
Update:
String newFileName = "mkyong-java-image";
File imageFile = new File("D:/1.jpg");
db = MongoDB.getDBConnection();
collection = db.getCollection("test");
// create a "photo" namespace
GridFS gfsPhoto = new GridFS(db, "photo");
// get image file from local drive
GridFSInputFile gfsFile = gfsPhoto.createFile(imageFile);
// set a new filename for identify purpose
gfsFile.setFilename(newFileName);
// save the image file into mongoDB
gfsFile.save();
// print the result
DBCursor cursor = gfsPhoto.getFileList();
while (cursor.hasNext()) {
System.out.println(cursor.next());
}
// get image file by it's filename
GridFSDBFile imageForOutput = gfsPhoto.findOne(newFileName);
// save it into a new image file
imageForOutput.writeTo("D:\\JavaWebHostingNew.jpg");
// remove the image file from mongoDB
// gfsPhoto.remove(gfsPhoto.findOne(newFileName));
System.out.println("Done");

Wicket : FileUploadPage doesnt refresh the filepath

again, i got a problem with wicket. Im trying to upload data with my Class "FileUploadPanel", which is implemented on another Page "Class A":
Class A
...
/* uploadfields for Picture and Video */
ArrayList<String> picExt = new ArrayList<String>();
ArrayList<String> videoExt = new ArrayList<String>();
picExt.add("jpg");
videoExt.add("mp4");
final FileUploadPanel picUpload = new FileUploadPanel("picUpload", "C:\\", picExt);
final FileUploadPanel videoUpload = new FileUploadPanel("videoUpload", "C:\\", videoExt);
final Form form = new Form("form"){
protected void onSubmit() {
...
// Save the path of Video and Picture into Database
table.setVideo(videoUpload.getFilepath());
table.setPicture(picUpload.getFilepath());
...
}
...
Class FileUploadPanel
public class FileUploadPanel extends Panel {
private static final long serialVersionUID = -2059476447949908649L;
private FileUploadField fileUpload;
private String UPLOAD_FOLDER = "C:\\";
private String filepath = "";
private List<String> fileExtensions;
/**
* Constructor of this Class
* #param id the wicket-id
* #param uploadFolder the folder, in which the File will be uploaded
* #param fileExtensions List of Strings
*/
public FileUploadPanel(String id, String uploadFolder, List<String> fileExtensions) {
super(id);
this.UPLOAD_FOLDER = uploadFolder;
this.fileExtensions = fileExtensions;
add(fileUpload = new FileUploadField("fileUpload"));
}
#Override
public void onComponentTag(ComponentTag tag){
// If no file is selected on startup
if(fileUpload.getFileUpload() == null){
return;
}
final FileUpload uploadedFile = fileUpload.getFileUpload();
if (uploadedFile != null) {
// write to a new file,
File newFile = new File(UPLOAD_FOLDER
+ uploadedFile.getClientFileName());
filepath = UPLOAD_FOLDER + uploadedFile.getClientFileName();
// if file in upload-folder already exists -> delete it
if (newFile.exists()) {
newFile.delete();
}
try {
newFile.createNewFile();
uploadedFile.writeTo(newFile);
info("saved file: " + uploadedFile.getClientFileName());
} catch (Exception e) {
throw new IllegalStateException("Error");
}
}
}
public String getFilepath() {
return filepath;
}
}
Well, if i use the submit-Button on my "Class A", the Pic and Video get saved on C:\, which is quite good so far. I thought i finally get along with wicket, but i cheered too soon...
Problem: The correct path is not saved in the Database, which is handled in the Form of "Class A"
I really dont get it, because the onComponentTag(...) of my FileUploadPanel must be executed when using the submit-button. Thats because i added some validations like "picture must be a JPG or wont be saved" in onComponentTag(...) - and that worked. So im sure, the onComponentTag(...) is executed when the Submit-Button of the Form is used, which also means the filepath should be up-to-date.
What is it im doin wrong this time?
Thank in Advance!
Greeting
V1nc3nt
You are using
File newFile = new File(UPLOAD_FOLDER +
uploadedFile.getClientFileName());
this code to create a new File.
Instead of it you can try this one :
File file = new File(UPLOAD_FOLDER ,
uploadedFile.getClientFileName());
And then get the absolute path and save it:
newFile.getAbsolutePath();

com.sun.jersey.api.client.UniformInterfaceException (returned a response status of 400)

I am trying to set up file upload example using JAX RS. I could set up the project and successfully upload file in a server location. But i get the following error when file size is more than 10KB (weird!!)
com.sun.jersey.api.client.UniformInterfaceException: POST http://localhost:9090/DOAFileUploader/rest/file/upload returned a response status of 400
at com.sun.jersey.api.client.WebResource.handle(WebResource.java:607)
at com.sun.jersey.api.client.WebResource.access$200(WebResource.java:74)
at com.sun.jersey.api.client.WebResource$Builder.post(WebResource.java:507)
at com.sony.doa.rest.client.DOAClient.upload(DOAClient.java:75)
at com.sony.doa.rest.client.DOAMain.main(DOAMain.java:34)
I am new to JAX RS and i'm not sure what exactly the issue is. Do i need to set some parameters client side or server side (like size, timeout etc)?
This is the client side code calling webservice:
public void upload() {
File file = new File(inputFilePath);
FormDataMultiPart part = new FormDataMultiPart();
part.bodyPart(new FileDataBodyPart("file", file, MediaType.APPLICATION_OCTET_STREAM_TYPE));
WebResource resource = Client.create().resource(url);
String response = resource.type(MediaType.MULTIPART_FORM_DATA_TYPE).post(String.class, part);
System.out.println(response);
}
This is the server side code:
#Path("/file")
public class UploadFileService {
#POST
#Path("/upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(
#FormDataParam("file") InputStream uploadedInputStream,
#FormDataParam("file") FormDataContentDisposition fileDetail) {
String uploadedFileLocation = "e://uploaded/"
+ fileDetail.getFileName();
writeToFile(uploadedInputStream, uploadedFileLocation);
String output = "File uploaded to : " + uploadedFileLocation;
return Response.status(200).entity(output).build();
}
private void writeToFile(InputStream uploadedInputStream,
String uploadedFileLocation) {
try {
OutputStream out = new FileOutputStream(new File(
uploadedFileLocation));
int read = 0;
byte[] bytes = new byte[16000];
out = new FileOutputStream(new File(uploadedFileLocation));
while ((read = uploadedInputStream.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
} } }
Please let me know what settings i have to change for file sizes greater than 10KB?
Thanks!
I use org.apache.commons.fileupload.servlet.ServletFileUpload in a Jersey context, and it works fine., and yes, it set the max file size, sorry I missed this before.
here is a snipet of code I use (this is a multipart form, so there are other fields along with the file)
private LibraryUpload parseLibraryUpload(HttpServletRequest request) {
LibraryUpload libraryUpload;
File libraryZip = null;
String name = null;
String version = null;
ServletFileUpload upload = new ServletFileUpload();
upload.setFileSizeMax(MAX_FILE_SIZE);
FileItemIterator iter;
try {
iter = upload.getItemIterator(request);
while (iter.hasNext()) {
....
if (item.isFormField()) {
....
}else{
BufferedInputStream buffer = new BufferedInputStream(stream);
buffer.mark(MAX_FILE_SIZE);
libraryZip = File.createTempFile("fromUpload", null);
IOUtils.copy(buffer, new FileOutputStream(libraryZip));
...
}
I have encountered the same problem with Jersey. I have activated jersey trace but nothing help me.
I have changed the library by an apache Library and I see than the problem with linked to a repository for temporary files for tomcat. The repository was not exist. For files under 10k, the repository was not used.
So, after the repository creation, I used jersey library and all works fine.

How to make a screenshot from the Microsoft Surface emulator?

In order to write a user manual for my application, I need to take some screenshots from the Microsoft Surface emulator.
How can I do that? For sure I could just make a screenshot in my OS and then cut the image in a photo editor, but isn't there a simpler way?
So finally I found a nice way to do it:
class ScreenshotTaker
{
public static void TakeScreenshot(Visual target)
{
String fileName = "Screenshot-" + DateTime.UtcNow.ToString().Replace(" ", "-").Replace(".", "_").Replace(":", "_") + ".tiff";
Console.WriteLine("Try to take screenshot: " + fileName);
FileStream stream = new FileStream(fileName, FileMode.Create);
TiffBitmapEncoder encoder = new TiffBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(GetScreenShot(target)));
encoder.Save(stream);
stream.Flush();
stream.Close();
Console.WriteLine("Screenshot taken");
}
private static BitmapSource GetScreenShot(Visual target)
{
Rect bounds = VisualTreeHelper.GetDescendantBounds(target);
RenderTargetBitmap bitmap = new RenderTargetBitmap(1024, 768, 96, 96, PixelFormats.Pbgra32);
DrawingVisual drawingvisual = new DrawingVisual();
using (DrawingContext context = drawingvisual.RenderOpen())
{
context.DrawRectangle(new VisualBrush(target), null, new Rect(new Point(), bounds.Size));
context.Close();
}
bitmap.Render(drawingvisual);
return bitmap;
}
}