I know a library called libaums and had implemented it, but I don't know how to open Images and Videos using their library.
According to https://github.com/magnusja/libaums, you can actually read a file from the storage using this:
// read from a file
InputStream is = new UsbFileInputStream(file);
byte[] buffer = new byte[currentFs.getChunkSize()];
is.read(buffer);
Then your buffer contains the image data, so you can convert it to e.g. a Bitmap, like this:
Bitmap bmp = BitmapFactory.decodeByteArray(buffer , 0, buffer .length);
After that you can set it to an ImageView or whatever to show it to your user.
To be short, find your File and implement this logic.
Related
Is there a way to resize a JPEG image file (from filesystem to filesystem) without removing meta data (just like ImageMagicks convert in.jpg -resize 50% out.jpg)?
The only way I found to resize .jpg files I found is BitmapFactory.decodeStream and Bitmap.compress, which looks like a lot of overhead if I manually need to transfer image meta data.
It may be possible to read the metadata with android.media.ExifInterface, compress the image via Bitmap.compress and then save the metadata back:
String filename = "yourfile.jpg";
// this reads all meta data
ExifInterface exif = new ExifInterface(filename);
// read and compress file
Bitmap bitmap = BitmapFactory.decodeFile(filename);
FileOutputStream fos = new FileOutputStream(filename);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);
fos.close();
// write meta data back
exif.saveAttributes();
I didn't test it, but looking at the source code of ExifInterface, it may work.
If you don't want to rely on the implementation details, you could of course loop through all attributes and copy them.
Another solution would be to use the Android Exif Extended library. It is a small project to read and write exif data.
I wrote an android application that part of it is to handle upload and download documents. Currently I am using the Microsoft Azure server to save the files on.
The way I am currently doing it is by turning the files to a string and saving it that way on the Azure server:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
FileInputStream fis;
try {
fis = new FileInputStream(new File(Uridata.getPath()));
byte[] buf = new byte[1024];
int n;
while (-1 != (n = fis.read(buf)))
baos.write(buf, 0, n);
} catch (Exception e) {
e.printStackTrace();
}
byte[] bbytes = baos.toByteArray();
item.setStringFile(Base64.encodeToString(bbytes, Base64.URL_SAFE));
item.setName(Uridata.getLastPathSegment());
where item is my class that saves the string representation and the name of the file and is being loaded to the Azure, Uridata is an Uri instance of the file chosen.
I have one main problem with this solution and it is the limit on the file size.
I am searching for a good server to use instead of the Azure (maybe a RESET one) and if there is a better way to save files of all kinds (pdf, word...).
I will also want in the future to use the same data in a web interface
Does anybody have any suggestions on how to do it?
Thanks in advance!
To start, you don't have to transform the file into a string, you can just save it as a file. You have the possibility of losing data by continuing to do that. See: How do I save a stream to a file in C#?
If you're looking for another service to save files, then you should look into Azure Blob Storage. It will allow you to upload as much data as you want to a storage service for arbitrary files. See for example:
https://azure.microsoft.com/en-us/documentation/articles/storage-dotnet-how-to-use-blobs/
With the Google Photos app, I am trying to pick a video, that is not cached on the device.
I am using the ACTION_GET_CONTENT intent, to launch the options dialog, and from there I choose the Google Photos app.
While selecting local videos, it returns an Uri in this form.
content://media/external/video/media/6708
And from that, I query the content provider to retrieve the actual file location, and proceed from there. The file location looks like this.
/storage/emulated/0/WhatsApp/Media/WhatsApp
Video/VID-20131102-WA0000.mp4
Now, when I choose an online video, i.e: a video not available on my device yet, and which needs to be downloaded to be used, the returned Uri looks like this:
content://com.google.android.apps.photos.content/1/https://lh6.googleusercontent.com/_RD-QTO_SK5jlaPldTe2n5GANqMc3h-ukcbNoFlF1NLy=s0-d
Now, with this, there is no documented ContentProvider that would help me to get the actual link to this video. Even if I do a query, it returns nothing apart from a DISPLAY_NAME and SIZE columns.
DISPLAY_NAME contains video.mpeg (Same display name for different videos)
SIZE probably tells me the size of the actual file.
Referred to this post on SO.
I checked various posts, and thought that I would have to get an InputStream for the video through the content provider, save the file, and work with the file. Picking an image file however works fine, but with video it doesn't.
So, to copy the stream to a file, I have this code.
InputStream inputStream = context.getContentResolver().openInputStream(Uri.parse(path));
And finally write to a temporary file. The file gets created, but that doesn't seem to be correctly formatted. VLC plays the file, but shows only the first frame all throughout.
If I take the URL from the last part of the URI given above, and try to view it on a browser, it downloads a GIF file. I am guessing that's the problem. But I don't know how to get the mpeg format of the video.
Anyone has experienced the same?
Finally found the solution to the problem. This would work for both images and videos.
Referenced this video:
DevBytes: Android 4.4 Storage Access Framework: Client
https://www.youtube.com/watch?v=UFj9AEz0DHQ
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
startActivity(intent);
Get the Uri, and access and save the file like this:
ParcelFileDescriptor parcelFileDescriptor = context.getContentResolver()
.openFileDescriptor(Uri.parse(path),"r");
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
InputStream inputStream = new FileInputStream(fileDescriptor);
BufferedInputStream reader = new BufferedInputStream(inputStream);
// Create an output stream to a file that you want to save to
BufferedOutputStream outStream = new BufferedOutputStream(
new FileOutputStream(filePath));
byte[] buf = new byte[2048];
int len;
while ((len = reader.read(buf)) > 0) {
outStream.write(buf, 0, len);
}
For some reason, getting an input stream without using a ParcelFileDescriptor doesn't work.
I want to download PDF's and images into my app, essentially it will call a JSON web service that returns the link to the PDF, link to the image, and the title. It will download the image and PDF and save them. Then it will display the PDF's and images with the title. My only question is how do I deal with images? They cant be saved to APK since it is locked. The images are high enough resolution that they can scaled down to fit all the other densities, should I just use the large image, and let the activity scale it down when it uses it. Or should I implement an image scaler during the retrieval process?
Eventually the PDF's and images would be loaded into the APK. How would I check the assets folder to remove the images, would I just need to call a service that runs when the Application First starts to check for the files in the assets folder then remove them if they are present?
Sample code for your reference where u can download Images from the web.Its better to store Images in asset folder than Internal Memory and resize the images for good performance.U can delete the folder before making web service call and load new set images.
if (Utility.isWifiPresent()
|| Utility.isMobileConnectionPresent()) {
URL url = new URL(fileUrl);
InputStream iStream = url.openConnection().getInputStream();// .read(data)
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
byte[] tmpArray = new byte[1024];
int nRead;
while ((nRead = iStream.read(tmpArray, 0, tmpArray.length)) != -1) {
buffer.write(tmpArray, 0, nRead);
}
buffer.flush();
data = buffer.toByteArray();
FileOutputStream fOut = null;
//path to store
fOut = Utility.getFileOutputStreamForCloud(
sdcardFolderPath, fileUrl);
}
fOut.write(data);
fOut.flush();
fOut.close();
My application allows users to take a photo using the camera and save it as their profile picture. There can be only 1 image stored at a time?
Is it a bad idea to use SharedPrefertences for this purpose although I am only storing 1 image? (Converting image to Base64). What are the cons?
If storing the image using shared preferences is not a good idea, what are the alternatives?
I think storing binary data in SharedPreferences is not a good idea. Instead save it to the filesystem. Example for that, if the data is coming from an InputStream:
storeImage( new File(context.getFilesDir().getAbsolutePath() + fileDir),
is,
"profile.png" );
public static void storeImage(
File fileDir,
InputStream inputStream,
String fileName ) throws IOException {
File file = new File( fileDir,fileName );
FileOutputStream fos = new FileOutputStream( file );
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
inputStream.close();
fos.close();
bitmap.recycle();
bitmap = null;
}
Where context can be the Application/Activity context.
There is no reason why you can't use SharedPreferences to store a single image as a Base64 String, Of course this isn't really a scalable approach as when the SharedPreferences are loaded, every image would be loaded into memory at once, but that's not what your looking for.
The other possible approaches you can take is to store the images either using the internal or external storage APIs or to store them in a database
In general for this kind of thing you should be looking to use something other than shared preferences, however in this case, I can't see there been an actual issue to the approach your suggesting.