Searching specific file types in an emulator's storage [android studio]

android
java

(Christi Az) #1

I’m new to android development and I’m trying to build a book listing app. I pushed some files in my emulator’s sdcard through command line, but they appeared in its internal storage.

Now I’m trying to find a way to access it and load specific book types (such as mobi and epud) through a FloatingActionButton.

I have read and write external storage in permissions in my AndroidManifest and this is my MainActivity as it looks like now through alot of editing in and out code that could help

//MainActivity.java
//Hosts the app's fragments and handles communication between them
//I'm skipping the phone parts of the app since my revised one is for tablets only

package com.iekproject.siegfried.libraryapp;

import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;

import java.io.File;
import java.util.ArrayList;



public class MainActivity extends AppCompatActivity
    implements LibraryFragment.LibraryFragmentListener, DetailFragment.DetailFragmentListener,
        AddEditFragment.AddEditFragmentListener {

    private static final String AUTHORITY = "com.iekproject.siegfried.libraryapp";

    //key for storing a book's Uri in a Bundle passed to a fragment
    public static final String BOOK_URI = "book_uri";

    private LibraryFragment libraryFragment; //displays library aka book list

    private File root;
    private ArrayList<File> fileList = new ArrayList<File>();
    private LinearLayout view;

    FloatingActionButton btn;
    int PICKFILE_RESULT_CODE=1;

    //displays LibraryFragment when MainActivity first loads
   @Override
    protected void onCreate(Bundle savedInstanceState) {

       super.onCreate(savedInstanceState);
       //Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
       //setSupportActionBar(toolbar);
       setContentView(R.layout.activity_main);

        //if layout contains fragmentContainer, the phone layout is in use. Create and display
        //a LibraryFragment
        if (savedInstanceState == null && findViewById(R.id.fragmentContainer) != null) {
            //create LibraryFragment
            libraryFragment = new LibraryFragment();

            //add the fragment to the FrameLayout
            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
            transaction.add(R.id.fragmentContainer, libraryFragment);
            transaction.commit(); //displays LibraryFragment
        }
        else {
            libraryFragment =
                    (LibraryFragment) getSupportFragmentManager().
                            findFragmentById(R.id.DetailFragment);
        }


       //view = (LinearLayout) findViewById(R.id.DetailFragment);

       //getting SDcard root path
       root = new File(Environment.getExternalStorageDirectory()
               .getAbsolutePath());
       getfile(root);

       for (int i = 0; i < fileList.size(); i++) {
           TextView textView = new TextView(this);
           textView.setText(fileList.get(i).getName());
           textView.setPadding(5, 5, 5, 5);

           System.out.println(fileList.get(i).getName());

           if (fileList.get(i).isDirectory()) {
               textView.setTextColor(Color.parseColor("#FF0000"));
           }
           view.addView(textView);
       }

       btn = (FloatingActionButton) findViewById(R.id.addButton);
       btn.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
               Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
               intent.setType("file/*");
               startActivityForResult(intent,PICKFILE_RESULT_CODE);
           }
       });

   }

    public ArrayList<File> getfile(File dir) {
        File listFile[] = dir.listFiles();
        if (listFile != null && listFile.length > 0) {
            for (int i = 0; i < listFile.length; i++) {

                if (listFile[i].isDirectory()) {
                    fileList.add(listFile[i]);
                    getfile(listFile[i]);

                }
                else {
                    if (listFile[i].getName().endsWith(".mobi")
                            || listFile[i].getName().endsWith(".epub")) {
                        fileList.add(listFile[i]);
                    }
                }

            }
        }
    return fileList;
    }


        @Override
            protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if(resultCode==PICKFILE_RESULT_CODE){
                Log.d("TAG", "File Uri " +data.getData());
            }
        }


   public boolean isExternalStorageReadable() {
        String state = Environment.getExternalStorageState();
        if (Environment.MEDIA_MOUNTED.equals(state) ||
                Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
            return true;
        }
        return false;
   }

    //displays DetailFragment for selected book
    @Override
    public void onBookSelected(Uri bookUri) {
            getSupportFragmentManager().popBackStack();
            displayBook(bookUri, R.id.rightPaneContainer);
    }

    //displays AddEditFragment to add a new book. Possibly what I'll also have to change to make it
    //scan/update the book list
    @Override
    public void onAddBook() {
            displayAddEditFragment(R.id.rightPaneContainer, null);
    }

    //displays a book
    private void displayBook(Uri bookUri, int viewID) {
        DetailFragment detailFragment = new DetailFragment();

        //specify book's Uri as an argument to the DetailFragment
        Bundle arguments = new Bundle();
        arguments.putParcelable(BOOK_URI, bookUri);
        detailFragment.setArguments(arguments);

        //use a FragmentTransaction to display the DetailFragment
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        transaction.replace(viewID, detailFragment);
        transaction.addToBackStack(null);
        transaction.commit(); //causes DetailFragment to display
    }

    //displays fragment for adding new or editing existing book
    private void displayAddEditFragment(int viewID, Uri bookUri) {
        AddEditFragment addEditFragment = new AddEditFragment();

        //if editing existing book, provide bookUri as an argument
        if (bookUri != null) {
            Bundle arguments = new Bundle();
            arguments.putParcelable(BOOK_URI, bookUri);
            addEditFragment.setArguments(arguments);
        }

        //use a FragmentTransaction to display the AddEditFragment
        FragmentTransaction transaction =
                getSupportFragmentManager().beginTransaction();
        transaction.replace(viewID, addEditFragment);
        transaction.addToBackStack(null);
        transaction.commit(); //causes AddEditFragment to display
    }

    //return to book list when displayed book deleted
    @Override
    public void onBookDeleted() {
        //removes top of back stack
        getSupportFragmentManager().popBackStack();
        libraryFragment.updateLibrary(); //refresh book list
    }

    //displays the AddEditFragment to edit an existing book. Maybe it can be used as Move or sth
   /*@Override
    public void onEditBook(Uri bookUri) {
        displayAddEditFragment(R.id.rightPaneContainer, bookUri);
    }*/

    //update GUI after the new book or updated book saved
    @Override
    public void onAddEditCompleted(Uri bookUri) {
        //removes top of back stack
        getSupportFragmentManager().popBackStack();
        libraryFragment.updateLibrary(); //refresh book list

        if (findViewById(R.id.fragmentContainer) == null){ //tablet
            //removes top of back stack
            getSupportFragmentManager().popBackStack();

            //on tablet, displays the book that was just added or edited
            displayBook(bookUri, R.id.rightPaneContainer);
        }
    }
}

I am at my wits end… I’ve been trying to find a solution to just what I’m asking help for for like 2 days and I can’t spend more than 2 more days on it 'cos I have alot of other projects to do (opengl, dreamweaver, more java just not in android studio etc) so any help will be greatly appreciated =D

EDIT: I was informed that Internal storage is part of the memory system that is “local” to an app, which cleared some things for me. I pushed some books through command line on the emulator that were supposed to appear in the sdcard but they appear instead in Storage (through the emulator’s settings app) and in Android SDK built for x86 which has multiple folders one of which is Downloads and there my files are. Hope this clears some things that might have otherwise confuse


(Yassine) #2

Welcome @Christi_Az to Stopbyte :slight_smile:
I understand your urgency so I’m going ahead and tagging some Android & Java experts in the platform that can help you out.

@jms @yay @isoftech @sparta @sam @KunniCan Have fun guys.


(Christi Az) #3

thank you so much =D
My urgency mostly stems from the fact that after the Lent holidays I have exams so I can’t spend anymore time on it without a solution >_<


(SAM) #4

Hi @Christi_Az,

So after checking your code I found that you are actually listing files in External storage not in SD card.

  //getting SDcard root path
   root = new File(Environment.getExternalStorageDirectory()
           .getAbsolutePath());
   getfile(root);

So instead try to add the “/external_sd” path segment for it to work, something like this:

  //getting SDcard root path
   root = new File(Environment.getExternalStorageDirectory().toString() + "/external_sd");
   getfile(root);

P.S. I am not sure why you used “getAbsolutePath()” so I removed it :stuck_out_tongue:

Let us know if that didn’t work or you had any specific issues :slight_smile:


(Yassine) #5

I believe since is using the a recursive method to search through directories it wont be a problem!

public ArrayList<File> getfile(File dir)

that will list all files in the external storage (no matter what storage)… including the SD Card.


(Christi Az) #6

Nothing really changed and I wonder if the problem is here:

btn = (FloatingActionButton) findViewById(R.id.addButton);
       btn.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
               Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
               intent.setType("file/*");
               startActivityForResult(intent,PICKFILE_RESULT_CODE);
           }
       });

        @Override
            protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if(resultCode==PICKFILE_RESULT_CODE){
                Log.d("TAG", "File Uri " +data.getData());
            }
        }

Can it be the rest of the code is getting bypassed because of that? 'Cos when I’m clicking the Floating Button it takes me here:

and my files aren’t there to find and “open” plus I’m looking for the floating button to search and load the files automatically


(Kunni Can) #7

hmm… I have couple notes on this part of your code:

   public void onClick(View v) {
       Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
       intent.setType("file/*");
       startActivityForResult(intent,PICKFILE_RESULT_CODE);
   }

First just for debugging purposes, you can probably consider putting your files in a specific folder in the SD card, rather than directly into the SD card (that’s optional) and then you can get directly taken to that folder when clicked, using this code snippet:

public void onClick(View v) {
    Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
    Uri uri = Uri.parse(Environment.getExternalStorageDirectory().getPath() + "/YourSpecificDirectory/");
    intent.setDataAndType(uri, "*/*");
    startActivity(Intent.createChooser(intent, "Open folder"));
}

That should help you out.


(jms) #8

I don’t know if this helps, but noticed you used intent.setType("file/*");

not sure if you are already aware of this; setting a file extension filter will force Android to look for an installed app that is set to handle that specific file extension, if it fails to find one it will either crash or open the default android file browser.

I highly recommend using / as your extension filter, and probably install a file manager.
And just in case adding a try/catch wouldn’t hurt as well.


(jms) #9

You can actually use OI File Manager To browse your SD Card.

And then use this code to get it to work:

    File root = new File(Environment.getExternalStorageDirectory().getPath() + "/Your Path If any/");
    Uri uri = Uri.parse(root);
    Intent intent = new Intent();

    intent.setAction(android.content.Intent.ACTION_VIEW);
    intent.setData(uri);
    startActivityForResult(intent, 1);

Only minor edits were done from your original code.


(Christi Az) #10

I have no clue how to do that, our prof’s fave motto is “if you don’t know how to do something google it” which would have been okay if we weren’t just now learning java along with this class project, which requires some rudimentary skills.

Should I assume that SDcard is the same as theAndroid SDK built for x86 which has multiple folders one of which is Downloads and there my files are which those 2 things show as separate in my tablet emulator.

That btw was LOADS of help, though I’m starting to suspect that since there’s no program to open book file types they just don’t bother to appear. The music I pushed on the emulator appeared but the books are AWOL


(Christi Az) #11

Please feel free to upend the code however you think it’ll work best. As I mentioned in my answer towards KunniCan, I’m developing the app as a project for a class when we have only started learning java in another class for the past month, so frankly the code is based on a Contact List app and whatever help I could find through searching the internet copy-pasting and editing.

I’m not sure I can use an app to access my app (that’s what it is right? google didn’t betray me?) I’ll have to ask my prof after the Lent holidays.

As for the “/” I think KunniCan fixed it in their answer


(Yassine) #12

Are you using a Samsung Device for this android app?

taking into account that you are a bit new to java here is full code snippet of your app, with changes

//MainActivity.java
//Hosts the app's fragments and handles communication between them
//I'm skipping the phone parts of the app since my revised one is for tablets only

package com.iekproject.siegfried.libraryapp;

import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;

import java.io.File;
import java.util.ArrayList;



public class MainActivity extends AppCompatActivity
    implements LibraryFragment.LibraryFragmentListener, DetailFragment.DetailFragmentListener,
        AddEditFragment.AddEditFragmentListener {

    private static final String AUTHORITY = "com.iekproject.siegfried.libraryapp";

    //key for storing a book's Uri in a Bundle passed to a fragment
    public static final String BOOK_URI = "book_uri";

    private LibraryFragment libraryFragment; //displays library aka book list

    private File root;
    private ArrayList<File> fileList = new ArrayList<File>();
    private LinearLayout view;

    FloatingActionButton btn;
    int PICKFILE_RESULT_CODE=1;

    //displays LibraryFragment when MainActivity first loads
   @Override
    protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       //Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
       //setSupportActionBar(toolbar);
       setContentView(R.layout.activity_main);

        //if layout contains fragmentContainer, the phone layout is in use. Create and display
        //a LibraryFragment
        if (savedInstanceState == null && findViewById(R.id.fragmentContainer) != null) {
            //create LibraryFragment
            libraryFragment = new LibraryFragment();

            //add the fragment to the FrameLayout
            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
            transaction.add(R.id.fragmentContainer, libraryFragment);
            transaction.commit(); //displays LibraryFragment
        } else {
            libraryFragment =
                    (LibraryFragment) getSupportFragmentManager().
                            findFragmentById(R.id.DetailFragment);
        }

       //view = (LinearLayout) findViewById(R.id.DetailFragment);

       //getting SDcard root path
       root = new File(Environment.getExternalStorageDirectory().getAbsolutePath());
       getfile(root);

       for (int i = 0; i < fileList.size(); i++) {
           TextView textView = new TextView(this);
           textView.setText(fileList.get(i).getName());
           textView.setPadding(5, 5, 5, 5);

           System.out.println(fileList.get(i).getName());

           if (fileList.get(i).isDirectory()) {
               textView.setTextColor(Color.parseColor("#FF0000"));
           }
           view.addView(textView);
       }

       btn = (FloatingActionButton) findViewById(R.id.addButton);
       btn.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
               /* This is the modifications I made for Samsung Devices */
               Intent intent = new Intent("com.sec.android.app.myfiles.PICK_DATA");
               intent.putExtra("CONTENT_TYPE", "*/*");
               intent.addCategory(Intent.CATEGORY_DEFAULT);
               startActivityForResult(intent,PICKFILE_RESULT_CODE);
           }
       });

   }

    public ArrayList<File> getfile(File dir) {
        File listFile[] = dir.listFiles();
        if (listFile != null && listFile.length > 0) {
            for (int i = 0; i < listFile.length; i++) {

                if (listFile[i].isDirectory()) {
                    fileList.add(listFile[i]);
                    getfile(listFile[i]);

                }
                else {
                    if (listFile[i].getName().endsWith(".mobi")
                            || listFile[i].getName().endsWith(".epub")) {
                        fileList.add(listFile[i]);
                    }
                }

            }
        }
    return fileList;
    }


        @Override
            protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if(resultCode==PICKFILE_RESULT_CODE){
                Log.d("TAG", "File Uri " +data.getData());
            }
        }


   public boolean isExternalStorageReadable() {
        String state = Environment.getExternalStorageState();
        if (Environment.MEDIA_MOUNTED.equals(state) ||
                Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
            return true;
        }
        return false;
   }

    //displays DetailFragment for selected book
    @Override
    public void onBookSelected(Uri bookUri) {
            getSupportFragmentManager().popBackStack();
            displayBook(bookUri, R.id.rightPaneContainer);
    }

    //displays AddEditFragment to add a new book. Possibly what I'll also have to change to make it
    //scan/update the book list
    @Override
    public void onAddBook() {
            displayAddEditFragment(R.id.rightPaneContainer, null);
    }

    //displays a book
    private void displayBook(Uri bookUri, int viewID) {
        DetailFragment detailFragment = new DetailFragment();

        //specify book's Uri as an argument to the DetailFragment
        Bundle arguments = new Bundle();
        arguments.putParcelable(BOOK_URI, bookUri);
        detailFragment.setArguments(arguments);

        //use a FragmentTransaction to display the DetailFragment
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        transaction.replace(viewID, detailFragment);
        transaction.addToBackStack(null);
        transaction.commit(); //causes DetailFragment to display
    }

    //displays fragment for adding new or editing existing book
    private void displayAddEditFragment(int viewID, Uri bookUri) {
        AddEditFragment addEditFragment = new AddEditFragment();

        //if editing existing book, provide bookUri as an argument
        if (bookUri != null) {
            Bundle arguments = new Bundle();
            arguments.putParcelable(BOOK_URI, bookUri);
            addEditFragment.setArguments(arguments);
        }

        //use a FragmentTransaction to display the AddEditFragment
        FragmentTransaction transaction =
                getSupportFragmentManager().beginTransaction();
        transaction.replace(viewID, addEditFragment);
        transaction.addToBackStack(null);
        transaction.commit(); //causes AddEditFragment to display
    }

    //return to book list when displayed book deleted
    @Override
    public void onBookDeleted() {
        //removes top of back stack
        getSupportFragmentManager().popBackStack();
        libraryFragment.updateLibrary(); //refresh book list
    }

    //displays the AddEditFragment to edit an existing book. Maybe it can be used as Move or sth
   /*@Override
    public void onEditBook(Uri bookUri) {
        displayAddEditFragment(R.id.rightPaneContainer, bookUri);
    }*/

    //update GUI after the new book or updated book saved
    @Override
    public void onAddEditCompleted(Uri bookUri) {
        //removes top of back stack
        getSupportFragmentManager().popBackStack();
        libraryFragment.updateLibrary(); //refresh book list

        if (findViewById(R.id.fragmentContainer) == null){ //tablet
            //removes top of back stack
            getSupportFragmentManager().popBackStack();

            //on tablet, displays the book that was just added or edited
            displayBook(bookUri, R.id.rightPaneContainer);
        }
    }
}

Copy and Paste that code it should work directly for you :slight_smile:

This is the only part of your code I changed, to make it Samsung devices Compliant:

  public void onClick(View v) {
       /* This is the modifications I made for Samsung Devices */
       Intent intent = new Intent("com.sec.android.app.myfiles.PICK_DATA");
       intent.putExtra("CONTENT_TYPE", "*/*");
       intent.addCategory(Intent.CATEGORY_DEFAULT);
       startActivityForResult(intent,PICKFILE_RESULT_CODE);
   }

If you (@Christi_Az) are not using Samsung device then please let me know more about your app so I can help you out better :blush:¨


(Christi Az) #13

My emulator is a Nexus 9 though I think I might use a Nexus 7, so that modification in the onClick will need to be changed

@Yassine
Thank you so much… I began this app thinking I’ll learn things as I go, but it didn’t prove to be like that. I’ll need a more thorough understanding of java before trying anything more ambitious next time. Let’s hope that after the holidays the class that teaches as java will pick up =D

EDIT: If I change the Intent intent to
Intent intent = new Intent("/external_sd/Downloads");

I see the Downloads folder briefly and then the app crashes, also from the brief glimpse it shows all files not just the .mobi and .epub ones


(Yassine) #14

Yep,
Apparently that means you DO NOT have an app that manages Files in your emulator.
and that is why almost everyone in the thread, suggested that you avoid using “file/*” or any specific file extensions (like .mobi and .epub).

Because your emulator doesn’t have a files manager app installed it will crash :slight_smile:
So either implement a File manager (which is hard to be honest especially for a newbie) or you can install a files manager before using your app :slight_smile:


(Christi Az) #15

Ahhh… that answers a few questions.
I think most of the emulators are of the Nexus variety. I do a Kindle tablet though. Do you think if I worked with that things might be easier?
And to cover all bases a file manager like that: https://play.google.com/store/apps/details?id=org.openintents.filemanager ??
Will that also help with instead of browsing the folders when I click the addButton to load the filtered files and display them as a list?


(Yassine) #16

Well @Christi_Az The point from using OI FileManager, is because you have to. in order for you to be able to browse your files.
And Yes, try it out :slight_smile:


(Christi Az) #17

Will do, thank you ^^ I’ll take a break for a couple of days from the code and regroup =D Till then if anyone has any ideas send them my way :wink: