Reputation: 8725
I'm trying to show images in the specific folder using default Android Gallery. I found only one sample code to do this. I have simplified that code and now it's much clear:
public class ScanActivity extends Activity implements MediaScannerConnectionClient {
private static final String SCAN_DIR = Environment.getExternalStorageDirectory() + File.separator + "MyFolder" + File.separator;
private static final String FILE_TYPE="image/*";
private String scanPath;
private MediaScannerConnection conn;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
scanPath = SCAN_DIR + new File(SCAN_DIR).list()[0];
conn = new MediaScannerConnection(getApplicationContext(), this);
conn.connect();
}
@Override
public void onMediaScannerConnected()
{
conn.scanFile(scanPath, FILE_TYPE);
}
@Override
public void onScanCompleted(String path, Uri uri)
{
try
{
if (uri != null)
{
//uri = content://media/external/images/media/11271
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uri, FILE_TYPE);
startActivity(intent);
}
}
finally
{
conn.disconnect();
conn = null;
}
}
}
On Android Froyo (2.2) it works OK - the gallery opens all images in MyFolder
directory, but on Jelly Bean (4.1) I see just black screen (see the screenshot below). Of course scanned folder contains photos on both devices.
The logcat output:
11-03 18:31:31.872: W/DataManager(12540): exception in creating media object: /local/image/item/11271
11-03 18:31:31.872: W/DataManager(12540): java.lang.RuntimeException: cannot find data for: /local/image/item/11271
11-03 18:31:31.872: W/DataManager(12540): at com.android.gallery3d.data.LocalImage.<init>(LocalImage.java:104)
11-03 18:31:31.872: W/DataManager(12540): at com.android.gallery3d.data.LocalSource.createMediaObject(LocalSource.java:106)
11-03 18:31:31.872: W/DataManager(12540): at com.android.gallery3d.data.DataManager.getMediaObject(DataManager.java:165)
11-03 18:31:31.872: W/DataManager(12540): at com.android.gallery3d.data.LocalSource.getDefaultSetOf(LocalSource.java:183)
11-03 18:31:31.872: W/DataManager(12540): at com.android.gallery3d.data.DataManager.getDefaultSetOf(DataManager.java:261)
11-03 18:31:31.872: W/DataManager(12540): at com.android.gallery3d.app.Gallery.startViewAction(Gallery.java:198)
11-03 18:31:31.872: W/DataManager(12540): at com.android.gallery3d.app.Gallery.initializeByIntent(Gallery.java:91)
11-03 18:31:31.872: W/DataManager(12540): at com.android.gallery3d.app.Gallery.onCreate(Gallery.java:68)
11-03 18:31:31.872: W/DataManager(12540): at android.app.Activity.performCreate(Activity.java:5008)
11-03 18:31:31.872: W/DataManager(12540): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
11-03 18:31:31.872: W/DataManager(12540): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2140)
11-03 18:31:31.872: W/DataManager(12540): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2211)
11-03 18:31:31.872: W/DataManager(12540): at android.app.ActivityThread.access$600(ActivityThread.java:143)
11-03 18:31:31.872: W/DataManager(12540): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1209)
11-03 18:31:31.872: W/DataManager(12540): at android.os.Handler.dispatchMessage(Handler.java:99)
11-03 18:31:31.872: W/DataManager(12540): at android.os.Looper.loop(Looper.java:137)
11-03 18:31:31.872: W/DataManager(12540): at android.app.ActivityThread.main(ActivityThread.java:4965)
11-03 18:31:31.872: W/DataManager(12540): at java.lang.reflect.Method.invokeNative(Native Method)
11-03 18:31:31.872: W/DataManager(12540): at java.lang.reflect.Method.invoke(Method.java:511)
11-03 18:31:31.872: W/DataManager(12540): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
11-03 18:31:31.872: W/DataManager(12540): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:558)
11-03 18:31:31.872: W/DataManager(12540): at dalvik.system.NativeStart.main(Native Method)
11-03 18:31:31.872: V/StateManager(12540): startState class com.android.gallery3d.app.PhotoPage
11-03 18:31:31.911: V/NFC(12540): this device does not have NFC support
11-03 18:31:32.044: W/DecodeService(12540): java.lang.NullPointerException
11-03 18:31:32.044: W/DecodeService(12540): at java.io.File.fixSlashes(File.java:185)
11-03 18:31:32.044: W/DecodeService(12540): at java.io.File.<init>(File.java:134)
11-03 18:31:32.044: W/DecodeService(12540): at java.io.FileInputStream.<init>(FileInputStream.java:105)
11-03 18:31:32.044: W/DecodeService(12540): at com.android.gallery3d.data.DecodeUtils.decodeThumbnail(DecodeUtils.java:92)
11-03 18:31:32.044: W/DecodeService(12540): at com.android.gallery3d.data.LocalImage$LocalImageRequest.onDecodeOriginal(LocalImage.java:188)
11-03 18:31:32.044: W/DecodeService(12540): at com.android.gallery3d.data.ImageCacheRequest.run(ImageCacheRequest.java:74)
11-03 18:31:32.044: W/DecodeService(12540): at com.android.gallery3d.data.LocalImage$LocalImageRequest.run(LocalImage.java:154)
11-03 18:31:32.044: W/DecodeService(12540): at com.android.gallery3d.data.ImageCacheRequest.run(ImageCacheRequest.java:28)
11-03 18:31:32.044: W/DecodeService(12540): at com.android.gallery3d.util.ThreadPool$Worker.run(ThreadPool.java:124)
11-03 18:31:32.044: W/DecodeService(12540): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
11-03 18:31:32.044: W/DecodeService(12540): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
11-03 18:31:32.044: W/DecodeService(12540): at java.lang.Thread.run(Thread.java:856)
11-03 18:31:32.044: W/DecodeService(12540): at com.android.gallery3d.util.PriorityThreadFactory$1.run(PriorityThreadFactory.java:43)
11-03 18:31:32.044: W/ImageCacheRequest(12540): decode orig failed /local/image/item/11271,THUMB
I googled and found no information about this exception.
I'm really confused about this problem and don't know how to fix it. Does anyone have idea how to fix it? Thanks.
Upvotes: 0
Views: 3689
Reputation: 11
Changing the below code for scanning all files in this folder. It works for me for JB.
public void onMediaScannerConnected()
{
for(File f : allFiles)
{
conn.scanFile(f.getAbsolutePath(), "image/*");
}
}
Upvotes: 1
Reputation: 7860
I came here looking for the same thing but by now I ended up designing my own custom gallery, maybe it helps someone out there:
public class ImageViewFlipper extends Activity {
private static final int EXIT = 0;
private static final int SWIPE_MIN_DISTANCE = 120;
private static final int SWIPE_MAX_OFF_PATH = 250;
private static final int SWIPE_THRESHOLD_VELOCITY = 200;
private static final String DIRECTORY = "/sdcard/edu";
private static final String DATA_DIRECTORY = "/sdcard/edu";
private static final String DATA_FILE = "/sdcard/imagelist.dat";
private GestureDetector gestureDetector;
View.OnTouchListener gestureListener;
private Animation slideLeftIn;
private Animation slideLeftOut;
private Animation slideRightIn;
private Animation slideRightOut;
private ViewFlipper viewFlipper;
private int currentView = 0;
List<String> ImageList;
private int currentIndex = 0;
private int maxIndex = 0;
FileOutputStream output = null;
OutputStreamWriter writer = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.main);
ImageView iv = (ImageView) findViewById(R.id.zero);
File data_directory = new File(DATA_DIRECTORY);
if (!data_directory.exists()) {
if (data_directory.mkdir()) {
FileUtils savedata = new FileUtils();
Toast toast = Toast.makeText(ImageViewFlipper.this,
"Please wait while we search your SD Card for images...", Toast.LENGTH_SHORT);
toast.show();
SystemClock.sleep(100);
ImageList = FindFiles();
savedata.saveArray(DATA_FILE, ImageList);
} else {
ImageList = FindFiles();
}
}
else {
File data_file= new File(DATA_FILE);
if (!data_file.exists()) {
FileUtils savedata = new FileUtils();
SystemClock.sleep(100);
ImageList = FindFiles();
savedata.saveArray(DATA_FILE, ImageList);
} else {
FileUtils readdata = new FileUtils();
ImageList = readdata.loadArray(DATA_FILE);
}
}
if (ImageList == null) {
quit();
}
SharedPreferences indexPrefs = getSharedPreferences("currentIndex",
MODE_PRIVATE);
if (indexPrefs.contains("currentIndex")) {
currentIndex = indexPrefs.getInt("currentIndex", 0);
}
maxIndex = ImageList.size() - 1;
Log.v("currentIndex", "Index: "+currentIndex);
viewFlipper = (ViewFlipper) findViewById(R.id.flipper);
slideLeftIn = AnimationUtils.loadAnimation(this, R.anim.slide_left_in);
slideLeftOut = AnimationUtils
.loadAnimation(this, R.anim.slide_left_out);
slideRightIn = AnimationUtils
.loadAnimation(this, R.anim.slide_right_in);
slideRightOut = AnimationUtils.loadAnimation(this,
R.anim.slide_right_out);
viewFlipper.setInAnimation(AnimationUtils.loadAnimation(this,
android.R.anim.fade_in));
viewFlipper.setOutAnimation(AnimationUtils.loadAnimation(this,
android.R.anim.fade_out));
iv.setImageDrawable(Drawable.createFromPath(ImageList
.get(currentIndex)));
System.gc();
gestureDetector = new GestureDetector(new MyGestureDetector());
gestureListener = new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (gestureDetector.onTouchEvent(event)) {
return true;
}
return false;
}
};
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
int NONE = Menu.NONE;
menu.add(NONE, EXIT, NONE, "Exit");
return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case EXIT:
quit();
break;
}
return super.onOptionsItemSelected(item);
}
protected void onPause() {
super.onPause();
SharedPreferences indexPrefs = getSharedPreferences("currentIndex",
MODE_PRIVATE);
SharedPreferences.Editor indexEditor = indexPrefs.edit();
indexEditor.putInt("currentIndex", currentIndex);
indexEditor.commit();
}
protected void onResume() {
super.onResume();
SharedPreferences indexPrefs = getSharedPreferences("currentIndex",
MODE_PRIVATE);
if (indexPrefs.contains("currentIndex")) {
currentIndex = indexPrefs.getInt("currentIndex", 0);
}
}
private List<String> FindFiles() {
final List<String> tFileList = new ArrayList<String>();
Resources resources = getResources();
// array of valid image file extensions
String[] imageTypes = resources.getStringArray(R.array.image);
FilenameFilter[] filter = new FilenameFilter[imageTypes.length];
int i = 0;
for (final String type : imageTypes) {
filter[i] = new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.endsWith("." + type);
}
};
i++;
}
FileUtils fileUtils = new FileUtils();
File[] allMatchingFiles = fileUtils.listFilesAsArray(
new File(DIRECTORY), filter, -1);
for (File f : allMatchingFiles) {
tFileList.add(f.getAbsolutePath());
}
return tFileList;
}
public class FileUtils {
public void saveArray(String filename, List<String> output_field) {
try {
FileOutputStream fos = new FileOutputStream(filename);
GZIPOutputStream gzos = new GZIPOutputStream(fos);
ObjectOutputStream out = new ObjectOutputStream(gzos);
out.writeObject(output_field);
out.flush();
out.close();
}
catch (IOException e) {
e.getStackTrace();
}
}
@SuppressWarnings("unchecked")
public List<String> loadArray(String filename) {
try {
FileInputStream fis = new FileInputStream(filename);
GZIPInputStream gzis = new GZIPInputStream(fis);
ObjectInputStream in = new ObjectInputStream(gzis);
List<String> read_field = (List<String>)in.readObject();
in.close();
return read_field;
}
catch (Exception e) {
e.getStackTrace();
}
return null;
}
public File[] listFilesAsArray(File directory, FilenameFilter[] filter,
int recurse) {
Collection<File> files = listFiles(directory, filter, recurse);
File[] arr = new File[files.size()];
return files.toArray(arr);
}
public Collection<File> listFiles(File directory,
FilenameFilter[] filter, int recurse) {
Vector<File> files = new Vector<File>();
File[] entries = directory.listFiles();
if (entries != null) {
for (File entry : entries) {
for (FilenameFilter filefilter : filter) {
if (filter == null
|| filefilter
.accept(directory, entry.getName())) {
files.add(entry);
Log.v("ImageViewFlipper", "Added: "
+ entry.getName());
}
}
if ((recurse <= -1) || (recurse > 0 && entry.isDirectory())) {
recurse--;
files.addAll(listFiles(entry, filter, recurse));
recurse++;
}
}
}
return files;
}
}
class MyGestureDetector extends SimpleOnGestureListener {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
try {
if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
return false;
// right to left swipe
if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE
&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
viewFlipper.setInAnimation(slideLeftIn);
viewFlipper.setOutAnimation(slideLeftOut);
if (currentIndex == maxIndex) {
currentIndex = 0;
} else {
currentIndex = currentIndex + 1;
}
if (currentView == 0) {
currentView = 1;
ImageView iv = (ImageView) findViewById(R.id.one);
iv.setImageDrawable(Drawable.createFromPath(ImageList
.get(currentIndex)));
System.gc();
} else if (currentView == 1) {
currentView = 2;
ImageView iv = (ImageView) findViewById(R.id.two);
iv.setImageDrawable(Drawable.createFromPath(ImageList
.get(currentIndex)));
System.gc();
} else {
currentView = 0;
ImageView iv = (ImageView) findViewById(R.id.zero);
iv.setImageDrawable(Drawable.createFromPath(ImageList
.get(currentIndex)));
System.gc();
}
Log.v("ImageViewFlipper", "Current View: " + currentView);
viewFlipper.showNext();
} else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
viewFlipper.setInAnimation(slideRightIn);
viewFlipper.setOutAnimation(slideRightOut);
if (currentIndex == 0) {
currentIndex = maxIndex;
} else {
currentIndex = currentIndex - 1;
}
if (currentView == 0) {
currentView = 2;
ImageView iv = (ImageView) findViewById(R.id.two);
iv.setImageDrawable(Drawable.createFromPath(ImageList
.get(currentIndex)));
} else if (currentView == 2) {
currentView = 1;
ImageView iv = (ImageView) findViewById(R.id.one);
iv.setImageDrawable(Drawable.createFromPath(ImageList
.get(currentIndex)));
} else {
currentView = 0;
ImageView iv = (ImageView) findViewById(R.id.zero);
iv.setImageDrawable(Drawable.createFromPath(ImageList
.get(currentIndex)));
}
Log.v("ImageViewFlipper", "Current View: " + currentView);
viewFlipper.showPrevious();
}
} catch (Exception e) {
// nothing
}
return false;
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (gestureDetector.onTouchEvent(event))
return true;
else
return false;
}
public void quit() {
SharedPreferences indexPrefs = getSharedPreferences("currentIndex",
MODE_PRIVATE);
SharedPreferences.Editor indexEditor = indexPrefs.edit();
indexEditor.putInt("currentIndex", 0);
indexEditor.commit();
File settings = new File(DATA_FILE);
settings.delete();
finish();
int pid = android.os.Process.myPid();
android.os.Process.killProcess(pid);
System.exit(0);
}
}
Dont forget: (Manifest)
android:configChanges="orientation"
Upvotes: 0
Reputation: 11
I had the same issue on Jelly Bean. FILE_TYPE = "image/jpeg" solved it for me
Upvotes: 1
Reputation: 8725
It seems that I found problem. Changing line
conn.scanFile(scanPath, FILE_TYPE);
//what is ectualy equals to:
//conn.scanFile(scanPath, "image/*");
to this line:
conn.scanFile(scanPath, null);
fixed a problem. I'm not sure but this seems to be an Android bug.
Upvotes: 2
Reputation: 3692
I was faced with a similar problem, here's the code I used to fix it:
public class CostumeLog extends Activity{
Integer[] imageIDs = {R.drawable.login_button, R.drawable.logout_button};
File root = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/TrickorTreater/Photos");
File[] files;
Bitmap[] bitmapArray;
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.costume_log_layout);
root.mkdirs();
Gallery gallery = (Gallery)findViewById(R.id.gallery1);
if ((root.isDirectory()) && (root.exists())){
files = root.listFiles();
if (!files.equals(null) || !(files.length <= 0)){
bitmapArray = new Bitmap[(files.length)];
for (int index = 0; (index <= files.length - 1); index++){
if (files[index] != null){
bitmapArray[index] = decodeSampledBitmapFromFile(files[index].toString(), 300, 240);
}//third if
}//for loop
gallery.setAdapter(new ImageAdapter(this));
gallery.setOnItemClickListener( new OnItemClickListener() {
public void onItemClick(AdapterView parent, View v, int position, long id){
Intent viewImage = new Intent(CostumeLog.this, ViewLargeImage.class);
viewImage.putExtra("INDEX", position);
startActivity(viewImage);
}
});
}//second if
}//first if
}
public class ImageAdapter extends BaseAdapter{
Context context;
int itemBackground;
public ImageAdapter(Context c){
context = c;
TypedArray a = obtainStyledAttributes(R.styleable.Gallery1);
itemBackground = a.getResourceId(R.styleable.Gallery1_android_galleryItemBackground, 0);
a.recycle();
}
public int getCount() {
return bitmapArray.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View converView, ViewGroup parent) {
ImageView imageView;
if (converView == null) {
imageView = new ImageView(context);
imageView.setImageBitmap(bitmapArray[position]);
//imageView.setImageResource(imageIDs[position]);
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
imageView.setLayoutParams(new Gallery.LayoutParams(300, 240));
} else {
imageView = (ImageView) converView;
}
imageView.setBackgroundResource(itemBackground);
return imageView;
}
}
I hope this helps
Upvotes: 0