My device has two ports USB, on one I have connected and read the name (this is GPS) and on the second port I connected a USB storage device and I want to read a file which is on it. Only on one of the device's storage I cannot perform a read like this:
Map<String, File> externalLocations = ExternalStorage.getAllStorageLocations();
File externalSdCard = externalLocations.get(ExternalStorage.EXTERNAL_SD_CARD);
if (externalSdCard != null && externalSdCard.exists() && externalSdCard.listFiles() != null) {
for (File f : externalSdCard.listFiles()) {
if ("key.xml".equalsIgnoreCase(f.getName())) {
String path = f.getPath().replace(".xml", "_DUMP.xml");
File file11 = new File(path);
if (!file11.exists()) {
moveFile(file11, f);
}
return f;
}
}
}
And I think I should do this to read a file :
UsbManager usbManager = ((UsbManager)(GetSystemService(Context.UsbService)));
var deviceList = usbManager.DeviceList;
IEnumerable<UsbDevice> deviceIterator = deviceList.Values.AsEnumerable();
if ((deviceIterator.Count() > 0)) {
UsbDevice device = deviceIterator.ElementAt(0);
usbManager.RequestPermission(device, mPermissionIntent);
if (usbManager.HasPermission(device)) {
if (usbManager.HasPermission(device)) {
System.Diagnostics.Debug.WriteLine("HasPermission");
UsbDeviceConnection connection = usbManager.OpenDevice(device);
if ((connection != null)) {
System.Diagnostics.Debug.WriteLine(" connection is not null");
var model = device.DeviceName;
string inline = null;
BufferedReader reader = null;
reader = new BufferedReader(new FileReader("/mnt/media_rw/C227-875D/test/hello.txt"));
System.Diagnostics.Debug.WriteLine("no exception occured");
while ((reader.ReadLine() != null)) {
System.Diagnostics.Debug.WriteLine(inlne);
}
}
}
But can I have open two ports at the same time?
Related
I want to get the list of all Storage Devices which are connected to the Android device.
For eg- Internal Storage(Storage in which all the folders such as Downloads, DCIM etc are present), SD Card and OTG device.
I Know there are a lot of StackOverflow posts which discuss this topic but none of them could serve my purpose as stated above.
I am able to get the Internal Storage by calling Environment.getExternalStorageDirectory().getPath() which return the path to the Internal Storage.
Any help on this would be really grateful as there is no standard AFAIK using which the list of all the connected Storage devices can be retrieved.
Also, many solutions do not work on different devices and Android version.
You can create one class EnvironmentSDCardCheck
package com.example.storagecheck;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Environment;
import android.os.storage.StorageManager;
import android.support.v4.content.ContextCompat;
import android.support.v4.os.EnvironmentCompat;
import android.util.Log;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
public class EnvironmentSDCardCheck {
private static final String TAG = "EnvironmentSDCardCheck";
public final static String TYPE_PRIMARY = "primär";
public final static String TYPE_INTERNAL = "intern";
public final static String TYPE_SD = "MicroSD";
public final static String TYPE_USB = "USB";
public final static String TYPE_UNKNOWN = "unbekannt";
public final static String WRITE_NONE = "none";
public final static String WRITE_READONLY = "readonly";
public final static String WRITE_APPONLY = "apponly";
public final static String WRITE_FULL = "readwrite";
private static Device[] devices, externalstorage, storage;
private static BroadcastReceiver receiver;
private static boolean useReceiver = true;
private static String userDir;
public static Device[] getDevices(Context context) {
if (devices == null) initDevices(context);
return devices;
}
public static Device[] getExternalStorage(Context context) {
if (devices == null) initDevices(context);
return externalstorage;
}
public static Device[] getStorage(Context context) {
if (devices == null) initDevices(context);
return storage;
}
public static IntentFilter getRescanIntentFilter() {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_MEDIA_BAD_REMOVAL);
filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
filter.addAction(Intent.ACTION_MEDIA_REMOVED);
filter.addAction(Intent.ACTION_MEDIA_SHARED);
filter.addDataScheme("file");
return filter;
}
public static void setUseReceiver(Context context, boolean use) {
if (use && receiver == null) {
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "Storage " + intent.getAction() + "-" + intent.getData());
initDevices(context);
}
};
context.registerReceiver(receiver, getRescanIntentFilter());
} else if (!use && receiver != null) {
context.unregisterReceiver(receiver);
receiver = null;
}
useReceiver = use;
}
public static void initDevices(Context context) {
if (userDir == null) userDir = "/Android/data/" + context.getPackageName();
setUseReceiver(context, useReceiver);
StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
Class c = sm.getClass();
Object[] vols;
try {
Method m = c.getMethod("getVolumeList", null);
vols = (Object[]) m.invoke(sm, null); // android.os.Storage.StorageVolume
Device[] temp = new Device[vols.length];
for (int i = 0; i < vols.length; i++) temp[i] = new Device(vols[i]);
Device primary = null;
for (Device d : temp) if (d.mPrimary) primary = d;
if (primary == null) for (Device d : temp)
if (!d.mRemovable) {
d.mPrimary = true;
primary = d;
break;
}
if (primary == null) {
primary = temp[0];
primary.mPrimary = true;
}
File[] files = ContextCompat.getExternalFilesDirs(context, null);
File[] caches = ContextCompat.getExternalCacheDirs(context);
for (Device d : temp) {
if (files != null) for (File f : files)
if (f != null && f.getAbsolutePath().startsWith(d.getAbsolutePath()))
d.mFiles = f;
if (caches != null) for (File f : caches)
if (f != null && f.getAbsolutePath().startsWith(d.getAbsolutePath()))
d.mCache = f;
}
ArrayList<Device> tempDev = new ArrayList<Device>(10);
ArrayList<Device> tempStor = new ArrayList<Device>(10);
ArrayList<Device> tempExt = new ArrayList<Device>(10);
for (Device d : temp) {
tempDev.add(d);
if (d.isAvailable()) {
tempExt.add(d);
tempStor.add(d);
}
}
Device internal = new Device(context);
tempStor.add(0, internal); // bei Storage-Alternativen immer
if (!primary.mEmulated) tempDev.add(0, internal); // bei Devices nur wenn zusätzlich
devices = tempDev.toArray(new Device[tempDev.size()]);
storage = tempStor.toArray(new Device[tempStor.size()]);
externalstorage = tempExt.toArray(new Device[tempExt.size()]);
} catch (Exception e) {
// Fallback auf normale Android-Funktionen
}
}
public static class Device extends File {
String mUserLabel, mUuid, mState, mWriteState, mType;
boolean mPrimary, mRemovable, mEmulated, mAllowMassStorage;
long mMaxFileSize;
File mFiles, mCache;
Device(Context context) {
super(Environment.getDataDirectory().getAbsolutePath());
mState = Environment.MEDIA_MOUNTED;
mFiles = context.getFilesDir();
mCache = context.getCacheDir();
mType = TYPE_INTERNAL;
mWriteState = WRITE_APPONLY;
}
#SuppressWarnings("NullArgumentToVariableArgMethod")
Device(Object storage) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
super((String) storage.getClass().getMethod("getPath", null).invoke(storage, null));
for (Method m : storage.getClass().getMethods()) {
if (m.getName().equals("getUserLabel") && m.getParameterTypes().length == 0 && m.getReturnType() == String.class)
mUserLabel = (String) m.invoke(storage, null); // ab Android 4.4
if (m.getName().equals("getUuid") && m.getParameterTypes().length == 0 && m.getReturnType() == String.class)
mUuid = (String) m.invoke(storage, null); // ab Android 4.4
if (m.getName().equals("getState") && m.getParameterTypes().length == 0 && m.getReturnType() == String.class)
mState = (String) m.invoke(storage, null); // ab Android 4.4
if (m.getName().equals("isRemovable") && m.getParameterTypes().length == 0 && m.getReturnType() == boolean.class)
mRemovable = (Boolean) m.invoke(storage, null); // ab Android 4.0
if (m.getName().equals("isPrimary") && m.getParameterTypes().length == 0 && m.getReturnType() == boolean.class)
mPrimary = (Boolean) m.invoke(storage, null); // ab Android 4.2
if (m.getName().equals("isEmulated") && m.getParameterTypes().length == 0 && m.getReturnType() == boolean.class)
mEmulated = (Boolean) m.invoke(storage, null); // ab Android 4.0
if (m.getName().equals("allowMassStorage") && m.getParameterTypes().length == 0 && m.getReturnType() == boolean.class)
mAllowMassStorage = (Boolean) m.invoke(storage, null); // ab Android 4.0
if (m.getName().equals("getMaxFileSize") && m.getParameterTypes().length == 0 && m.getReturnType() == long.class)
mMaxFileSize = (Long) m.invoke(storage, null); // ab Android 4.0
// getDescription (ab 4.1 mit context) liefert keine sinnvollen Werte
// getPathFile (ab 4.2) liefert keine sinnvollen Werte
// getMtpReserveSpace (ab 4.0) für diese Zwecke unwichtig
// getStorageId (ab 4.0) für diese Zwecke unwichtig
}
if (mState == null) mState = getState();
if (mPrimary)
mType = TYPE_PRIMARY;
else {
String n = getAbsolutePath().toLowerCase();
if (n.indexOf("sd") > 0)
mType = TYPE_SD;
else if (n.indexOf("usb") > 0)
mType = TYPE_USB;
else
mType = TYPE_UNKNOWN + " " + getAbsolutePath();
}
}
public String getType() {
return mType;
}
public String getAccess() {
if (mWriteState == null) {
try {
mWriteState = WRITE_NONE;
File[] root = listFiles();
if (root == null || root.length == 0)
throw new IOException("root empty/unreadable");
mWriteState = WRITE_READONLY;
File t = File.createTempFile("jow", null, getFilesDir());
//noinspection ResultOfMethodCallIgnored
t.delete();
mWriteState = WRITE_APPONLY;
t = File.createTempFile("jow", null, this);
//noinspection ResultOfMethodCallIgnored
t.delete();
mWriteState = WRITE_FULL;
} catch (IOException ignore) {
Log.v(TAG, "test " + getAbsolutePath() + " ->" + mWriteState + "<- " + ignore.getMessage());
}
}
return mWriteState;
}
public boolean isAvailable() {
String s = getState();
return (
Environment.MEDIA_MOUNTED.equals(s) ||
Environment.MEDIA_MOUNTED_READ_ONLY.equals(s)
);
// MEDIA_SHARED: als USB freigegeben; bitte Handy auf MTP umstellen
}
public String getState() {
if (mRemovable || mState == null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
// Android 5.0? Da gibts was neues
mState = Environment.getExternalStorageState(this);
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
// Android 4.4? Dann dort nachfragen
mState = Environment.getStorageState(this);
else if (canRead() && getTotalSpace() > 0)
// lesbar und Größe vorhanden => gibt es
mState = Environment.MEDIA_MOUNTED;
else if (mState == null || Environment.MEDIA_MOUNTED.equals(mState))
// nicht lesbar, keine Größe aber noch MOUNTED || oder ungesetzt => UNKNOWN
mState = EnvironmentCompat.MEDIA_UNKNOWN;
}
return mState;
}
public File getFilesDir() {
if (mFiles == null) {
mFiles = new File(this, userDir + "/files");
if (!mFiles.isDirectory())
//noinspection ResultOfMethodCallIgnored
mFiles.mkdirs();
}
return mFiles;
}
public File getCacheDir() {
if (mCache == null) {
mCache = new File(this, userDir + "/cache");
if (!mCache.isDirectory())
//noinspection ResultOfMethodCallIgnored
mCache.mkdirs();
}
return mCache;
}
public boolean isPrimary() {
return mPrimary;
}
public boolean isRemovable() {
return mRemovable;
}
public boolean isEmulated() {
return mEmulated;
}
public boolean isAllowMassStorage() {
return mAllowMassStorage;
}
public long getMaxFileSize() {
return mMaxFileSize;
}
public String getUserLabel() {
return mUserLabel;
}
public String getUuid() {
return mUuid;
}
}
}
and then you can use it to check sd card or Usb or unknown is presently connected or not with device
This way you can get the connected sd card, usb, etc.
private boolean checkSdCardPermission() {
boolean flag = false;
try {
EnvironmentSDCard.Device[] devices = EnvironmentSDCard.getExternalStorage(MainActivity.this);
for (EnvironmentSDCard.Device d : devices) {
if (d.getType().equals(EnvironmentSDCard.TYPE_SD) || d.getType().contains(EnvironmentSDCard.TYPE_UNKNOWN) || d.getType().contains(EnvironmentSDCard.TYPE_USB)) {
flag = d.isAvailable();
if (flag)
break;
}
}
} catch (Exception e) {
}
return flag;
}
I have had some luck with
ContextCompat.getExternalFilesDirs
This allows the application folders on external drives to be found. I haven't yet found a working better solution than this.
In my use case I am using Environment.DIRECTORY_MOVIES But if you need, there are other definitions, including the generic DIRECTORY_DOCUMENTS
Since API level 9 there is android.os.storage.StorageManager. Call getStorageVolumes() (available since API level 24) to get a list of storage volumes. As the doc puts it:
Return the list of shared/external storage volumes available to the current user. This includes both the primary shared storage device and any attached external volumes including SD cards and USB drives.
The result is List<StorageVolume>. Now, take a look at android.os.storage.StorageVolume:
Information about a shared/external storage volume for a specific user.
You can for example get a user-visible description of the volume by calling getDescription(). See createAccessIntent() how to get access.
This is an addition to #Sagar's answer about getting mounts from /proc. Note the use of /proc/self/mountinfo instead of /proc/mountinfo or /proc/mounts. You can read more about format of /proc/self/mountinfo in man 5 procfs. While the following code technically parses files, it is safe to run on the main thread (because /proc is in-memory filesystem).
private static final int SANE_SIZE_LIMIT = 200 * 1024 * 1024;
// some hashmap for mapping long values to objects
// personally I am using HPPC maps, the HashMap class is for simplicity
public final HashMap<String> mountMap = new HashMap<>();
public void parse() {
mountMap.clear();
CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder();
parseMounts(decoder, true);
}
private int measure(FileChannel fc) throws IOException {
final ByteBuffer buffer = ByteBuffer.allocate(1024 * 4);
int totalRead = 0, lastRead;
do {
buffer.clear();
lastRead = fc.read(buffer);
totalRead += lastRead;
if (totalRead > SANE_SIZE_LIMIT) {
throw new IOException("/proc/ file appears to be too big!!");
}
} while (lastRead != -1);
fc.position(0);
return totalRead;
}
private void parseMounts(CharsetDecoder d, boolean force) {
File file = new File("/proc/self/mountinfo");
int mode = ParcelFileDescriptor.MODE_READ_ONLY;
try (ParcelFileDescriptor pfd = ParcelFileDescriptor.open(file, mode));
FileChannel fc = new FileInputStream(pfd.getFileDescriptor()).getChannel()) {
// Measure size of file before reading from it.
// Virtual files in /proc/ appear to be zero-sized (because
// their contents are dynamic), but we want to attempt
// reading it in single read() call to avoid inconsistencies
final int totalRead = measure(fc);
try (FileInputStream fis = new FileInputStream(pfd.getFileDescriptor());
Reader r = Channels.newReader(fis.getChannel(), d, totalRead);
Scanner scanner = new Scanner(r)) {
while (scanner.hasNextLine()) {
scanner.nextInt();
scanner.nextInt();
final String[] mm = scanner.next().split(":");
final int major = Integer.parseInt(mm[0]);
final int minor = Integer.parseInt(mm[1]);
final long dev_t = makedev(major, minor);
final String source = scanner.next();
// ignore bind-mounts for now
if ("/".equals(source)) {
final String location = scanner.next();
// skip optional parts
scanner.skip("(.+ -)");
// type of file system (such as ext4)
// most useful filesystems can be distinguished by type
// but "fuse" is problematic (because most Android
// distributions implement dynamic permissions on
// external SD card via custom FUSE filesystem).
// To make matters worse, that SD card FUSE filesystem is
// often mounted in several places at once. The code below
// will throw away duplicate mounts by placing them in
// HashMap, keyed by uniqie filesystem type ID,
// but you can do it more cleverly be checking whether
// a mountpoint directory is accessible (via File#list).
// You can throw away rest of useless filesystems (such as
// /mnt/secure/asec) by permission checks and blacklisting
// well-known paths.
final String fsType = scanner.next().intern();
final String subject = scanner.next().intern();
String created = location + subject + fsType;
String prev = mountMap.put(dev_t, created);
if (prev != null) {
created.next = prev;
}
}
scanner.nextLine();
}
return;
} catch (NumberFormatException | NoSuchElementException nse) {
// oops.. either a new row type was introduced (not a big deal)
// or the file changed below our feet (because someone has mounted
// something). Let's retry once more
parseMounts(d, false);
} catch (IOException e) {
throw new WrappedIOException(e);
}
}
You can find more useful information (such as common path to useless filesystem), in this answer. Note, that formats of /proc/mounts and /proc/mountinfo are different, later was introduced after former to improve upon it's format without breaking backwards compatibility.
The code above is not golden bullet — it does not really tell you anything about individual filesystems, just their paths and filesystem name. You can be reasonable confident, that "vfat" and "ext4" are useful filesystems, and "procfs" is useless, but something like "fuse" is going to remain mysterious. You can augment output of code above by using android.os.storage.StorageManager to get more user-friendly filesystem names (like "SD Card") when they are available (match by mount paths). You can also use StatFs to obtain available free space on partition — useless virtual filesystems typically will return zero free space and zero available space when queried. Finally, if you are so inclined, you can consider filesystem mount options when deciding whether to show filesystem to user. E.g. ro vs rw, — read-only filesystem mounts typically will be a lot less useful for your users.
When I explain this method to people, they are often concerned with it's robustness… Will it work on some random junkphone? Will it remain available in future OS versions? Here is my take on it: this method is still better than many reflection-based advises, — in the worst case, reading from /proc/ file will return you IOException. It will not crash your app or result in unpredictable behavior like some reflection-based hacks.
/proc filesystem is official Linux API, maintained by Linux kernel developers. It is not possible to remove it by specifying different kernel build options (e.g. it is a mandatory part of OS kernel). It has been available for many years and retains better backwards compatibility than most Android APIs. In particular /proc/self/mountinfo was created over 10 years ago and will be available in most existing Android versions except most ancient.
Android developers do not officially support Linux-specific APIs. But they don't go out of their way to break them either. Some of recent SELinux changes in post-Lollipop Android have restricted access to some files in /proc/, — because they allowed applications to covertly spy on other applications. Those changes specifically kept /proc/self accessible, because /proc/self is designed to expose only applications own information (including information about file systems, available to the application).
If Google ever transitions from Linux to Fuchensa or some other homegrown BSD fork, the /proc/ and other Linux-specifc APIs will probably break. Do I care? Not really.
I'm using google API v3 for check exist folder. If folder does not exist, then create the new folder. This is my code for creating folder
private void createFolderInDrive() throws IOException {
boolean existed = checkExistedFolder("MyFolder");
if (existed = false) {
File fileMetadata = new File();
fileMetadata.setName("MyFolder");
fileMetadata.setMimeType("application/vnd.google-apps.folder");
File file = mService.files().create(fileMetadata)
.setFields("id")
.execute();
System.out.println("Folder ID: " + file.getId());
Log.e(this.toString(), "Folder Created with ID:" + file.getId());
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(),
"Folder is existed already", Toast.LENGTH_SHORT).show();
}
}
and here is the code for checking exist file
private boolean checkExistedFolder(String folderName) {
//File file = null;
boolean existedFolder = true;
// check if the folder exists already
try {
//String query = "mimeType='application/vnd.google-apps.folder' and trashed=false and title='" + "Evacuation Kit" + "'";
String query = "mimeType='application/vnd.google-apps.folder' and trashed=false and name='Evacuation Kit'";
// add parent param to the query if needed
//if (parentId != null) {
//query = query + " and '" + parentId + "' in parents";
// }
Drive.Files.List request = mService.files().list().setQ(query);
FileList fileList = request.execute();
if (fileList.getFiles().size() == 0 ) {
// file = fileList.getFiles().get(0);
existedFolder = false;
}
} catch (IOException e) {
e.printStackTrace();
}
return existedFolder;
fileList.getFiles().size() keep returning 3, even there is no folder on g drive. Can you guys tell me where am I doing wrong?
In the code you show, checkExistedFolder is always looking for the name "Evacuation Kit" and not using the argument folderName. Maybe this is the main reason you're always getting 3 from fileList.getFiles().size().
Also there's an assignment in if (existed = false), you should use if ( false == existed ) -using the static value in the left side of the comparison helps avoiding such mistakes-, or if (!existed). Note that it's important to check the nextPageToken when calling Files:list to check if there is more pages to look for the file. See more here https://developers.google.com/drive/api/v3/reference/files/list and Create folder if it does not exist in the Google Drive
This code will check if folder exist on drive. if exists, it will return id else create folder and returns id.
private DriveFile file;
GoogleApiClient mGoogleApiClient;
#Override
public void onConnected(#Nullable Bundle bundle) {
Log.e(TAG, "connected");
new Thread(new Runnable() {
#Override
public void run() {
DriveId Id = getFolder(Drive.DriveApi.getRootFolder(mGoogleApiClient).getDriveId(), "FOLDER_NAME");
Log.e(TAG, "run: " + Id);
}
}).start();
}
DriveId getFolder(DriveId parentId, String titl) {
DriveId dId = null;
if (parentId != null && titl != null) try {
ArrayList<Filter> fltrs = new ArrayList<>();
fltrs.add(Filters.in(SearchableField.PARENTS, parentId));
fltrs.add(Filters.eq(SearchableField.TITLE, titl));
fltrs.add(Filters.eq(SearchableField.MIME_TYPE, DriveFolder.MIME_TYPE));
Query qry = new Query.Builder().addFilter(Filters.and(fltrs)).build();
MetadataBuffer mdb = null;
DriveApi.MetadataBufferResult rslt = Drive.DriveApi.query(mGoogleApiClient, qry).await();
if (rslt.getStatus().isSuccess()) try {
mdb = rslt.getMetadataBuffer();
if (mdb.getCount() > 0)
dId = mdb.get(0).getDriveId();
} catch (Exception ignore) {
} finally {
if (mdb != null) mdb.close();
}
if (dId == null) {
MetadataChangeSet meta = new MetadataChangeSet.Builder().setTitle(titl).setMimeType(DriveFolder.MIME_TYPE).build();
DriveFolder.DriveFolderResult r1 = parentId.asDriveFolder().createFolder(mGoogleApiClient, meta).await();
DriveFolder dFld = (r1 != null) && r1.getStatus().isSuccess() ? r1.getDriveFolder() : null;
if (dFld != null) {
DriveResource.MetadataResult r2 = dFld.getMetadata(mGoogleApiClient).await();
if ((r2 != null) && r2.getStatus().isSuccess()) {
dId = r2.getMetadata().getDriveId();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return dId;
}
The code working for me with updated API on Kotlin:
override fun createFolder(name: String): Task<GoogleDriveFileHolder> {
check(googleDriveService != null) { "You have to init Google Drive Service first!" }
check(search(name, FOLDER_MIME_TYPE).not()){"folder already exist"}
return Tasks.call<GoogleDriveFileHolder>(
mExecutor,
Callable<GoogleDriveFileHolder> {
val metadata = File()
.setMimeType(FOLDER_MIME_TYPE)
.setName(name)
GoogleDriveFileHolder(
googleDriveService!!.files()
.create(metadata)
.setFields("id")
.execute() ?: throw IOException("Null result when requesting file creation.")
)
})
}
private fun search(name: String, mimeType:String): Boolean {
var pageToken: String? = null
do {
val result: FileList =
googleDriveService!!
.files()
.list()
.setQ("mimeType='$FOLDER_MIME_TYPE'")
.setSpaces("drive")
.setFields("nextPageToken, files(id, name)")
.setPageToken(pageToken)
.execute()
for (file in result.files) {
Log.d(TAG_UPLOAD_FILE , "Found file: %s (%s)\n ${file.name}, ${file.id} ")
if (name == file.name) return true
}
pageToken = result.nextPageToken
} while (pageToken != null)
return false
}
private const val FOLDER_MIME_TYPE= "application/vnd.google-apps.folder"
I am not able get root path usb otg in Android Nougat working fine till marshmallow. even able to get root path of sd card .can any body help me out from this i am frustrated from couple days.
Here is my code that return root path upto marshmallow and nougat sdcard. but not usb otg
public static String FileSystem() {
String path = null;
String SD_CARD_DIR = null;
try {
Process mount = Runtime.getRuntime().exec("mount");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(mount.getInputStream()));
mount.waitFor();
// String extPath = Environment.getExternalStorageDirectory().getPath();
// String isMedai = Environment.getExternalStorageState();
// if(Environment.MEDIA_MOUNTED.equalsIgnoreCase(isMedai)){
// String root = Environment.getRootDirectory().getPath();
// path = Environment.getExternalStoragePublicDirectory(DIRECTORY_EDUCOMP).getPath();
// }
String line;
String strFileSystem = null;
while ((line = bufferedReader.readLine()) != null) {
String[] split = line.split("\\s+");
for (int i = 0; i < split.length - 1; i++) {
if (SD_CARD_DIR == null) {
File mainroot = new File(split[i]);
File f[] = mainroot.listFiles(new FilenameFilter() {
#Override
public boolean accept(File dir, String name) {
return new File(dir, name).isDirectory();
}
}); // Get First level folders /mnt
if (f != null) {
for (File aFile : f) {
File[] filenames = aFile.listFiles(); // Get second level
// folders
// /mnt/sdcard so on
// and math Educomp
// folder
if (filenames != null) {
for (File ff : filenames) {
String eduFileName = ff.getName();
if (eduFileName.equals("Temp")) {
File[] listEducompfile = ff.listFiles();
if (listEducompfile != null) {
for (File fff : listEducompfile) {
String contentFileName = fff.getName();
if (contentFileName.equals("ts")) {
SD_CARD_DIR = aFile
.getAbsolutePath() + "/";
break;
}
}
}
} else {
File[] filenamesList = ff.listFiles(new FilenameFilter() {
#Override
public boolean accept(File dir, String name) {
return new File(dir, name).isDirectory();
}
});
if (filenamesList != null) {
for (File fff : filenamesList) {
String eduFileNamess = fff.getName();
if (eduFileNamess.equals("Temp")) {
File[] listEducompfile = fff.listFiles();
if (listEducompfile != null) {
for (File fffds : listEducompfile) {
String contentFileName = fffds.getName();
if (contentFileName.equals("ts")) {
return SD_CARD_DIR = ff + "/";
}
}
}
}
}
}
}
}
}
}
}
}
// SD_CARD_DIR = DEFAULT_SD_CARD_DIR;
}
return SD_CARD_DIR;
}
return path;
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
File dir = new File ("/");
File files = dir.listFiles();
You will not get a listing in Nougat for the root directory. You could have told us that.
`files==null` or files.length()==0
Nougat does not allow listing root. There are several other directories too that you cannot list anymore under Nougat.
You can check this approach on Nougat. But there is no way to make difference between removable SD card and USB flash if they are both connected to your device simultaneously.
Your approach - parsing mount file - does not work for some (chineese?) devices because string entry for internal memory may be completely the same as for removable SD card.
P.S. It is a user responsibility to find out where is USB flash or removable SD card in a "well" designed app. You should not do that by himself because Android does not provide public API for this purpose except Intent.ACTION_OPEN_DOCUMENT_TREE to call a built-in file chooser to interact with user in order to choose folder.
P.P.S INTERACTION WITH USER:
Create button with name "Show USB OTG Root" and onClick method containing
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
intent.putExtra("android.content.extra.SHOW_ADVANCED", true);//http://stackoverflow.com/questions/28605278/android-5-sd-card-label
startActivityForResult(intent, REQUEST_CODE_USB_ACCESS);
In onActivityResult callback you have to catch user answer when he choose USB OTG root in internal Android chooser:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CODE_USB_ACCESS:
if (data.getData() != null) {
int takeFlags = data.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
getContentResolver().takePersistableUriPermission(data.getData(), takeFlags);
DocumentFile documentFile = DocumentFile.fromTreeUri(this, data.getData());
}
}
}
documentFile is an access object representing USB OTG root (if user did not make mistake when choosing). You can make some file operation like documentFile.listFiles() on it. There is no other way to operate with files on removable media in public API starting from Lollipop. I.e. your desired path to USB OTG can not be obtained as a string from some public API method.
I want to upload a file to an existing Google Drive folder.
I am using this how to upload an image from my android app to a specific folder on google drive to get the folder name but not sure how to implement it (smokybob's answer)
//Search by name and type folder
String qStr = "mimeType = 'application/vnd.google-apps.folder' and title = 'myFolder'";
//Get the list of Folders
FileList fList=service.files().list().setQ(qStr).execute();
//Check that the result is one folder
File folder;
if (fList.getItems().lenght==0){
folder=fList.getItems()[0];
}
//Create the insert request is as in the sample
File file = service.files().insert(body, mediaContent);
//set the parent
file.setParents(Arrays.asList(newParentReference().setId(folder.getFolderId())));
//execute the request
file.execute();
I am getting cannot resolve symbol errors for FileList, body, mediacontent.
I am getting cannot resolve method for .files, getitems(), setparents, newparentsreference, and execute.
Class:GetFile.java https://github.com/googledrive/android-demos/blob/master/src/com/google/android/gms/drive/sample/demo/CreateFileActivity.java
public class GetFile extends UploadDrive {
private static final String TAG = "CreateFileActivity";
#Override
public void onConnected(Bundle connectionHint) {
super.onConnected(connectionHint);
// create new contents resource
Drive.DriveApi.newDriveContents(getGoogleApiClient())
.setResultCallback(driveContentsCallback);
}
final private ResultCallback<DriveContentsResult> driveContentsCallback = new
ResultCallback<DriveContentsResult>() {
#Override
public void onResult(DriveContentsResult result) {
if (!result.getStatus().isSuccess()) {
showMessage("Error while trying to create new file contents");
return;
}
final DriveContents driveContents = result.getDriveContents();
// Perform I/O off the UI thread.
new Thread() {
#Override
public void run() {
// write content to DriveContents
OutputStream outputStream = driveContents.getOutputStream();
Writer writer = new OutputStreamWriter(outputStream);
try {
writer.write(MainActivity.driveText); //what is the problem?
writer.close();
} catch (IOException e) {
Log.e(TAG, e.getMessage());
}
MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
.setTitle("New file")
.setMimeType("text/plain")
.setStarred(true).build();
// create a file on root folder
Drive.DriveApi.getRootFolder(getGoogleApiClient())
.createFile(getGoogleApiClient(), changeSet, driveContents)
.setResultCallback(fileCallback);
}
}.start();
}
};
final private ResultCallback<DriveFileResult> fileCallback = new
ResultCallback<DriveFileResult>() {
#Override
public void onResult(DriveFileResult result) {
if (!result.getStatus().isSuccess()) {
showMessage("Error while trying to create the file");
return;
}
showMessage("Created a file with content: " + result.getDriveFile().getDriveId());
}
};
}
When a folder is created under GDAA, it produces a DriveId.
/**************************************************************************
* create file/folder in GOODrive
* #param prnId parent's ID, (null or "root") for root
* #param titl file name
* #param mime file mime type
* #param file file (with content) to create (optional, if null, create folder)
* #return file id / null on fail
*/
static String create(String prnId, String titl, String mime, java.io.File file) {
DriveId dId = null;
if (mGAC != null && mGAC.isConnected() && titl != null) try {
DriveFolder pFldr = (prnId == null || prnId.equalsIgnoreCase("root")) ?
Drive.DriveApi.getRootFolder(mGAC):
Drive.DriveApi.getFolder(mGAC, DriveId.decodeFromString(prnId));
if (pFldr == null) return null; //----------------->>>
MetadataChangeSet meta;
if (file != null) { // create file
if (mime != null) { // file must have mime
DriveContentsResult r1 = Drive.DriveApi.newDriveContents(mGAC).await();
if (r1 == null || !r1.getStatus().isSuccess()) return null; //-------->>>
meta = new MetadataChangeSet.Builder().setTitle(titl).setMimeType(mime).build();
DriveFileResult r2 = pFldr.createFile(mGAC, meta, r1.getDriveContents()).await();
DriveFile dFil = r2 != null && r2.getStatus().isSuccess() ? r2.getDriveFile() : null;
if (dFil == null) return null; //---------->>>
r1 = dFil.open(mGAC, DriveFile.MODE_WRITE_ONLY, null).await();
if ((r1 != null) && (r1.getStatus().isSuccess())) try {
Status stts = file2Cont(r1.getDriveContents(), file).commit(mGAC, meta).await();
if ((stts != null) && stts.isSuccess()) {
MetadataResult r3 = dFil.getMetadata(mGAC).await();
if (r3 != null && r3.getStatus().isSuccess()) {
dId = r3.getMetadata().getDriveId();
}
}
} catch (Exception e) {
UT.le(e);
}
}
} else {
meta = new MetadataChangeSet.Builder().setTitle(titl).setMimeType(UT.MIME_FLDR).build();
DriveFolderResult r1 = pFldr.createFolder(mGAC, meta).await();
DriveFolder dFld = (r1 != null) && r1.getStatus().isSuccess() ? r1.getDriveFolder() : null;
if (dFld != null) {
MetadataResult r2 = dFld.getMetadata(mGAC).await();
if ((r2 != null) && r2.getStatus().isSuccess()) {
dId = r2.getMetadata().getDriveId();
}
}
}
} catch (Exception e) { UT.le(e); }
return dId == null ? null : dId.encodeToString();
}
(must be run on non-UI thread)
This ID is used in subsequent calls as a "parent ID". If you have questions about unresolved methods, please refer to this GitHub project. BTW (as I mentioned before), it does everything you're trying to accomplish (creates folders, creates text files, reads contents back, deletes files/folders, ...)
Good Luck
I have created a sequence file out of directory and then given index according to groups I want so that I can create groups using that index. This groups are then given one by one to my customized java class which gives information based on the file present in the group.
My problem is that some time it runs perfectly but some time gives different errors like null pointer exception, data type of field not found.
The problem is may be due to size of group. Because I am creating folder based group and then do the fetches the information from that folder inside my customized jar.
So how can I resolve this issue?
Below is my java class code:
public class OperateDirectory extends EvalFunc<DataBag>{
public TupleFactory tupleFactory = TupleFactory.getInstance();
public BagFactory bagFactory = BagFactory.getInstance();
public DataBag exec(Tuple input) throws IOException{
ArrayList<String> protoTuple = new ArrayList<>();
DataBag dataBag = bagFactory.newDefaultBag();
/* Create Directory */
if(input == null)
return dataBag;
if(input.size() != 2)
return dataBag;
long id = (long)input.get(0);
DataBag infoBag = (DataBag)input.get(1);
Iterator<Tuple> it = infoBag.iterator();
File dir = new File("/tmp/TestFolder"+id);
if(dir.exists())
{
FileUtils.cleanDirectory(dir);
}
else
{
dir.mkdir();
}
while(it.hasNext())
{
Tuple file_details = (Tuple)it.next();
if(file_details != null && file_details.size()==3)
{
String file_name = (String)file_details.get(1);
BytesWritable file_contents = (BytesWritable)file_details.get(2);
File f = new File(dir.getPath()+"/"+file_name);
f.deleteOnExit();
writeToFile(file_contents, f);
}
}
/* Perform operation here */
File f = new File("output"+id+".log");
ProcessBuilder performProcess1 = new ProcessBuilder("processes/processor", dir.getPath(),f.getPath());
Process process1 = performProcess1.start();
try
{
process1.waitFor();
if(f.exists() && f.length()>0)
{
ProcessBuilder performProcess2 = new ProcessBuilder("perl", "scripts/ParseFile.pl", f.getPath());
Process process2 = performProcess2.start();
InputStream is = process2.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null)
{
if(!line.isEmpty())
{
String [] tmpArray = line.split(",");
if(tmpArray.length == 2)
{
protoTuple.clear();
protoTuple.add(tmpArray[0]);
protoTuple.add(tmpArray[1]);
dataBag.add(tupleFactory.newTuple(protoTuple));
}
}
}
}
else
{
protoTuple.clear();
protoTuple.add("Error");
protoTuple.add("File "+f.getPath()+" does not exists ");
dataBag.add(tupleFactory.newTuple(protoTuple));
}
}
catch(Exception e)
{
protoTuple.clear();
protoTuple.add("Error ");
protoTuple.add(e.getMessage());
dataBag.add(tupleFactory.newTuple(protoTuple));
}
try
{
FileUtils.cleanDirectory(dir);
FileUtils.deleteDirectory(dir);
}
catch(Exception e)
{
}
return dataBag;
}
void writeToFile(BytesWritable value, File binaryFile) throws IOException{
FileOutputStream fileOut = new FileOutputStream(binaryFile);
fileOut.write(value.getBytes(), 0, value.getLength());
fileOut.close();
}
}