The file utils which i am using in my service class is not retrieving the files from its path,but when i am using the same in activity its performing as required.
so can anyone suggest me the correct answer for my question.
These are my programming lines which i have used.
public class MyService extends Service
{
IBinder mBinder;
private File root;
private ArrayList<File> fileList = new ArrayList<File>();
#Override
public void onCreate()
{
root = new File(Environment.getExternalStorageDirectory() + "/user/");
getfile(root);
for (int i = 0; i < fileList.size(); i++)
{
if (fileList.get(i).isDirectory()) {
File userPath = new File(fileList.get(i).getPath());
File[] uFiles = userPath.listFiles();
for (int k = 0; k < uFiles.length; k++) {
File f1 = new File(uFiles[k].toString());
String comFile = Environment.getExternalStorageDirectory() + "/Download/" + uFiles[k].getName();
// System.out.println(comFile);
// System.out.println(f1.getPath());
File f2 = new File(comFile);
try {
boolean compare1and2 = FileUtils.contentEquals(f1, f2);
// Toast.makeText(getApplicationContext(), "Are " + uFiles[k] + " and " + comFile + " the same? " + compare1and2, Toast.LENGTH_SHORT).show();
if (!compare1and2) {
File f4 = new File(Environment.getExternalStorageDirectory() + "/upload/" + uFiles[k].getName());
File f3 = new File(comFile);
FileUtils.copyFile(f3, f4);
f1.delete();
Toast.makeText(getApplicationContext(), "File uploaded" , Toast.LENGTH_SHORT).show();
System.out.println("file uploaded");
} else {
f1.delete();
}
} catch (IOException e) {
e.printStackTrace();
}
}
fileList.get(i).delete();
}
}
}
public ArrayList<File> getfile (File dir)
{
Log.e("logger", dir.toString());
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(".png")
|| listFile[i].getName().endsWith(".jpg")
|| listFile[i].getName().endsWith(".jpeg")
|| listFile[i].getName().endsWith(".gif"))
{
fileList.add(listFile[i]);
}
}
}
}
return fileList;
}
public IBinder onBind(Intent intent)
{
Toast.makeText(getApplicationContext()," onbind", Toast.LENGTH_SHORT).show();
return mBinder;
}
}
Null Pointer Exception
This is a generic issue as the instance of the class is not initiated, you are getting this error.
when you are using third party library and you are not sure how it may behave with certain methods, you should always check if the given instance generated by that method is null or not, before taking any action on that reference variable as that method may have returned null
In your code put conditions like this
if(object != null){
// now you can call methods on this reference variable as it is not null
}else{
// forget it, the reference variable, does not hold address to any object, if you try anything with this, VM will complain with Null Pointer Exception
}
I would recommend you to check this variables as following
root, listFile[], uFiles, f1, f2, f3, f4,
pay attention as you may consider some directories have sub-directories but that not always the case, so you have to check that listFiles() is indeed returns the array of files otherwise you have to deal with more bugs in the code
Related
I've been bringing up the list of files in the folder as below, but I can't use the method below in Android Q(Android 10) or higher.
How do I load a list of files in the MUSIC folder using MediaStore?
public void getFileListInFolder() {
String path = Environment.getExternalStoragePublicDirectory(DIRECTORY_MUSIC);
File directory = null;
try {
directory = new File(path);
Log.i("debug","dir = " + directory);
}
catch (Exception e)
{
Log.i("debug","Uri e = " + e);
}
File[] files = directory.listFiles(new FileFilter() {
#Override
public boolean accept(File pathname) {
return pathname.isFile();
}
});
if(files != null)
{
for (int i = 0; i < files.length; i++) {
Log.i("debug", "FileName:" + files[i].getName());
}
}
}
getExternalStoragePublicDirectory is deprecated since Android Q
To improve user privacy, direct access to shared/external
storage devices is deprecated. When an app targets
{#link android.os.Build.VERSION_CODES#Q}, the path returned
from this method is no longer directly accessible to apps.
Apps can continue to access content stored on shared/external
storage by migrating to alternatives such as
{#link Context#getExternalFilesDir(String)},
{#link MediaStore}, or {#link Intent#ACTION_OPEN_DOCUMENT}.
That means could not read/write file of /storage/emulated/0/Music directly,
but could read/write file under /storage/emulated/0/Android/data/com.youapp/files/Music
public void getFileListInFolder() {
String path = getExternalFilesDir(DIRECTORY_MUSIC).getAbsolutePath();
Log.d(TAG, "getFileListInFolder:path " + path);
File directory = null;
try {
directory = new File(path);
Log.i(TAG,"dir = " + directory);
}
catch (Exception e)
{
Log.i(TAG,"Uri e = " + e);
}
File[] files = directory.listFiles();
Log.i(TAG, "getFileListInFolder:files " + files);
for (File f:
files) {
Log.d(TAG, "getFileListInFolder: " + f.getName());
}
if(files != null)
{
for (int i = 0; i < files.length; i++) {
Log.i(TAG, "FileName:" + files[i].getName());
}
}
}
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 am now building an file sharing app in android and i have tried to get all the files on a certain directory (in my case it is the mp3 directory). while I was doing it using the function File.listFiles() it was returning null for no reason that I know of.
directorys = new File(Environment.getExternalStorageDirectory().toString()+"/mp3");
Log.d(TAG,directorys.listFiles().length+"");
after it an exception has be given for that listFiles is an null array?
btw I have used this permission
<uses-permission- android:name="android.permission.READ_EXTERNAL_STORAGE"/>
try this code
String path = Environment.getExternalStorageDirectory().toString()+"/mp3";
Log.d("Files", "Path: " + path);
File directory = new File(path);
File[] files = directory.listFiles();
Log.d("Files", "Size: "+ files.length);
for (int i = 0; i < files.length; i++)
{
Log.d("Files", "FileName:" + files[i].getName());
}
and from marshmallow and above version you need to add permission programaticaly
public boolean requestForPermission() {
boolean isPermissionOn = true;
final int version = Build.VERSION.SDK_INT;
if (version >= 23) {
if (!canAccessExternalSd()) {
isPermissionOn = false;
requestPermissions(EXTERNAL_PERMS, EXTERNAL_REQUEST);
}
}
return isPermissionOn; }
public boolean canAccessExternalSd() {
return (hasPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)); }
private boolean hasPermission(String perm) {
return (PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(this, perm));
}
I want my App to list all directories and files on my FTP-Server. This is the code from How to list ftp directories with android?:
FTPFile[] files = null;
files = ftpClient.listDirectories();
String path = null;
for (int i = 0; i < files.length; i++) {
path = files[0].getName();
Log.d("CONNECT", "Directories: "+ files[i].getName());
}
FTPFile[] files2 = ftpClient.listFiles(topPath);
for (int j = 0; j < files2.length; j++) {
Log.d("CONNECT", "Below " + files[j].getName()
+ " is " + files2[j].getName());
}
}
Now this works for only for the first two layers. How can I manage to get as deep as necessary so I can list files that in folders that are in folders that are in folders and so on?
Thanks in advance :)
Now what I tried (not quite) recursively:
{ ...
FTPFile[] files = ftpClient.listFiles();
listContent(files);
.... }
private void listContent(FTPFile[] file) throws IOException {
FTPFile[] list = ftpClient.listDirectories();
if (list != null) {
for (FTPFile f : list) {
if (f.isDirectory()) {
Log.d(TAG, "directory: " + f.getName());
} else {
Log.d(TAG, "file: " + f.getName());
}
}
listContent(list);
} else return;
}
This code lets me get just the first layer of directories, the FTPFile[] is overwritten in ever new cycle.
How can I do that?
UPDATE:
Here's my solution. This code walks the whole content of the host-adress. Thanks to all who helped me:
private void listContent(String s) throws IOException {
try {
FTPFile[] ftpFiles = ftpClient.listFiles(s);
int length = ftpFiles.length;
for (int i = 0; i < length; i++) {
String name = ftpFiles[i].getName();
boolean isFile = ftpFiles[i].isFile();
if (isFile) {
Log.i(TAG, "File : " + name);
}
} else {
Log.i(TAG, "Directory : " + name);
if (ftpChangeDirectory(name) == true) {
Log.d("ftpChangeDirectory", name);
String newDir = ftpGetCurrentWorkingDirectory();
Log.d(TAG, "new Dir: " + newDir);
listContent(newDir);
}
}
}
ftpChangeDirectory("..");
String test = ftpGetCurrentWorkingDirectory();
Log.d("dirUp", test);
} catch (Exception e) {
e.printStackTrace();
}
}
I can't test it but something like this should work :
private void listAllFiles(String path) // path is the top folder to start the search
{
FTPFile[] files = ftpClient.listFiles(path); // Search all the files in the current directory
for (int j = 0; j < files.length; j++) {
Log.d("CONNECT", "Files: " + files[j].getName()); // Print the name of each files
}
FTPFile[] directories = ftpClient.listDirectories(path); // Search all the directories in the current directory
for (int i = 0; i < directories.length; i++) {
String dirPath = directories[i].getName();
Log.d("CONNECT", "Directories: "+ dirPath); // Print the path of a sub-directory
listAllFiles(dirPath); // Call recursively the method to display the files in the sub-directory
}
}
Anyway, i strongly recommend that you understand the code and check this link to learn more about recursivity.
Hi friend thanks for previous replies,
i am facing problem in removing cache and temp files/folders,
what i require is to clean the whole device temp files and cache from one app which is mine app
but here i am able to clean only my apps cache , here is my code
private void mAppMethod(List<App> mApps) {
// TODO Auto-generated method stub
// File f = g
for (int i = 0; i < mApps.size(); i++) {
File dir = new File("/data/data/"+mApps.get(i).getPackageName().concat("/cache"));
Log.e("dir "+dir, "is directory "+dir.isDirectory());
int j = clearCacheFolder(dir, 10);
if (dir!= null && dir.isDirectory())
Log.e("j", "rff "+dir.delete());
System.out.println(j+" rff "+dir.delete());
}
and my clear cache method as under
static int clearCacheFolder(final File dir, final int numDays) {
int deletedFiles = 0;
if (dir!= null && dir.isDirectory()) {
// System.out.println("here"+dir.delete());
Log.e("here", "here "+dir.isDirectory());
try {
Log.e("here1", "here1"+dir.listFiles());
for (File child:dir.listFiles()) {
Log.e("here11", "here11");
//first delete subdirectories recursively
if (child.isDirectory()) {
Log.e("here111", "here111");
deletedFiles += clearCacheFolder(child, numDays);
Log.e("here1111", "here1111");
}
Log.e("here11111", "here11111");
//then delete the files and subdirectories in this dir
//only empty directories can be deleted, so subdirs have been done first
if (child.lastModified() < new Date().getTime() - numDays * DateUtils.DAY_IN_MILLIS) {
Log.e("here111111", "here111111");
if (child.delete()) {
Log.e("here1111111", "here1111111");
deletedFiles++;
Log.e("here11111111", "here11111111");
}
}
}
}
catch(Exception e) {
Log.e("TAG", String.format("Failed to clean the cache, error %s", e.getMessage()));
}
}
return deletedFiles;
}
please help how can i clear the whole device cache,here i am getting every apps cache location i.e. dir to cache of all apps in device but when i want to delete them it returns false
please help any help is appreciable
i am able to clear cache of one app which is the one i am running this code but not for other apps
thanks in advance
Try with this code
public void clearApplicationData() {
File cache = getCacheDir();
File appDir = new File(cache.getParent());
if(appDir.exists()){
String[] children = appDir.list();
for(String s : children){
if(!s.equals("lib")){
deleteDir(new File(appDir, s));
Log.i("TAG", "**************** File /data/data/APP_PACKAGE/" + s +" DELETED *******************");
}
}
}
}
public static boolean deleteDir(File dir) {
if (dir != null && dir.isDirectory()) {
String[] children = dir.list();
for (int i = 0; i < children.length; i++) {
boolean success = deleteDir(new File(dir, children[i]));
if (!success) {
return false;
}
}
}
return dir.delete();
}
This will delete your all data,and cache files in the application.