I am very new to android still creating my first application. I am trying to achieve reading from a static excel file(data will not change) and do some computation. I have gone through various online resources but however all does not specify where to store my excel file into(maybe it is too idiotproof) but unfortunately i do not know.
What i have done:
private static void readExcelFile(Context context, String filename) {
if (!isExternalStorageAvailable() || isExternalStorageReadOnly()) {
Log.e(TAG, "Storage not available or read only");
return;
}
try {
// Creating Input Stream
File file = new File(context.getExternalFilesDir(null), filename);
FileInputStream myInput = new FileInputStream(file);
// Create a POIFSFileSystem object
POIFSFileSystem myFileSystem = new POIFSFileSystem(myInput);
// Create a workbook using the File System
HSSFWorkbook myWorkBook = new HSSFWorkbook(myFileSystem);
// Get the first sheet from workbook
HSSFSheet mySheet = myWorkBook.getSheetAt(0);
/** We now need something to iterate through the cells. **/
Iterator rowIter = mySheet.rowIterator();
while (rowIter.hasNext()) {
HSSFRow myRow = (HSSFRow) rowIter.next();
Iterator cellIter = myRow.cellIterator();
while (cellIter.hasNext()) {
HSSFCell myCell = (HSSFCell) cellIter.next();
Log.d(TAG, "Cell Value: " + myCell.toString());
Toast.makeText(context, "cell Value: " + myCell.toString(),
Toast.LENGTH_SHORT).show();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return;
}
public static boolean isExternalStorageReadOnly() {
String extStorageState = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(extStorageState)) {
return true;
}
return false;
}
public static boolean isExternalStorageAvailable() {
String extStorageState = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(extStorageState)) {
return true;
}
return false;
}
and when onlclick i will call by using readExcelFile(ScoreActivity.this, "myExcel.xlsx");
Can someone please advice
If you want your file to be shipped along with your application, then you could put it in assets or res/raw folders, and then read it from there. Otherwise, you can put it on sdcard, but I see you are already doing this.
Related
Programming with Android Studio and the osmdroid library.
I downloaded a portion of a map using the cacheManager.downloadAreaAsync() method. This method stores the map piece in a sqlite file in the data/data/<package>/osmdroid/tiles directory, chosen by me.
Now I want to use this map to load it offline in a mobile application.
I've tried to do it through all kinds of classes (MapTileSqlCacheProvider, XYTileSource, OfflineTileProvider, ...) but I can't get the map to appear.
How should I do it?
To download a portion of the map I do this:
map.setTileSource(TileSourceFactory.OpenTopo);
outputPath = "/data/data/<package>/files" + File.separator + "osmdroid" + File.separator + "tiles" + File.separator;
outputName = outputPath + boxE6.name + ".db";
try {
writer=new SqliteArchiveTileWriter(outputName);
} catch (Exception ex) {
ex.printStackTrace();
}
CacheManager cacheManager = new CacheManager(map,writer);
cacheManager.downloadAreaAsync(this, boxE6, 7, 13, new CacheManager.CacheManagerCallback() {
#Override
public void onTaskComplete() {
Toast.makeText(ctx, "Download complete!", Toast.LENGTH_LONG).show();
if (writer!=null)
writer.onDetach();
} ...
To retrieve the stored map (in this case it is in the usa.db file) I try to do this:
map.setUseDataConnection(false);
map.setTileSource(TileSourceFactory.OpenTopo);
File cache = new File(outputName);
Configuration.getInstance().setOsmdroidTileCache(cache);
mapController.setCenter(new GeoPoint((n+s)/2,(e+w)/2));
I will show how I store and load multiple sqlite Tiles, not just one.
The above answer from José Espejo Roig worked only partly for me. It worked almost fine for caching the tiles, but not for reading them. Writing down cache files though is also not complete. I have created my own code using as example: Make a tile archive from OSMDroid Github.
So to store potentially more than 1 tiles in a specific directory I use a code like below. It creates sequentially my_mapX.sqlite, where X are just stepped consecutive integers. So I get my_map1.sqlite, my_map2.sqlite and so on.
private final String MAP_FILE_NAME = "my_map";
private final String MAP_FILE_EXTENSION = ".sqlite";
// ...
Context ctx = getActivity();
mMapView = new MapView(ctx);
((ConstraintLayout) view.findViewById(R.id.osm_fragment)).addView(mMapView);
mMapView.setTileSource(TileSourceFactory.OpenTopo);
ContextWrapper contextWrapper = new ContextWrapper(ctx);
File root_directory = contextWrapper.getDir(ctx.getFilesDir().getName(), Context.MODE_PRIVATE);
File directory_osm = new File(root_directory, "osmdroid");
directory_osm.mkdir();
File directory = new File(directory_osm, "tiles");
directory.mkdir();
File[] nrFiles = directory.listFiles(new FilenameFilter() {
#Override
public boolean accept(File dir, String name) {
if (name.endsWith(MAP_FILE_EXTENSION))
return true;
return false;
}
});
String osmdroidTile = directory.getAbsolutePath() + File.separator + MAP_FILE_NAME + (nrFiles.length + 1) + MAP_FILE_EXTENSION;
BoundingBox boxE6 = mMapView.getBoundingBox();
SqliteArchiveTileWriter writer = null;
try {
writer = new SqliteArchiveTileWriter(osmdroidTile);
} catch (Exception ex) {
ex.printStackTrace();
}
CacheManager cacheManager = new CacheManager(mMapView, writer);
SqliteArchiveTileWriter finalWriter = writer;
int currZoom = (int)mMapView.getZoomLevelDouble();
cacheManager.downloadAreaAsync(ctx, boxE6, currZoom, currZoom + 1, new CacheManager.CacheManagerCallback() {
#Override
public void onTaskComplete() {
Toast.makeText(ctx, "Download complete!", Toast.LENGTH_LONG).show();
if (finalWriter != null)
finalWriter.onDetach();
}
#Override
public void updateProgress(int progress, int currentZoomLevel, int zoomMin, int zoomMax) {
}
#Override
public void downloadStarted() {
}
#Override
public void setPossibleTilesInArea(int total) {
}
#Override
public void onTaskFailed(int errors) {
Toast.makeText(getActivity(), "Download complete with " + errors + " errors", Toast.LENGTH_LONG).show();
if (finalWriter != null)
finalWriter.onDetach();
}
});
}
});
This way I can create as many tile files as I want. Important is that they have ".sqlite" extension. ".db" extension didn't work for me.
Now to read these tiles I used again example from OSMDroid Github: Sample SQLITE example. In OSMDroid Github example TileSource is being determined with IArchiveFile. I skipped that, as I assume I know what TileSource I used (in my case it is OpenTopo, as you can see). Then to read multiple offline tiles from the same TileSource (basing on example from OSMDroid) my code looks like this:
//first we'll look at the default location for tiles that we support
Context ctx = getActivity();
mMapView = new MapView(ctx);
((ConstraintLayout) view.findViewById(R.id.osm_fragment)).addView(mMapView);
mMapView.setUseDataConnection(false);
ContextWrapper contextWrapper = new ContextWrapper(ctx);
File root_directory = contextWrapper.getDir(ctx.getFilesDir().getName(), Context.MODE_PRIVATE);
String osmDir = root_directory.getAbsolutePath() + File.separator + "osmdroid" + File.separator + "tiles";
File f = new File(osmDir);
if (f.exists()) {
File[] list = f.listFiles();
ArrayList<File> sqliteArray = new ArrayList<>();
if (list != null) {
for (int i = 0; i < list.length; i++) {
if (list[i].isDirectory()) {
continue;
}
String name = list[i].getName().toLowerCase();
if (!name.contains(".")) {
continue; //skip files without an extension
}
name = name.substring(name.lastIndexOf(".") + 1);
if (name.length() == 0) {
continue;
}
//narrow it down to only sqlite tiles
if (ArchiveFileFactory.isFileExtensionRegistered(name) && name.equals("sqlite")) {
sqliteArray.add(list[i]);
}
}
}
OfflineTileProvider tileProvider;
if (sqliteArray.size() > 0) {
try {
tileProvider = new OfflineTileProvider(new SimpleRegisterReceiver(getActivity()), sqliteArray.toArray(new File[0]));
mMapView.setTileProvider(tileProvider);
mMapView.setTileSource(TileSourceFactory.OpenTopo);
mMapView.invalidate();
} catch (Exception e) {
e.printStackTrace();
}
}
} else {
Toast.makeText(getActivity(), f.getAbsolutePath() + " dir not found!", Toast.LENGTH_SHORT).show();
}
I used to get all the files in USB/SD Card from "/storage/external_storage" like so
File = new File("/storage/external_storage");
file.listFiles()
and show the files and folders in my own Fragment and it worked great until API 23. Where now I am unable to get the file list from the path.
I know in Android Marshmallow (23) there were permission changes and some USB Connection behavior changes.
If your app supports user interactions with the device over a USB port, take into consideration that the interaction must be explicitly enabled.
Does not explain how or when user can enable interactions explicitly.
My question is whether or not it is possible to Access USB files and Folders list.
If there is how can we achieve this?
EDIT : I opened Android Device Monitor and I couldn't find external_storage in /storage/external_storage.
It is true the doc is not very clear about that....but it seems you have to ask the system to mount the media device for you. Can you try to use
Environment.getExternalStorageState() to see what it returns you?
Otherwise, you can also try to access the SD/External USB by using this class:
public class ExternalStorage {
public static final String SD_CARD = "sdCard";
public static final String EXTERNAL_SD_CARD = "externalSdCard";
/**
* #return True if the external storage is available. False otherwise.
*/
public static boolean isAvailable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
return true;
}
return false;
}
public static String getSdCardPath() {
return Environment.getExternalStorageDirectory().getPath() + "/";
}
/**
* #return True if the external storage is writable. False otherwise.
*/
public static boolean isWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
/**
* #return A map of all storage locations available
*/
public static Map<String, File> getAllStorageLocations() {
Map<String, File> map = new HashMap<String, File>(10);
List<String> mMounts = new ArrayList<String>(10);
List<String> mVold = new ArrayList<String>(10);
mMounts.add("/mnt/sdcard");
mVold.add("/mnt/sdcard");
try {
File mountFile = new File("/proc/mounts");
if(mountFile.exists()){
Scanner scanner = new Scanner(mountFile);
while (scanner.hasNext()) {
String line = scanner.nextLine();
if (line.startsWith("/dev/block/vold/")) {
String[] lineElements = line.split(" ");
String element = lineElements[1];
// don't add the default mount path
// it's already in the list.
if (!element.equals("/mnt/sdcard"))
mMounts.add(element);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
try {
File voldFile = new File("/system/etc/vold.fstab");
if(voldFile.exists()){
Scanner scanner = new Scanner(voldFile);
while (scanner.hasNext()) {
String line = scanner.nextLine();
if (line.startsWith("dev_mount")) {
String[] lineElements = line.split(" ");
String element = lineElements[2];
if (element.contains(":"))
element = element.substring(0, element.indexOf(":"));
if (!element.equals("/mnt/sdcard"))
mVold.add(element);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
for (int i = 0; i < mMounts.size(); i++) {
String mount = mMounts.get(i);
if (!mVold.contains(mount))
mMounts.remove(i--);
}
mVold.clear();
List<String> mountHash = new ArrayList<String>(10);
for(String mount : mMounts){
File root = new File(mount);
if (root.exists() && root.isDirectory() && root.canWrite()) {
File[] list = root.listFiles();
String hash = "[";
if(list!=null){
for(File f : list){
hash += f.getName().hashCode()+":"+f.length()+", ";
}
}
hash += "]";
if(!mountHash.contains(hash)){
String key = SD_CARD + "_" + map.size();
if (map.size() == 0) {
key = SD_CARD;
} else if (map.size() == 1) {
key = EXTERNAL_SD_CARD;
}
mountHash.add(hash);
map.put(key, root);
}
}
}
mMounts.clear();
if(map.isEmpty()){
map.put(SD_CARD, Environment.getExternalStorageDirectory());
}
return map;
}
}
The use is like this:
Map<String, File> externalLocations = ExternalStorage.getAllStorageLocations();
File sdCard = externalLocations.get(ExternalStorage.SD_CARD);
File externalSdCard = externalLocations.get(ExternalStorage.EXTERNAL_SD_CARD);
Source here: Find an external SD card location
Have a look at getExternalFilesDirs().
If a micro SD card is inserted the second entry will point to the card.
If you then attach a USB OTG drive the third entry will point to the drive.
With Intent.ACTION_OPEN_DOCUMENT_TREE you can let the user choose from all drives and then use Storage Access Framework.
I'm having this issue with Android TV (sampleApp).
I'm inputting streaming channels from a xml file. I'm creating a temp file to be used at the start, and then I have created a button that does all the necessary functions to acquire data from the server and create the NEW xml file from that data. All of this works, but there's one issues:
After pressing the button and file is created, I try to add channels by pressing "add channels" button, but the file that is used is the temp file, not the NEW xml file. So that it uses the NEW xml file, I have to re-run the setup again and then it works flawlesly. It seems like it caches the temp file in memory or something and uses it first when adding channels, because when the app is launched there is no internal storage file (this is where i save my NEW xml file), the file is created only after the button press.
How do I make it so it uses the NEW xml file instead of the temp file(that created during app launch)?, instead of doing a re-setup
This is the method that is used. Basically, on the first launch it creates an xml with no channels or programs(the temp file) and does what it has to. Then using my other class I create a NEW xml file with all the channels and programs. That also works, the file exists and it goes to the else statement after I press the "add Channels" button. But regardless, on the first try after pressing the button it always adds the temp file, rather than the new one. The new one is only runned, if I launch the setup again.
public static XmlTvParser.TvListing getRichTvListings(Context context) {
context1 = context;
FileOutputStream fos;
try {
Boolean exists = context.getFileStreamPath(FILENAME).exists();
if (exists == false){
String string = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
"<!DOCTYPE tv SYSTEM \"xmltv.dtd\">\n" +
"\n" +
"<tv>\n" +
"</tv>";
Log.d(TAG,"Exists: FALSE");
fos = context.openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(string.getBytes());
fos.close();
read = "file:" + context.getFilesDir().toString() + "/" + FILENAME ;
Uri catalogUri =Uri.parse(read);
if (sSampleTvListing != null) {
return sSampleTvListing;
}
try (InputStream inputStream = getInputStream(context, catalogUri)) {
sSampleTvListing = XmlTvParser.parse(inputStream);
} catch (IOException e) {
Log.e(TAG, "Error in fetching " + catalogUri, e);
}
}
else{
Log.d(TAG,"Exists: TRUE");
FileInputStream fis = context.openFileInput(FILENAME2);
StringBuilder builder = new StringBuilder();
int inputChar;
while((inputChar = fis.read()) != -1) {
builder.append((char) inputChar);
}
String readFile = builder.toString();
Log.d(TAG, "FileContent: " + readFile);
read = "file:" + context.getFilesDir().toString() + "/" + FILENAME2 ;
Uri catalogUri =Uri.parse(read);
if (sSampleTvListing != null) {
return sSampleTvListing;
}
try (InputStream inputStream = getInputStream(context, catalogUri)) {
sSampleTvListing = XmlTvParser.parse(inputStream);
} catch (IOException e) {
Log.e(TAG, "Error in fetching " + catalogUri, e);
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return sSampleTvListing;
}
The the button functionalities are in my richSetupFragment class(I wont post all of it, but these are the part that I think are most important in this case):
#Override
protected Boolean doInBackground(Uri... params) {
mTvListing = RichFeedUtil.getRichTvListings(getActivity());
mPoster = fetchPoster();
return true;
}
#Override
public void onActionClicked(Action action) {
if (action.getId() == ACTION_ADD_CHANNELS) {
setupChannels(mInputId);
} else if (action.getId() == ACTION_CANCEL) {
getActivity().finish();
}
else if (action.getId() == RETRIEVE_DATA) {
getChannelsFromServer();
// Log.d(TAG,"List: " + list);
}
private void setupChannels(String inputId) {
inputIdLocal= inputId;
if (mTvListing == null) {
onError(R.string.feed_error_message);
return;
}
TvContractUtils.updateChannels(getActivity(), inputId, mTvListing.channels);
SyncUtils.setUpPeriodicSync(getActivity(), inputId);
SyncUtils.requestSync(inputId, true);
mSyncRequested = true;
// Watch for sync state changes
if (mSyncObserverHandle == null) {
final int mask = ContentResolver.SYNC_OBSERVER_TYPE_PENDING |
ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE;
mSyncObserverHandle = ContentResolver.addStatusChangeListener(mask,
mSyncStatusObserver);
}
}
Is it true that the file path to external SDCard on Android devices are always "/storage/extSdCard"? If not, how many variations are there?
I need it for my App to test the availability of external SDCard.
I am using Titanium, it has a method Titanium.Filesystem.isExternalStoragePresent( )
but it always return true even external SDCard is not mounted.
I think it detect SDCard at local storage thus return true. But what I really want is detect whether physical SDCard is mounted or not.
Can I do this by detecting the existence of file "/storage/extSdCard" alone?
Thanks.
Is it true that the file path to external SDCard on Android devices are always "/storage/extSdCard"? If not, how many variations are there?
Sadly the path to the external storage is not always the same according to manufacturer. Using Environment.getExternalStorageDirectory() will return you the normal path for SD card which is mnt/sdcard/. But for Samsung devices for example, the SD card path is either under mnt/extSdCard/ or under mnt/external_sd/.
So one way to proceed would be to check the existence of external directory according to the path used by each manufacturer. With something like this:
mExternalDirectory = Environment.getExternalStorageDirectory()
.getAbsolutePath();
if (android.os.Build.DEVICE.contains("samsung")
|| android.os.Build.MANUFACTURER.contains("samsung")) {
File f = new File(Environment.getExternalStorageDirectory()
.getParent() + "/extSdCard" + "/myDirectory");
if (f.exists() && f.isDirectory()) {
mExternalDirectory = Environment.getExternalStorageDirectory()
.getParent() + "/extSdCard";
} else {
f = new File(Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/external_sd" + "/myDirectory");
if (f.exists() && f.isDirectory()) {
mExternalDirectory = Environment
.getExternalStorageDirectory().getAbsolutePath()
+ "/external_sd";
}
}
}
But what I really want is detect whether physical SDCard is mounted or not.
I didn't try the code yet, but the approach of Dmitriy Lozenko in this answer is much more interesting. His method returns the path of all mounted SD cards on sytem regardless of the manufacturer.
This is how I finally got sdcard path using :
public String getExternalStoragePath() {
String internalPath = Environment.getExternalStorageDirectory().getAbsolutePath();
String[] paths = internalPath.split("/");
String parentPath = "/";
for (String s : paths) {
if (s.trim().length() > 0) {
parentPath = parentPath.concat(s);
break;
}
}
File parent = new File(parentPath);
if (parent.exists()) {
File[] files = parent.listFiles();
for (File file : files) {
String filePath = file.getAbsolutePath();
Log.d(TAG, filePath);
if (filePath.equals(internalPath)) {
continue;
} else if (filePath.toLowerCase().contains("sdcard")) {
return filePath;
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
try {
if (Environment.isExternalStorageRemovable(file)) {
return filePath;
}
} catch (RuntimeException e) {
Log.e(TAG, "RuntimeException: " + e);
}
}
}
}
return null;
}
I hope it will be useful for you :)
import android.os.Environment;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
public class MemoryStorage {
private MemoryStorage() {}
public static final String SD_CARD = "sdCard";
public static final String EXTERNAL_SD_CARD = "externalSdCard";
/**
* #return True if the external storage is available. False otherwise.
*/
public static boolean isAvailable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
return true;
}
return false;
}
public static String getSdCardPath() {
return Environment.getExternalStorageDirectory().getPath() + "/";
}
/**
* #return True if the external storage is writable. False otherwise.
*/
public static boolean isWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
/**
* #return A map of all storage locations available
*/
public static Map<String, File> getAllStorageLocations() {
Map<String, File> map = new HashMap<String, File>(10);
List<String> mMounts = new ArrayList<String>(10);
List<String> mVold = new ArrayList<String>(10);
mMounts.add("/mnt/sdcard");
mVold.add("/mnt/sdcard");
try {
File mountFile = new File("/proc/mounts");
if (mountFile.exists()) {
Scanner scanner = new Scanner(mountFile);
while (scanner.hasNext()) {
String line = scanner.nextLine();
if (line.startsWith("/dev/block/vold/")) {
String[] lineElements = line.split(" ");
String element = lineElements[1];
// don't add the default mount path
// it's already in the list.
if (!element.equals("/mnt/sdcard"))
mMounts.add(element);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
try {
File voldFile = new File("/system/etc/vold.fstab");
if (voldFile.exists()) {
Scanner scanner = new Scanner(voldFile);
while (scanner.hasNext()) {
String line = scanner.nextLine();
if (line.startsWith("dev_mount")) {
String[] lineElements = line.split(" ");
String element = lineElements[2];
if (element.contains(":"))
element = element.substring(0, element.indexOf(":"));
if (!element.equals("/mnt/sdcard"))
mVold.add(element);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
for (int i = 0; i < mMounts.size(); i++) {
String mount = mMounts.get(i);
if (!mVold.contains(mount))
mMounts.remove(i--);
}
mVold.clear();
List<String> mountHash = new ArrayList<String>(10);
for (String mount : mMounts) {
File root = new File(mount);
if (root.exists() && root.isDirectory() && root.canWrite()) {
File[] list = root.listFiles();
String hash = "[";
if (list != null) {
for (File f : list) {
hash += f.getName().hashCode() + ":" + f.length() + ", ";
}
}
hash += "]";
if (!mountHash.contains(hash)) {
String key = SD_CARD + "_" + map.size();
if (map.size() == 0) {
key = SD_CARD;
} else if (map.size() == 1) {
key = EXTERNAL_SD_CARD;
}
mountHash.add(hash);
map.put(key, root);
}
}
}
mMounts.clear();
if (map.isEmpty()) {
map.put(SD_CARD, Environment.getExternalStorageDirectory());
}
return map;
}
}
I just figured out something. At least for my Android Emulator, I had the SD Card Path like ' /storage/????-???? ' where every ? is a capital letter or a digit.
So, if /storage/ directory has a directory which is readable and that is not the internal storage directory, it must be the SD Card.
My code worked on my android emulator!
String removableStoragePath;
File fileList[] = new File("/storage/").listFiles();
for (File file : fileList)
{ if(!file.getAbsolutePath().equalsIgnoreCase(Environment.getExternalStorageDirectory().getAbsolutePath()) && file.isDirectory() && file.canRead())
removableStoragePath = file.getAbsolutePath(); }
//If there is an SD Card, removableStoragePath will have it's path. If there isn't it will be an empty string.
If there is an SD Card, removableStoragePath will have it's path. If there isn't it will be an empty string.
I have got solution on this after 4 days, Please note following points while giving path to File class in Android(Java):
Use path for internal storage String
path="/storage/sdcard0/myfile.txt";
use path for external storage
path="/storage/sdcard1/myfile.txt";
mention permissions in Manifest file.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
First check file length for confirmation.
Check paths in ES File Explorer regarding sdcard0 & sdcard1 is
this same or else...
e.g.:
File file = new File(path);
long = file.length();//in Bytes
I have some folders with HTML files in the "assets" folder in my Android project. I need to show these HTML files from assets' sub-folders in a list. I already wrote some code about making this list.
lv1 = (ListView) findViewById(R.id.listView);
// Insert array in ListView
// In the next row I need to insert an array of strings of file names
// so please, tell me, how to get this array
lv1.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, filel));
lv1.setTextFilterEnabled(true);
// onclick items in ListView:
lv1.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> a, View v, int position, long id) {
//Clicked item position
String itemname = new Integer(position).toString();
Intent intent = new Intent();
intent.setClass(DrugList.this, Web.class);
Bundle b = new Bundle();
//I don't know what it's doing here
b.putString("defStrID", itemname);
intent.putExtras(b);
//start Intent
startActivity(intent);
}
});
private boolean listAssetFiles(String path) {
String [] list;
try {
list = getAssets().list(path);
if (list.length > 0) {
// This is a folder
for (String file : list) {
if (!listAssetFiles(path + "/" + file))
return false;
else {
// This is a file
// TODO: add file name to an array list
}
}
}
} catch (IOException e) {
return false;
}
return true;
}
Call the listAssetFiles with the root folder name of your asset folder.
listAssetFiles("root_folder_name_in_assets");
If the root folder is the asset folder then call it with
listAssetFiles("");
try this it will work in your case
f = getAssets().list("");
for(String f1 : f){
Log.v("names",f1);
}
The above snippet will show the contents of the asset root.
For example... if below is the asset structure..
assets
|__Dir1
|__Dir2
|__File1
Snippet's output will be ....
Dir1 Dir2 File1
If you need the contents of the Directory Dir1
Pass the name of Directory in the list function.
f = getAssets().list("Dir1");
Hope This Help:
following code will copy all the folder and it's content and content of sub folder to sdcard location:
private void getAssetAppFolder(String dir) throws Exception{
{
File f = new File(sdcardLocation + "/" + dir);
if (!f.exists() || !f.isDirectory())
f.mkdirs();
}
AssetManager am=getAssets();
String [] aplist=am.list(dir);
for(String strf:aplist){
try{
InputStream is=am.open(dir+"/"+strf);
copyToDisk(dir,strf,is);
}catch(Exception ex){
getAssetAppFolder(dir+"/"+strf);
}
}
}
public void copyToDisk(String dir,String name,InputStream is) throws IOException{
int size;
byte[] buffer = new byte[2048];
FileOutputStream fout = new FileOutputStream(sdcardLocation +"/"+dir+"/" +name);
BufferedOutputStream bufferOut = new BufferedOutputStream(fout, buffer.length);
while ((size = is.read(buffer, 0, buffer.length)) != -1) {
bufferOut.write(buffer, 0, size);
}
bufferOut.flush();
bufferOut.close();
is.close();
fout.close();
}
Here is a solution to my problem that I found out working 100% listing all directories and files even sub-directories and files in subdirectories.
Note: In my case
Filenames had a . in them. i.e. .htm .txt etc
Directorynames did not have any . in them.
listAssetFiles2(path); // <<-- Call function where required
//function to list files and directories
public void listAssetFiles2 (String path){
String [] list;
try {
list = getAssets().list(path);
if(list.length > 0){
for(String file : list){
System.out.println("File path = "+file);
if(file.indexOf(".") < 0) { // <<-- check if filename has a . then it is a file - hopefully directory names dont have .
System.out.println("This is a folder = "+path+"/"+file);
listAssetFiles2(file); // <<-- To get subdirectory files and directories list and check
}else{
System.out.println("This is a file = "+path+"/"+file);
}
}
}else{
System.out.println("Failed Path = "+path);
System.out.println("Check path again.");
}
}catch(IOException e){
e.printStackTrace();
}
}//now completed
Thanks
i think that this is best that check file is dir or not, altarnative try,catch!
public static List<String> listAssetFiles(Context c,String rootPath) {
List<String> files =new ArrayList<>();
try {
String [] Paths = c.getAssets().list(rootPath);
if (Paths.length > 0) {
// This is a folder
for (String file : Paths) {
String path = rootPath + "/" + file;
if (new File(path).isDirectory())
files.addAll(listAssetFiles(c,path));
else files.add(path);
}
}
} catch (IOException e) {
e.printStackTrace();
}
return files;
}
Based on the #Kammaar answer. This kotlin code scans the file tree for the leafs:
private fun listAssetFiles(path: String, context: Context): List<String> {
val result = ArrayList<String>()
context.assets.list(path).forEach { file ->
val innerFiles = listAssetFiles("$path/$file", context)
if (!innerFiles.isEmpty()) {
result.addAll(innerFiles)
} else {
// it can be an empty folder or file you don't like, you can check it here
result.add("$path/$file")
}
}
return result
}
This method return file names in a directory in Assets folder
private fun getListOfFilesFromAsset(path: String, context: Context): ArrayList<String> {
val listOfAudioFiles = ArrayList<String>()
context.assets.list(path)?.forEach { file ->
val innerFiles = getListOfFilesFromAsset("$path/$file", context)
if (innerFiles.isNotEmpty()) {
listOfAudioFiles.addAll(innerFiles)
} else {
// it can be an empty folder or file you don't like, you can check it here
listOfAudioFiles.add("$path/$file")
}
}
return listOfAudioFiles
}
For example you want to load music file path from sound folder
You can fetch all sound like this:
private const val SOUND_DIRECTORY = "sound"
fun fetchSongsFromAssets(context: Context): ArrayList<String> {
return getListOfFilesFromAsset(SOUND_DIRECTORY, context)
}
public static String[] getDirectoryFilesRecursive(String path)
{
ArrayList<String> result = new ArrayList<String>();
try
{
String[] files = Storage.AssetMgr.list(path);
for(String file : files)
{
String filename = path + (path.isEmpty() ? "" : "/") + file;
String[] tmp = Storage.AssetMgr.list(filename);
if(tmp.length!=0) {
result.addAll(Arrays.asList(getDirectoryFilesRecursive(filename)));
}
else {
result.add(filename);
}
}
}
catch (IOException e)
{
Native.err("Failed to get asset file list: " + e);
}
Object[] objectList = result.toArray();
return Arrays.copyOf(objectList,objectList.length,String[].class);
}