Click here to Skip to main content
15,885,546 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
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 storage where you can find multiple folders like Downloads (where my files are), Alarms, Music etc.

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

Java
//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

What I have tried:

Pretty much everything I have tried are in the code commented or at work
Posted
Updated 13-Apr-17 11:09am
v2
Comments
Nick_3141592654 13-Apr-17 11:47am    
Please spell-out your technical problem clearly.

Is it that:

1. You were expecting SDCARD in your emulator to correspond to a physical SDCARD on your device rather than internal storage?

or related to what you mention about:

2. Reading specific books, e.g. are you looking for a file filter of some kind?

One other thing, do you actually know what Internal and External storage mean in Android? These terms are not well named and can cause a lot of confusion. Internal storage is part of the memory system that is "local" to an app, i.e. is it accessed only within that app and is in that sense internal. External storage is *ALL* other parts of the memory system (excluding the internal storage associated with other apps). Do not assume that Internal & External corresponds to Flash & SD physical memory respectively, because this is not the case.
Christi Az 13-Apr-17 12:10pm    
1. I did the push of the files through command line to sdcard but the files when going through the emulator's settings app appear to be in Android SDK built for x86 which has multiple folders one of which is Downloads.

2. File filter that's why I have this:
(listFile[i].getName().endsWith(".mobi")
|| listFile[i].getName().endsWith(".epub")) {
fileList.add(listFile[i]);
though I'm not sure if it works or not.

Oh okay didn't know that, thank you for clearing it up
Nick_3141592654 13-Apr-17 11:51am    
Also to add, if you're really trying to access External storage on Android Marshmallow or later, you will need to handle an explicit permission request at run-time: in these later Android versions you cannot simply declare all wanted permissions in the Manifest and expect them to be granted to your app (some permissions are OK, depending on their security implications).
Christi Az 13-Apr-17 12:11pm    
I have added the permission to the AndroidManifest, both write and read on external storage

1 solution

OK, so when you say "push" you're talking about an adb push command - that's very different from the kind of PUSH service that I thought you might be talking about.

Let's think about your second question first: how to do the file filtering. There's an easy solution using the Apache Commons IO File Utilities. This is an additional Android library that you can add to your project, it will supplement the SDK and provides a set of very useful file-related utilities which will make it easier to achieve the filtering that you want.

I know that you want to wrap this up quickly so you might not want to go with the new library approach. In that case you need to use the debugger and work through it yourself. Just set some breakpoints and single step from there.

Now the question about pushing files. You can again use the debugger (or android.util.Log) to confirm the absolute path to your device's external storage area. It's likely available at /storage/sdcard0. Use the "adb shell" command to open a shell and check that you can navigate to that directory (e.g. "cd /storage/sdcard0") and list some files there ("ls -l"). Assuming that you can then quit the shell and do your push to that absolute path ("adb push <your files> <absolute path to ext storage>").
 
Share this answer
 
Comments
Christi Az 14-Apr-17 5:35am    
Added the library you recommended will have to spend some time trying to work out how to use it but nevertheless thank you

Okay I'll try pushing the files like that, just a quick question, do you think that if I push them correctly (meaning in the right storage) once I click on the button, instead of being directed to the folder they are stored like it semi-happens now, they will appear as a list on my tablet screen?
Nick_3141592654 14-Apr-17 7:32am    
Do you want the files to appear like app icons on your tablet screen? If so then no this won't happen.

However your tablet must have a File Manager app that you can use to explore the file system (although the default app is unlikely to show system areas). On Marshmallow there's a basic file-explorer view available within the Settings menu (access here: http://www.greenbot.com/article/2996030/android/how-to-get-to-android-marshmallows-hidden-file-manager.html). On Android N the simple file-explorer is similarly accessed but in this case you need Settings->Storage->Explore (and very nice it is too, giving access to, I think, the entire file system).
Christi Az 14-Apr-17 10:07am    
What I want to do is by pressing a button have it enter the Storage->Explore->Downloads folder and load in a list view all the mobi and epub files it finds there, with minimal info (cover, author, title), like a simple audio app does (you know item1, item2, item3 etc). My MainActivity might be going totally the wrong way about it, but till I find a way to access and load the info on that folder I don't think I can move on.

I don't want clicking the button to show me another screen in which on the left it says "OPEN FROM" and has SOME of the folders like SDCard, Downloads (which for some reason is empty, 'cos apparently it isn't the one on the Storage>Explore), audio, contacts, gallery and an unsupported action

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900