Finding a way to download course materials to android mobile - java

Is there any way to download google drive file to custom location? I am using this code to get the file,
courses.get(0).getCourseMaterialSets().get(0).getMaterials().get(0).getDriveFile()
This function is returning File type output. How to save it locally?
Or is there any way to download google drive files using classroom API?

I don't think there's a way to do this using Classroom API. To download files from Google Drive, check the download files tutorial using Android API for Drive.
Downloading a file
Preferred method: using alt=media
To download files, you make an authorized HTTP GET request to the
file's resource URL and include the query parameter alt=media. For
example:
GET https://www.googleapis.com/drive/v2/files/0B9jNhSvVjoIVM3dKcGRKRmVIOVU?alt=media
Authorization: Bearer
ya29.AHESVbXTUv5mHMo3RYfmS1YJonjzzdTOFZwvyOAUVhrs Downloading the file
requires the user to have at least read access. Additionally, your app
must be authorized with a scope that allows reading of file content.
For example, an app using the drive.readonly.metadata scope would not
be authorized to download the file contents. Users with edit
permission may restrict downloading by read-only users by setting the
restricted label to true.
Here's a snippet from the guide:
/**
* Download a file's content.
*
* #param service Drive API service instance.
* #param file Drive File instance.
* #return InputStream containing the file's content if successful,
* {#code null} otherwise.
*/
private static InputStream downloadFile(Drive service, File file) {
if (file.getDownloadUrl() != null && file.getDownloadUrl().length() > 0) {
try {
// uses alt=media query parameter to request content
return service.files().get(file.getId()).executeMediaAsInputStream();
} catch (IOException e) {
// An error occurred.
e.printStackTrace();
return null;
}
} else {
// The file doesn't have any content stored on Drive.
return null;
}
}

Related

Change file permissions in java

I want to convert the MultipartFile to File and upload this to specified directory on my ec2 instance. Here is the converter method.
private fun convertMultiPartFileToFile(multipartFile: MultipartFile, name: String): File? {
val file = multipartFile.originalFilename?.let { File(it) }
try {
log.info { file?.canWrite() } // logs 'false'
log.info { file?.canExecute() } // logs 'false'
file?.setExecutable(true) // still 'false'
file?.setWritable(true) // still 'false'
file.let {
if (file != null) {
FileOutputStream(file).use { outputStream -> outputStream.write(multipartFile.bytes) }
}
}
} catch (e: IOException) {
throw RuntimeException(e)
}
return file
}
It works locally, but when I try this on my ec2 instance, I got the error
java.lang.RuntimeException: java.io.FileNotFoundException: file.png (Permission denied)
I guess it's because I do not have permission to write to specified file. How can I solve this if file?.setWritable(file) and file?.setExecutable(true) return false.
I run the jar by java -jar path/to/jar
The setWritable method documentation says
* #return {#code true} if and only if the operation succeeded. The
* operation will fail if the user does not have permission to
* change the access permissions of this abstract pathname.
How to get the access permissions to this abstract pathname then?
MultipartFiles do not represent files on the file system while File represents a local file on your system. They are just data that's uploaded.
Hence, multipartFile.originalFilename does not give you the name of any file on your system (except a file with the same name "randomly" exists) but the name of the file the user uploaded (on their system).
If you want to access a MultipartFile as a File, you first need to save it as such:
val file=File("what/ever/file/you.want")//in the directory you want to upload it to
multipartFile.transferTo(file)
//it is now stored in file
This will copy the file to your system.

Creating Java config files

What exactly is the best way to generate config files for my Java application? Right now I have a runnable jar which when opened will open a file selector gui for the user to select where the config files along with saved data should be stored at. I have my default config file saved in my resource folder and I am wanting to save that file to the location specified. Anyways the problem I am having is that I am not sure how I will be able to refence back to those files in the future because I only want that file selector to pop up once. As soon as the application is closed all references to that file pathway would be lost. The only thing I can think of is that I could replace my config.yml file inside the resource folder with the newly generated file and include a file location parameter (if that is even possible). But to be honest I am not sure how programs actually handle this and would love any insight into this topic.
Perhaps place the selected path into a small text file located within the Startup directory of your JAR file. Encrypt it if you like or whatever. The method below should provide you with the Directory (folder) path of where your JAR file was started:
/**
* Returns the path from where the JAR file was started. In other words, the
* installed JAR file's home directory (folder).<br><br>
*
* <b>Example Usage:</b><pre>
* <code>String applicationPath = appPath(MyStartupClassName.class);</code></pre>
*
* #param mainStartupClassName (Class) The main startup class for your
* particular Java application. To be supplied
* as: <b>MyMainClass.class</b><br>
*
* #return (String) The full path to where the JAR file resides (its Home
* Directory).
*/
public static String appPath(Class<?> mainStartupClassName) {
try {
String path = mainStartupClassName.getProtectionDomain().getCodeSource().getLocation().getPath();
String pathDecoded = java.net.URLDecoder.decode(path, "UTF-8");
pathDecoded = pathDecoded.trim().replace("/", File.separator);
if (pathDecoded.startsWith(File.separator)) {
pathDecoded = pathDecoded.substring(1);
}
return pathDecoded.substring(0, pathDecoded.lastIndexOf(File.separator));
}
catch (java.io.UnsupportedEncodingException ex) {
java.util.logging.Logger.getLogger("appPath()")
.log(java.util.logging.Level.SEVERE, null, ex);
}
return null;
}

How to access file that has been transferred using Nearby Connections API with android 11, as file is stored in Nearby's scoped storage?

I am trying to transfer a file using googles Nearby Connections API. Largely I can get all components of the transfer to work so that all of the files data is transferred but the issue is that the files data is then stored in Nearby's scoped storage so I am unable to access it from my app to be able to process that data into the appropriate file type and then save and rename as necessary.
The current method I am using to try and process the payload is
private void processFilePayload(long payloadId) {
// BYTES and FILE could be received in any order, so we call when either the BYTES or the FILE
// payload is completely received. The file payload is considered complete only when both have
// been received.
Payload filePayload = completedFilePayloads.get(payloadId);
String filename = filePayloadFilenames.get(payloadId);
if (filePayload != null && filename != null) {
completedFilePayloads.remove(payloadId);
filePayloadFilenames.remove(payloadId);
// Get the received file (which will be in the Downloads folder)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
File fromPayload = filePayload.asFile().asJavaFile();
Uri uri = Uri.fromFile(fromPayload);
try {
// Copy the file to a new location.
InputStream in = getApplicationContext().getContentResolver().openInputStream(uri);
copyStream(in, new FileOutputStream(new File(getApplicationContext().getCacheDir(), filename)));
} catch (IOException e) {
// Log the error.
Log.e("copy file", e.toString());
} finally {
// Delete the original file.
getApplicationContext().getContentResolver().delete(uri, null, null);
}
} else {
File payloadFile = filePayload.asFile().asJavaFile();
// Rename the file.
payloadFile.renameTo(new File(payloadFile.getParentFile(), filename));
}
}
}
});
Because of android 11's scoped storage to be able to access the file the files Uri needs to be used to create an input stream with a content resolver to access the file.
According to the Nearby Documentation there should be a method Payload.File.asUri so I would be able to use the line Uri payloadUri = filePayload.asFile().asUri(); but this is not actually available in the API despite using the most recent version of Nearby.
As well as this the use of Payload.File.AsJavaFile() should be deprecated according to the google Nearby documentation
I have seen some other answers for similar problems where the suggestion is to use Media.Store but this is not possible as the file does not have any extension yet so doesn't show up as any particular file type.
Note: I have requested read/write external storage permissions both in the manifest and at runtime.
===Update===
Payload.asFile.asUri() is available in com.google.android.gms:play-services-nearby:18.0.0
============
Sorry about that. We'll be releasing an update soon with #asUri properly exposed.
In the meantime, if you target API 29, you can use requestLegacyExternalStorage=true as a workaround. (See more: https://developer.android.com/about/versions/11/privacy/storage)

How to write SQLite file via Room in external storage, by using upcoming Scoped storage?

One of our app requirements is that some SQLite file should be retained and backup, even the app is uninstalled.
We achieve such, by writing SQLite file via Room, into location Environment.getExternalStorageDirectory
RoomDatabase with customizable SQLite file path
#Database(
entities = {Backup.class},
version = 1
)
public abstract class LocalBackupNamedRoomDatabase extends RoomDatabase {
public abstract BackupDao backupDao();
public static LocalBackupNamedRoomDatabase newInstance(String dbName) {
LocalBackupNamedRoomDatabase INSTANCE = Room.databaseBuilder(
WeNoteApplication.instance(),
LocalBackupNamedRoomDatabase.class,
dbName
)
.build();
return INSTANCE;
}
}
Function returns Environment.getExternalStorageDirectory
public static String getBackupDirectory() {
if (backupDirectory == null) {
File _externalStorageDirectory = Environment.getExternalStorageDirectory();
if (_externalStorageDirectory == null) {
return null;
}
try {
backupDirectory = _externalStorageDirectory.getCanonicalPath();
} catch (IOException e) {
Log.e(TAG, "", e);
}
if (backupDirectory == null) {
return null;
}
backupDirectory = toEndWithFileSeperator(backupDirectory) + "com.yocto.wenote" + File.separator + "backup" + File.separator;
}
return backupDirectory;
}
How we save SQLite file via Room in external storage
LocalBackupNamedRoomDatabase.newInstance(
getBackupDirectory() + "local-backup"
).backupDao().insert(backup)
According to this, my understanding is that Environment.getExternalStorageDirectory might not be usable anymore (am I correct??).
My guess is that, in order to achieve the same behavior, I might need to use MediaStore.Downloads? But how?
Can anyone provide a concrete example for the above use case? Or, we are no longer possible to achieve such behavior, under Scoped storage?
From my own experiments with the Q beta 2 emulator, with a test app with targetSdkVersion 'Q':
Initially Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).exists() was false, which led me to believe you can't even access it in Q. Then I found mkdirs() worked, and I could then read and write to a sandboxed view of this folder restricted to my app's files only. This has the interesting side effect that multiple apps can write files with the same name to the 'download' folder, and that's how they show in the default files app on the emulator!
As the docs mention, you lose access to your own files after uninstall then reinstall. So, in order to restore a sqlite file from downloads after uninstall, you'd have to:
"allow the user to choose a file using the system's file picker app." (from docs)
This will give you a URI rather than a File. Because SQLiteDatabase can only read Files, you'll need to open the URI as a stream and write it to a real file somewhere you control, eg cache or internal storage.
This is a pain, but doable for most use cases. It gets tricky for very large database files, eg mapbox tiles which may be hundreds of mb or more, stored on an actual SD card because they won't fit on regular 'external' storage.
As stated here, the files located in your external storage will be removed upon uninstallation of your application. Hence, you might consider using getExternalStoragePublicDirectory function to store your files in the top level shared storage. If you want to store in the DOWNLOADS directory, you can use the following to get the directory path.
File path = Environment.getExternalStoragePublicDirectory(
Environment. DIRECTORY_DOWNLOADS);
Hope that helps.

File missing in Google Cloud Storage on AppEngine after following instructions

I wrote a file to Google Cloud Storage using the instructions given here:
https://developers.google.com/appengine/docs/java/googlestorage/overview
The code runs and executes successfully, however, after logging into my Storage account, I don't see the newly written file in my bucket.
Any ideas as to why?
So this is the export code:
This is the code I am using:
try {
// Get the file service
FileService fileService = FileServiceFactory.getFileService();
/**
* Set up properties of your new object
* After finalizing objects, they are accessible
* through Cloud Storage with the URL:
* http://storage.googleapis.com/my_bucket/my_object
*/
GSFileOptionsBuilder optionsBuilder = new GSFileOptionsBuilder()
.setBucket(bucket)
.setKey(key)
.setAcl("public-read");
// Create your object
AppEngineFile writableFile = fileService
.createNewGSFile(optionsBuilder.build());
// Open a channel for writing
boolean lockForWrite = false;
FileWriteChannel writeChannel = fileService.openWriteChannel(
writableFile, lockForWrite);
// For this example, we write to the object using the
// PrintWriter
PrintWriter out = new PrintWriter(Channels.newWriter(
writeChannel, "UTF8"));
Iterator<String> it = spRes.iterator();
while (it.hasNext()) {
out.println(it.next());
}
// Close without finalizing and save the file path for writing
// later
out.close();
String path = writableFile.getFullPath();
// Write more to the file in a separate request:
writableFile = new AppEngineFile(path);
// Lock the file because we intend to finalize it and
// no one else should be able to edit it
lockForWrite = true;
writeChannel = fileService.openWriteChannel(writableFile,
lockForWrite);
// Now finalize
writeChannel.closeFinally();
} catch (IOException e) {
result = "Failed to export";
e.printStackTrace();
}
I believe that you have not added the email of your application which you can find under Application Setting of your appengine application.
Then you need to add this email in the Team under Google API Console for Google Cloud Storage with is Owner privilege. Make sure you are also using the same bucket name which you created in Online Browser Tool for Cloud Storage in the UploadOptions.
Looks like I had 2 different projects setup in the Google Cloud Console. I was updating the wrong project.
Works now.
Thank you for your help.
As Ankur said, you have to deploy your code on appengine to write to Cloud Storage. Otherwise the files will only be stored on your local hard disk.

Categories

Resources