Work with Google Drive

davfla

Member
Licensed User
Longtime User
Hello,

I will show you my new library which make it easy to connect and work with Google Drive.

Bis jetzt beherrscht diese lib folgende Punkt :
  • Es verbindet sich automatisch mit Google Drive und behält diese Verbindung auch beim nächsten Start der App. Die Zugangsdaten inkl. generierter Token werden in einer Textdatei unter File.DirIntern gespeichert.
  • Hochladen einer Datei
  • Download einer Datei (FileID wird benötigt)
  • Suchen der FileID durch den Dateinamen
  • Metadaten der Datei auslesen
  • Monitoring einer Datei. Hierbei wird automatisch eine Datei mit Google Drive abgeglichen. Sollte die Drive Datei neuer sein, wird die lokale Datei, wenn gewünscht, überschrieben. Genauso umgekehrt. Beispiel dafür wäre eine Backupfunktion oder auch das nutzen einer Konfigurationsdatei/Datenbank zwischen zwei verschiedenen Geräten.
Diese Lib ist jedoch kein Tool, um Google Drive komplett zu verwalten. Es kann keine Dateien verschieben, kopieren oder löschen (Ich weiß auch nicht, ob das durch HTTP-Header möglich ist.)

Until this moment the library can :
  • Connect and reconnect automatically. The token will stored in a file on internal storage. The refresh of the access token the lib makes alone if needed.
  • Upload a file
  • Download a file (FileID is needed)
  • Find the FileID with filename. This function is not yet fully matured, because it's only possible to search for the filename. If two files with the same name on the drive storage, the first founded will be choosed.
  • Metatag of files (FileID is needed)
  • Monitoring of a file. This procedure automatically mirror a local file with a file on Google Drive. To example, the setting file on Google Drive was changed by an another app (i.e. from tablet version). This file will downloaded to the device with older version of this file. And upload in case of newer file, too.
This lib is not a completely administration tool for google drive, but you can for example storage a setting file for your application on Drive. So you can access from miscellaneous devices to this file. Or use it as a backup solution.

All what you need is your access key and the secret key from the google developer console :
https://console.developers.google.com/


Methods :

Initialize(CallbackModul, Eventname, ClientID, ClientSecret)

ConnectToDrive
Here is the start point. If the connection is successfully, the event Drive_Connected raised.
If no Network connection available the event Drive_NoInternetConnection raised.

UploadFile(Title, UploadDir, UploadFilename, FileID, FolderID) as String
With this function you can upload a file on drive. The param "title" is the name of the file in Google Drive. If you want the name is the same as the filename, then pass it with "".
UploadDir and UploadFilename is the path of the file on the local device.
If you upload the file the first time, you can pass the FileID with "". Else, if you want to update a file, you need this ID. Without this ID google created every time a new file (test.jpg, test(1).jpg, test(2)....)
The event "FileUploaded(FileID as string)" will be raised with the FileID, if the upload was successfully.

DownloadFile(FileID, LocalPath, LocalFilename)
Save the file on the device on the passed path. The FileID is needed to find this file on drive. If you don't know the FileID, you can try to find it with the "SearchForFile" function.

SearchForFile(Filename)
If you don't know the FileID of a file, you can try to find it with this function.
The Event "FileFound(ID as String)" will be raised in any case. If the file was found, the ID will return. If not, the ID return an empty string "".

SearchForFolderID(Foldername)
The same like SearchForFile, but only for folders.

ShowTheFileList
Returns a list with all filenames on Drive.

GetMetadata(FileID)
Some information can download about a file. The result returns as a map with the follow entrys :
"kind", "fileid", "selflink", "iconLink", "title", "mimeType", "createdDate", "modifiedDate", "downloadUrl", "fileExtension"

ResetAll
Delete internal oauth files to restart the connection. Should call at start of application or with a follow "ConnectToDrive"-method.

Monitoring :

This function mirrors a file between the device and Google Drive. The path of this file is "Apps/vad_YourFoldername". In this folder the mirrored file will upload.

Monitoring_Start(Foldername, LocalDir, LocalFile, Monitoring_Interval, DoNotTransmitUpdates)
- Foldername is the name of the folder on Google Drive. The file will saved in the folder "Apps/vad_YourFolderName". But you don't need this name for any access.
- LocalDir und LocalFile is the path for the file on your device.
- Monitoring_Interval is the duration between check for actuality of the file. Time in Minutes
- DoNotTransmitUpdates prevent the function to update or download the file. Only the Events "DriveFileIsNewer" or "DriveFileIsOlder" will be raised. If you want to make an update catch the event and call "Monitoring_ForceTransmission".

To reset the folderID or fileID on Google Drive, call ResetMonitoring. Else ever the same fileID and FolderID will uses until you deinstall the application.

You can manually File.Delete(File.DirInternal, "fileid.txt"), too. It's the same effect. Recall the Monitoring_Start after this command.

Monitoring_Start2(Foldername, LocalDir, LocalFile, Monitoring_Interval, DoNotTransmitUpdates, ForceFileID)
The same like Monitoring_Start, but with ForceFileID. With this method will not create new file on first init, but the pass FileID will used. (No controlling for correctness of the ID) Good for switching between further files. To keep the old fileID, use Monitoring_GetID and save this content.

Monitoring_Refresh
Start the check manual.

Monitoring_Stop
Stops the check interval.

Monitoring_ForceTransmission
Transfer the monitoring file if needed. This function ignores the command "TransferFile" in "Monitor_Start" function.

ResetMonitoring
Resets the access data for monitoring. Helpful to create new monitoring file, changing folder or for tests.

Monitoring_GetID as Map
Returns a map with the storaged IDs from monitoring service (contents "fileid" and "folderid")
If config file is not create, a uninitialized map will return

Propertys :

Monitoring_OnlyWlan as Boolean (False)
If True, the Monitoring function will not work without WLAN.

Events :

Connected(Settings as Map)
If the connection was successfully.

FileListResult(Filelist as List)
Returns the list of names on Google Drive

FileDownloaded
If download from a file was successfully.

FileFound(ID as String)
Returns the result from SearchForFileID. If anything found, the FileID returns. Else "".

FolderFound(ID as String)
Returns the result from SearchForFolderID. If anything found, the FolderID returns. Else "".

FileUploaded(FileID as string)
If a file was correctly uploaded.

UserAbortsRequest
User denied the access.

GetMetadata(Data as Map)
Returns some metadata from a file :
kind,fileid,selflink,iconlink,title,mimeType,createDate,modifiedDate,downloadUrl,fileExension,trashed

NoInternetConnection
Raise if on connection process no network connection available.

DriveFileIsNewer
DriveFileIsOlder

If the monitoring file on drive older or newer, on of this event raises.

Tip :
If you use the monitoring function and the application don't change anything on the file in a background process, use this :
B4X:
Sub Activity_Resume
   Drive.Monitoring_Start("yourEvent", File.DirInternal, YOUR_FILE, 1, FALSE)
End Sub

Sub Activity_Pause (UserClosed As Boolean)
    clsDrive.Monitoring_Stop
End Sub
This will conserve your battery.

Maybe this library helps someone.

Update 29.09 :
Fixed failures with Monitor_Stop

Update 29.09 V2 :
Fixed a problem with fileupload
Adds method "ResetMonitoring" for reset the monitoring settings

Update 29.09 V3 :
Added a better method to proof whether the file on gDrive is newer.
Prevent a failure message.

Last Update :
Fixed some failures. Upload the source code.
 

Attachments

  • LibDriveExample_V3.zip
    114.4 KB · Views: 867
  • libGoogleDrive.jar
    38.1 KB · Views: 619
  • Google Drive Source.zip
    167.2 KB · Views: 646
Last edited:

b4auser1

Well-Known Member
Licensed User
Longtime User
Thank you. It's very usefull lib. How do you compare modif datetime of files for monitoring ? Could it be a problem if the system time of device not syncronized with Google drive sec 2 sec ?
 

davfla

Member
Licensed User
Longtime User
Hi,

Thank you. It's very usefull lib. How do you compare modif datetime of files for monitoring ? Could it be a problem if the system time of device not syncronized with Google drive sec 2 sec ?
The comparing at this moment uses the timestamp of the last modified. To repeat the update of this file in seconds is not possible and useful, because :
- It's drain your battery significantly
- The function comparse not for seconds. Only every minute can the change event raise.
But if you wish I can add an optional property which allows to compare the files for seconds.

Is there a FileUploaded event ?
I added all events in the describtion text of this thread. Yes, there is an event which raise on fileupload :

"FileUploaded(FileID as String)"


If you want to overwrite or download the file later, store the FileID in a textfile/database/anywhere. The monitoring function do this independently.
 
Last edited:

susu

Well-Known Member
Licensed User
Longtime User
Thank you for useful lib. Can I use your lib to open a file on Google Drive? For example, can I open/play a mp3 file directly from Drive?
 

davfla

Member
Licensed User
Longtime User
Thank you for useful lib.
My pleasure. I needed this function anyway for my app project.

Can I use your lib to open a file on Google Drive? For example, can I open/play a mp3 file directly from Drive?
Not directly I think. But you can download this file on your device and play the mp3. What you mean is streaming, but I don't know whether it would be possible to stream with Google Drive.

David
 

susu

Well-Known Member
Licensed User
Longtime User
I saw some websites can streaming video directly from Google Drive. It will be extremely useful if your lib can do it too.
 

davfla

Member
Licensed User
Longtime User
I saw some websites can streaming video directly from Google Drive. It will be extremely useful if your lib can do it too.
I don't think I can realizing such a function. You need an interface which play the video, like VLC or Youtube player. For this I need an own play engine. That's too much for this library.

But you can use the GetMetadata(FileID) function. In the result map is the key "downloadUrl". Maybe you find a way to play with an external program. Sorry.

David
 

susu

Well-Known Member
Licensed User
Longtime User
Of course, I don't ask for streaming function in your lib. I just want to be sure your lib can open/play a file without downloading it.
I'm sorry because I didn't try your lib but I will when I get my computer. Thank you again :D
 

Peter Gould

Member
Licensed User
Longtime User
Hi Davfla,

This is a very interesting library. However when I tried the example libDriveExample_V3, I get the following error when I try to connect to google drive:

java.lang.RuntimeException: Object should first be initialized (Activity).

I'm runnning Android 4.4 on an LG L34C phone.
 

mtselection

Member
Licensed User
Longtime User
Hi Davfla,

Thank you for lib. I can upload the files in the root directory of google drive, but can not upload files in sub directories.
I am using the field DriveFolder
clsDrive.UploadFile ("xxxxxxx", "xxxxxxx", "xxxxxx", "drivedir", "")

Maurizio
 

Peter Gould

Member
Licensed User
Longtime User
Hi Maurizio,

did you get the DriveTest example to work? I could not (see my post before yours). Would you share a working example of using ligGoogle drive if you have one?

Cheers,
Peter
 

mtselection

Member
Licensed User
Longtime User
Hi Peter,

I have used the example library and I have changed only the ClientID and Cientsecret.
Check in the log file which the object should be initialized.

Maurizio
 

Peter Gould

Member
Licensed User
Longtime User
Thanks for the reply Maurizio. I also replaced the client_id and client_secret, but I get the error java.lang.RuntimeException: Object should first be initialized (Activity) when I try to connect. It is a strange error since the activity clearly is initialized (it's running!). There isn't any additional information in the log. I've spent quite a bit of time trying to debug but no luck.

UPDATE: I found that the problem only occurs when I deploy in 'debug (rapid)' mode. The example works in release mode and 'debug (legacy)'.
 
Last edited:

Kiese

Member
Licensed User
Longtime User
Hi ! It really is a very useful lib. However I have this issue when using your example and trying to connect :

** Activity (main) Create, isFirst = true **


** Activity (main) Resume **


** Activity (main) Pause, UserClosed = false **


java.lang.NoClassDefFoundError: anywheresoftware.b4a.objects.ServiceHelper$StarterHelper


at anywheresoftware.b4a.samples.gmailcontacts.modrequest.onCreate(modrequest.java:62)
at android.app.Activity.performCreate(Activity.java:5541)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1093)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2411)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2507)
at android.app.ActivityThread.access$900(ActivityThread.java:172)


at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1308)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:146)
at android.app.ActivityThread.main(ActivityThread.java:5692)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
at dalvik.system.NativeStart.main(Native Method)


Any ideas ?
 
Top