I need to randomly select an image from a user's photo gallery. I don't mean starting an intent as in
Intent gallery = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(gallery, GALLERY_PHOTO_REQUEST_CODE);
No. I need to randomly select the image myself. Is there an efficient way to do this? Or do I have to actually read in all the image files and then randomly select a file, and then from the file get the image? By read all files, I mean with something as (snippet: I have a question not an answer)
void addFiles(final File parent, Set<File> images) {
try {
for (final File file : parent.listFiles()) {
if (!file.getParent().contains("Android")) {
if (!file.isDirectory()) {
if (isImageFile(file.getName())) {
images.add(file);
}
} else {
addFiles(file, images);
}
}
}
} catch (Exception e) {
}
}
Please don't be too concerned with the code snippet. If I knew the best way, I would not be asking for help. Does anyone know an efficient way of doing this?
I don't know your code aside from the snippets. Unless you have a large number of files, you could very well read all the files into an array. Then generate a random number with 0 as lowest and arrayList.size()-1 as highest and get that index from the array.
Pseudo code:
private static Random random = new Random();
ArrayList<File> list = readFiles();
File randomFile = list.get(getRandomValue(0, list.size()-1));
...
public static int getRandomValue(int low, int high) {
return random.nextInt((high - low) + 1) + low;
}
Related
In android, I need to load a set of images from res/drawable directory
I use the following code:
Field[] fields = R.drawable.class.getFields();
List<Picture> pictures = new ArrayList<>();
for (Field field : fields) {
String name = field.getName();
if (name.startsWith("img")) {
Picture picture = new Picture(name);
pictures.add(picture);
}
}
Among all files in 'drawable', it finds all files starting as a string 'img'.
For this code to work correctly, I have to manually change the names of image files by myself.
If I can get the extension of each resource in drawable (such as jpg, png, etc.), I don't need to change the file name like this.
Is there any way to achieve this?
I appreciate your help, thanks :D
I answer my question.
I moved all the image files into "asset/imgs"
and use the following code to load them
List<Picture> pictures = new ArrayList<>();
try {
String[] images = assetManager.list("imgs");
for (String name : images) {
Picture picture = new Picture(name);
pictures.add(picture);
}
} catch (IOException e) {
// you can print error or log.
throw new RuntimeException(e);
}
I want to delete image from gallery that was most recently captured. I have followed a couple of SO questions, but nothing seems to work. Can anyone give me a simple code that works?
Sample code:
public void deleteImage() {
File f = new File("/storage/emulated/0/Pictures");
File [] files = f.listFiles();
Arrays.sort(files, new Comparator<File>() {
#Override
public int compare(File a, File b) {
if (a.lastModified() < b.lastModified())
return 1;
if (a.lastModified() > b.lastModified())
return -1;
return 0;
}
});
files[0].delete();
}
This code sorts the files in gallery folder by time of last modification, and delete the most recent file.
I'm creating an image filter app in Android studio. first, the user selects an image from gallery and it will be displayed in imageview. Then the user clicks edit button and that image is displayed in imageview of next activity where we can add filters... It works fine with low resolution images but when I select any high resolution image it is shown in first imageview but when I click edit button either the app crashes or the last image I had selected is displayed.I searched for the solution but couldn't find it. If anyone knows how to solve this problem please help me
There is a limit to the size of data that can be passed through an intent. The limit is roughly 500Kb - your high resolution photographs will be larger than this.
Consider saving your image to a file location on the device, passing the URI to the receiving activity and loading it within there.
first paste crash logs.
then instead of passing image itself just pass image path.
or simply add the edit tools and mainView in one activity and make edit tools invisible! however you can use fragment too.
use with putExtra to send the Uri Path:
Intent intent = new Intent(Intent.ACTION_VIEW);
intent .setClass(ThisActivity.this, NewActivity.class);
intent .putExtra("KEY", Uri);
startActivity(intent );
You just need to add path of image.
It's better to save the image in storage and pass the Uri of location instead of passing the image.
Save image in storage:-
public static Uri saveImageOnExternalStorage(Bitmap capturedBitmap, String imageId) {
if (null != capturedBitmap ) {
OutputStream fOutputStream;
String path = Environment.getExternalStorageDirectory().toString();
File file = new File(path + "temp", mediaId + ".png");
file.delete();
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
try {
if (file.createNewFile()) {
fOutputStream = new FileOutputStream(file);
capturedBitmap.compress(COMPRESS_FORMAT, 100, fOutputStream);
fOutputStream.flush();
fOutputStream.close();
return Uri.fromFile(file); // return saved image path on external storage
}
} catch (FileNotFoundException e) {
Log.e(TAG,e.getMessage());
return null;
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG,e.getMessage());
}
}
return null;
}
Now the same Uri you can pass in the intent of next activity:-
Intent intent = new Intent(CurrentActivity.this, LaunchActivity.class);
intent .putExtra("image_key", Uri);
startActivity(intent );
I am trying to load the thumbnails for videos in a file browser but its causing me to run out of memory.
public class Filea {
private Bitmap VideoIcon;
public Bitmap getVideoIcon() {
return VideoIcon;
}
public void setVideoIcon(Bitmap videoIcon) {
VideoIcon = videoIcon;
}
This is being done for every video file that is in a folder.
Every time that I load a new folder does it keep the information from the previous folder, and if so how do i get it to delete the unwanted resources?
private List<Filea> LoadFiles(String dirPath) {
inSearch = false;
List<Filea> files = new ArrayList<Filea>();
try {
for(String F:EditedFileList(current)) {
Filea file = new Filea();
file.setVideoIcon(ThumbnailUtils.createVideoThumbnail(current + "/" + getName(F), MediaStore.Images.Thumbnails.MINI_KIND));
files.add(file);
}
} catch (NullPointerException e) {
e.getStackTrace();
} catch (NoSuchElementException e) {
Log.i("LoadFiles", "No files found");
}
return files;
}
This is how the information is obtained.
Along with the video thumbnails I am loading other bits of data E.g. File name, size, permissions, Image icons(as bitmaps) ect..
Most likely you're keeping around a bunch of unneeded references. My suggestion would be to put the images in an LRUCache and load them from there. That way you can set a reasonable maximum amount of memory to use on images.
I found the problem, i was trying to load the full image of picture instead of the thumbnails.`
file.setImageIcon(ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(current + "/" + getName(F)), 100, 100));
Thank. LukeMovement.
I want to add an audio file to an image. So when someone gets that image he can extract the sound from it. I think we can add additional data to image header. But I don't know how to do that sort of header processing in Android. Can you please guide me...
Using the below code you can add a small comment to the JPEG header in Android. It's only for JPEG.
final static String EXIF_TAG = "UserComment";
public static boolean setComment(String imagePath, String comment) {
try {
ExifInterface exif = new ExifInterface(imagePath);
exif.setAttribute(EXIF_TAG, comment);
exif.saveAttributes();
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
But the problem is you can't put a audio file there because the data stream is way too big to fit in to the header.