Italian Sincronizzazione files da onedrive

Fulvio75

Well-Known Member
Licensed User
Ciao qualcuno ha mai provato a sviluppare una app che permette di sincronizzare le cartelle del proprio onedrive con quelle del telefono?
È fattibile per via delle limitazioni di accesso alle cartelle sul telefono?
 

Fulvio75

Well-Known Member
Licensed User
Mai provato, ma credo che le uniche cartelle alle quali la tua app non possa accedere, siano quelle private delle altre app (le DirInternal, per intenderci).
Ok proverò, esiste un file picker per selezionare cartelle e files già pronto? Non ho mai guardato
 

LucaMs

Expert
Licensed User
Longtime User
Ok proverò, esiste un file picker per selezionare cartelle e files già pronto? Non ho mai guardato
Guarda se questa funzioni ancora (con tutti i cambiamenti Android...!)

Ci sarebbe anche ContentChooser, che però consente di selezionare file, non cartelle, ma quando l'utente seleziona un file, puoi ottenere anche il nome della cartella che lo contiene.
 

Paperinik

Member
Licensed User
Longtime User
Ciao Fulvio, hai trovato un modo per accedere a OneDrive? Ho la tua stessa necessità: selezionare una cartella, elencarne il contenuto e nel caso aggiungere files, ma non riesco a trovare una quadra.
Con la libreria ExternalStorage posso accedere ad una cartella ed al suo contenuto, ma non per i cloud ( OneDrive, GoogleDrive, ecc).
Con il ContentChooser riesco ad accedere ai cloud ma devo puntare ad un file specifico e non ho accesso a tutta la cartella selezioanta.
 

Fulvio75

Well-Known Member
Licensed User
Ciao Fulvio, hai trovato un modo per accedere a OneDrive? Ho la tua stessa necessità: selezionare una cartella, elencarne il contenuto e nel caso aggiungere files, ma non riesco a trovare una quadra.
Con la libreria ExternalStorage posso accedere ad una cartella ed al suo contenuto, ma non per i cloud ( OneDrive, GoogleDrive, ecc).
Con il ContentChooser riesco ad accedere ai cloud ma devo puntare ad un file specifico e non ho accesso a tutta la cartella selezioanta.
Si appena riesco oggi o domani ti scrivo
 

Fulvio75

Well-Known Member
Licensed User
B4X:
'B4A Pagina

Sub Class_Globals

'Qui se no non funziona
private GD As clsGoogleDrive

end sub

Private Sub B4XPage_Created (Root1 As B4XView)
  
    Root = Root1
    Root.LoadLayout("layMainPage")
  
    'Inizializzo GoogleDrive per forza qui
    Initialize_GoogleDrive

End Sub

private Sub B4XPage_Foreground

    'Qui non altrove
    GD.Resume(Me)
  
end sub

private Sub Initialize_GoogleDrive
   
    GD.Initialize(Me,"Authcode da inserire","","")
       
End Sub
 

Fulvio75

Well-Known Member
Licensed User
Classe

B4X:
Sub Class_Globals
  
    Private xui As XUI
  
    Private CallBack As Object
  
    ' GoogleAuth
    Private GoogleOAuth As GoogleOAuth2
    Private Client_ID As String = ""
    Private Client_Secret As String = ""
    Private Data_Folder As String = ""
    Public TokenInfo As TokenInformationDef
  
    Private Const Scope As String = "https://www.googleapis.com/auth/drive"
    Private Const Event_Name As String = "GoogleDrive"

    Private Phone As Phone
  
    Private Network As ServerSocket
    Type NetworkStatesTypes (Disconnected As Int,Connecting As Int,Connected As Int,Suspended As Int)
    Public NetworkStates As NetworkStatesTypes
  
    Private StartAuthenticateTime As Long = 0
    Private AuthenticateTimeOutMin As Int = 10
    Private AuthenticateTimeOut As Boolean = False
  
    Public IsReady As Boolean = False
    Public ConsentOAuthShowed As Boolean = False
    Public WaitingForAuthenticate As Boolean = False
  
End Sub

Public Sub Initialize (EventTarget As Object, ClientID As String, ClientSecret As String, DataFolder As String)

CallBack = EventTarget
Client_ID = ClientID
Client_Secret = ClientSecret
Data_Folder = DataFolder

NetworkStates = CreateNetworkStatesTypes(0,1,2,3)

AuthenticateTimeOut = False
IsReady = False
WaitingForAuthenticate = False
ConsentOAuthShowed = False
StartAuthenticateTime = DateTime.Now
TokenInfo.Initialize

Authenticate

End Sub

private Sub Authenticate

Do While Check_NetworkState = NetworkStates.Disconnected

Sleep(0)

'Per generare l'evento solo una volta
If WaitingForAuthenticate = False Then
WaitingForAuthenticate = True
CallSub(CallBack,Event_Name & "_WaitingForNetwork")
CallSub(CallBack,Event_Name & "_WaitingForAuthenticate")
End If

If (DateTime.Now-StartAuthenticateTime) >= (AuthenticateTimeOutMin*60*1000) Then
AuthenticateTimeOut = True
Exit
End If

Loop

If AuthenticateTimeOut = False Then

WaitingForAuthenticate = True

CallSub(CallBack,Event_Name & "_AuthenticateInitialize")

GoogleOAuth.Initialize(Me,Client_ID,Scope,Client_Secret,Data_Folder)
GoogleOAuth.GetAccessToken

Else If AuthenticateTimeOut = True Then

IsReady = False
WaitingForAuthenticate = False
ConsentOAuthShowed = False

CallSubDelayed2(CallBack,Event_Name & "_IsReady",False)
CallSubDelayed(CallBack,Event_Name & "_AuthenticateTimeOut")
CallSubDelayed(CallBack,Event_Name & "_AuthenticateComplete")

End If

End Sub

'Da inserire tassativamente in B4XPage_Foreground serve per recuperare il Token quando rivisualizzo la pagina
Public Sub Resume(EventTarget As Object)

'Serve per attendere che vengano impostate le variabili in Initialize perchè Resume viene chiamato sul Foreground della pagina
Sleep(500)

CallBack = EventTarget

Do While Check_NetworkState = NetworkStates.Disconnected Or (WaitingForAuthenticate = True And IsReady = False)

Sleep(0)

If AuthenticateTimeOut = True Then
Exit
End If

Loop

If AuthenticateTimeOut = False And IsReady = True Then
GoogleOAuth.CallFromResume(B4XPages.GetNativeParent(CallBack).GetStartingIntent)
End If

End Sub

'Se GoogleDrive connesso e Token disponibile
private Sub GoogleOAuth_AccessTokenAvailable(Success As Boolean,TokenInformation As TokenInformationDef)

If Success = True Then

IsReady = True

TokenInfo = TokenInformation

else if Success = False Then

IsReady = False

TokenInfo.Initialize

End If

WaitingForAuthenticate = False
ConsentOAuthShowed = False

CallSubDelayed2(CallBack,Event_Name & "_IsReady",IsReady)
CallSubDelayed(CallBack,Event_Name & "_AuthenticateComplete")

End Sub

'Schermata di consenso visualizzata
private Sub GoogleOAuth_ConsentOAuthShowed

ConsentOAuthShowed = True

End Sub

public Sub setAuthTimeOut(Minutes As Int)

AuthenticateTimeOutMin = Minutes

End Sub

public Sub getAuthTimeOut As Int

Return AuthenticateTimeOutMin

End Sub

Public Sub setRedirectEventTarget(EventTarget As Object)

CallBack = EventTarget

End Sub

#end region

#Region Comandi

'Restituisce una lista di Files contenuti nella cartella
'FolderID: Id della cartella, passare "" se i Files non sono in una cartella
'<code>
'Wait For GoogleDrive_ListFilesCompleted (Success As Boolean,Files As List)
'</code>
Public Sub List_Files(FolderID As String) As ResumableSub

'Gestione Rete dati
If Check_NetworkState <> NetworkStates.Connected Then

IsReady = False

CallSubDelayed3(CallBack,Event_Name & "_ListFilesCompleted",False,Null)
CallSubDelayed2(CallBack,Event_Name & "_IsReady",False)
CallSubDelayed(CallBack,Event_Name & "_WaitingForNetwork")

Return Null

Else

IsReady = True

CallSubDelayed2(CallBack,Event_Name & "_IsReady",True)

End If

Dim h_sfl As HttpJob
Dim FilesList As List

h_sfl.Initialize("", Me)

If FilesList.IsInitialized = False Then
FilesList.Initialize
FilesList.Clear
End If

If FolderID = "" Then

h_sfl.Download2("[URL]https://www.googleapis.com/drive/v3/files[/URL]", _
Array As String("access_token", TokenInfo.AccessToken, _
"corpora", "user", _
"q","mimeType!='application/vnd.google-apps.folder' and trashed=false"))

Else

h_sfl.Download2("[URL]https://www.googleapis.com/drive/v3/files[/URL]", _
Array As String("access_token", TokenInfo.AccessToken, _
"corpora", "user", _
"q", $"mimeType!='application/vnd.google-apps.folder' and '${FolderID}' in parents and trashed=false"$))

End If

Wait For (h_sfl) JobDone(h_sfl As HttpJob)

If h_sfl.Success = True Then

Dim Map1, FileEntry As Map
Dim J As JSONParser
Dim Files As List

J.Initialize(h_sfl.GetString)
Files.Initialize
Map1 = J.NextObject
Files = Map1.Get("files")

For i = 0 To Files.Size - 1
FileEntry = Files.Get(i)
FilesList.Add(FileEntry.Get("name") & ";" & FileEntry.Get("id"))
Next

CallSubDelayed3(CallBack,Event_Name & "_ListFilesCompleted",True,FilesList)

Else

CallSubDelayed3(CallBack,Event_Name & "_ListFilesCompleted",False,FilesList)

End If

h_sfl.Release

Return Null

End Sub

'Elimina il File
'FileID: Id del File da eliminare
'<code>
'Wait For GoogleDrive_DeleteFileCompleted (Success As Boolean)
'</code>
Public Sub Delete_File(FileID As String) As ResumableSub

'Gestione Rete dati
If Check_NetworkState <> NetworkStates.Connected Then

IsReady = False

CallSubDelayed2(CallBack,Event_Name & "_DeleteFileCompleted", False)
CallSubDelayed2(CallBack,Event_Name & "_IsReady",False)
CallSubDelayed(CallBack,Event_Name & "_WaitingForNetwork")

Return Null

Else

IsReady = True

CallSubDelayed2(CallBack,Event_Name & "_IsReady",True)

End If

Dim del_file As HttpJob

del_file.Initialize("",Me)
del_file.Delete("[URL]https://www.googleapis.com/drive/v3/files/[/URL]" & FileID)
del_file.GetRequest.SetHeader("Authorization", "Bearer " & TokenInfo.AccessToken)
Wait For (del_file) JobDone(del_file As HttpJob)

If del_file.Success Then

CallSubDelayed2(CallBack,Event_Name & "_DeleteFileCompleted", True)

Else

CallSubDelayed2(CallBack,Event_Name & "_DeleteFileCompleted", False)

End If

del_file.Release

Return Null

End Sub

'Crea una cartella
'ParentID: ID della cartella padre dove creare la sotto cartella, passare "" per creare la cartella non in una sotto cartella
'FolderName: Nome della cartella
'<code>
'Wait For GoogleDrive_CreateFolderCompleted (Success As Boolean,FolderID As String)
'</code>
Public Sub Create_Folder(ParentID As String, FolderName As String) As ResumableSub

'Gestione Rete dati
If Check_NetworkState <> NetworkStates.Connected Then

IsReady = False

CallSubDelayed3(CallBack, Event_Name & "_CreateFolderCompleted", False, "")
CallSubDelayed2(CallBack,Event_Name & "_IsReady",False)
CallSubDelayed(CallBack,Event_Name & "_WaitingForNetwork")

Return Null

Else

IsReady = True

CallSubDelayed2(CallBack,Event_Name & "_IsReady",True)

End If

Dim h_cf As HttpJob
Dim m As Map

Dim Jg As JSONGenerator
Dim Data() As Byte

m.Initialize
m.Put("name", FolderName)
m.Put("mimeType", "application/vnd.google-apps.folder")

If ParentID<>"" Then
m.Put("parents",Array As String(ParentID))
End If

Jg.Initialize(m)

Data = (Jg.ToString).GetBytes("UTF-8")

h_cf.Initialize("",Me)
h_cf.PostBytes("[URL]https://www.googleapis.com/drive/v3/files?UploadType=multipart[/URL]",Data)
h_cf.GetRequest.SetHeader("Authorization", "Bearer " & TokenInfo.AccessToken)
h_cf.GetRequest.SetContentType("application/json;charset=UTF-8")

wait For (h_cf) JobDone(h_cf As HttpJob)

If h_cf.Success Then

Dim j As JSONParser
Dim Map1 As Map

J.Initialize(h_cf.GetString)
Map1 = J.NextObject

CallSubDelayed3(CallBack, Event_Name & "_CreateFolderCompleted", True, Map1.Get("id"))

Else

CallSubDelayed3(CallBack, Event_Name & "_CreateFolderCompleted", False, "")

End If

h_cf.Release

Return Null

End Sub

'Carica un File su GoogleDrive
'FileID: Id del file su GoogleDrive, se vuoto viene creato un nuovo file altrimenti viene sostituito
'LocalPath: Percorso locale dove si trova il file da copiare in GoogleDrive
'LocalFileName: Nome del file nella catella locale
'FolderID: Id della cartella di GoogleDrive dove copiare il file se "" viene copiato nella cartella principale
'GoogleDriveFileName: Nome del file da attribuire in GoogleDrive se "" il nome è uguale al locale
'<code>
'Wait For GooleDrive_UploadCompleted (Success As Boolean,FileID As String)
'</code>
Public Sub Upload_File(FileId As String,LocalPath As String,LocalFileName As String,FolderID As String,GoogleDriveFileName As String) As ResumableSub

'Gestione Rete dati
If Check_NetworkState <> NetworkStates.Connected Then

IsReady = False

CallSubDelayed3(CallBack, Event_Name & "_UploadCompleted",False, "")
CallSubDelayed2(CallBack,Event_Name & "_IsReady",False)
CallSubDelayed(CallBack,Event_Name & "_WaitingForNetwork")

Return Null

Else

IsReady = True

CallSubDelayed2(CallBack,Event_Name & "_IsReady",True)

End If

Dim Data() As Byte

If GoogleDriveFileName = "" Then GoogleDriveFileName = LocalFileName

Try

Dim h_ul As HttpJob

h_ul.Initialize("",Me)

If FileId = "" Then

'Create the stream
Dim boundary As String = "foo_bar_baz"
Dim ContentType As String = "application/octet-stream"
Dim EOL As String= Chr(13) & Chr(10)

Dim In As InputStream = File.OpenInput(LocalPath, LocalFileName)
Dim out2 As OutputStream
out2.InitializeToBytesArray(1000)

Dim m As Map
m.Initialize
m.Put("name", GoogleDriveFileName)

If FolderID <> "" Then
m.Put("parents",Array As String(FolderID))
End If

Dim Jg As JSONGenerator
Jg.Initialize(m)

'The first half of the POST contains the JSON data AND the Content Type from above.
Dim RR As String = "--" & boundary & EOL & "Content-Type: application/json; charset=UTF-8" & EOL & _
EOL & Jg.ToString & EOL & EOL & "--" & boundary & EOL & "Content-Type: " & ContentType & EOL & EOL
Data = (RR).GetBytes("UTF-8")
out2.WriteBytes(Data, 0, Data.Length) 'Write it To the Stream.
File.Copy2(In, out2) 'Add the File itself To the Stream.
Data = (EOL & EOL & "--" & boundary & "--").GetBytes("UTF-8") 'Add the final boundary to the POST
out2.WriteBytes(Data, 0, Data.Length) 'Write it To the Stream Then make the Bytes the complete Stream.
Data = out2.ToBytesArray


h_ul.PostBytes("[URL]https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart[/URL]", Data)
h_ul.GetRequest.SetContentType("multipart/related; boundary=" & boundary)
h_ul.GetRequest.SetHeader("Authorization", "Bearer " & TokenInfo.AccessToken)

Else

'Create a new stream
Dim OutUpdate As OutputStream
Dim InUpate As InputStream = File.OpenInput(LocalPath, LocalFileName)

OutUpdate.InitializeToBytesArray(1000) 'Initialize the stream
File.Copy2(InUpate, OutUpdate) 'Copy the filestream in the output stream
Data = OutUpdate.ToBytesArray 'Fill export data array
h_ul.PatchBytes($"[URL]https://www.googleapis.com/upload/drive/v3/files/$[/URL]{FileId}?uploadType=media"$, Data)
h_ul.GetRequest.SetHeader("Authorization", "Bearer " & TokenInfo.AccessToken)

End If

wait For (h_ul) JobDone(h_ul As HttpJob)

If h_ul.Success = True Then

Dim j As JSONParser
Dim map1 As Map

J.Initialize(h_ul.GetString)
map1 = J.NextObject

CallSubDelayed3(CallBack, Event_Name & "_UploadCompleted",True, map1.Get("id"))

Else

CallSubDelayed3(CallBack, Event_Name & "_UploadCompleted",False, "")

End If

Catch

CallSubDelayed3(CallBack, Event_Name & "_UploadCompleted",False, "")

End Try

Return Null

End Sub

'Scarica un File da GoogleDrive
'FileID: ID del file su GoogleDrive da scaricare
'LocalFolder: Percorso locale dove scaricare il File
'LocalFileName: Nome da dare al File
'<code>
'Wait For GooleDrive_DownloadCompleted (Success As Boolean,FilePath As String)
'</code>
Public Sub Download_File(FileID As String, LocalFolder As String, LocalFileName As String) As ResumableSub

'Gestione Rete dati
If Check_NetworkState <> NetworkStates.Disconnected Then

IsReady = False

CallSubDelayed3(CallBack, Event_Name & "_DownloadCompleted", False, "")
CallSubDelayed2(CallBack,Event_Name & "_IsReady",False)
CallSubDelayed(CallBack,Event_Name & "_WaitingForNetwork")

Return Null

Else

IsReady = True

CallSubDelayed2(CallBack,Event_Name & "_IsReady",True)

End If

Dim h_dl As HttpJob

h_dl.Initialize("",Me)
h_dl.Download("[URL]https://www.googleapis.com/drive/v3/files/[/URL]" & FileID & "?alt=media")
h_dl.GetRequest.SetHeader("Authorization", "Bearer " & TokenInfo.AccessToken)

Wait For (h_dl) JobDone(h_dl As HttpJob)

If h_dl.Success = True Then

Dim inStr As InputStream
Dim out As OutputStream

If LocalFileName = "" Then LocalFileName = "Download-" & DateTime.Time(DateTime.Now) & ".x"
inStr = h_dl.GetInputStream

out = File.OpenOutput(LocalFolder, LocalFileName, False)
File.Copy2(inStr, out)
out.Close

CallSubDelayed3(CallBack, Event_Name & "_DownloadCompleted", True, File.Combine(LocalFolder, LocalFileName))

Else

CallSubDelayed3(CallBack, Event_Name & "_DownloadCompleted", False, "")

End If

h_dl.Release

Return Null

End Sub

'Elimina la cartella
'FolderID: ID della cartella da eliminare
'<code>
'Wait For GooleDrive_DeleteFolderComplete(Success as Boolean)
'</code>
Public Sub Delete_Folder(FolderID As String) As ResumableSub

'Gestione Rete dati
If Check_NetworkState <> NetworkStates.Disconnected Then

IsReady = False

CallSubDelayed2(CallBack,Event_Name & "_DeleteFolderComplete", False)
CallSubDelayed2(CallBack,Event_Name & "_IsReady",False)
CallSubDelayed(CallBack,Event_Name & "_WaitingForNetwork")

Return Null

Else

IsReady = True

CallSubDelayed2(CallBack,Event_Name & "_IsReady",True)

End If

Dim del_folder As HttpJob

del_folder.Initialize("",Me)
del_folder.Delete("[URL]https://www.googleapis.com/drive/v3/files/[/URL]" & FolderID)
del_folder.GetRequest.SetHeader("Authorization", "Bearer " & TokenInfo.AccessToken)
Wait For (del_folder) JobDone(del_folder As HttpJob)

If del_folder.Success = True Then

CallSubDelayed2(CallBack,Event_Name & "_DeleteFolderComplete", True)

Else

CallSubDelayed2(CallBack,Event_Name & "_DeleteFolderComplete", False)

End If

del_folder.Release

Return Null

End Sub

'Restituisce una lista di Cartelle
'FolderID: Id della cartella, passare "" se le cartelle non sono in una cartella
'<code>
'Wait For GoogleDrive_ListFoldersComplete (Success As Boolean,Folders As List)
'</code>
Public Sub List_Folders(FolderID As String) As ResumableSub

'Gestione Rete dati
If Check_NetworkState <> NetworkStates.Connected Then

IsReady = False

CallSubDelayed3(CallBack,Event_Name & "_ListFoldersComplete",False,Null)
CallSubDelayed2(CallBack,Event_Name & "_IsReady",False)
CallSubDelayed(CallBack,Event_Name & "_WaitingForNetwork")

Return Null

Else

IsReady = True

CallSubDelayed2(CallBack,Event_Name & "_IsReady",True)

End If

Dim H_SFO As HttpJob
Dim FoldersList As List

H_SFO.Initialize("", Me)

If FoldersList.IsInitialized=False Then
FoldersList.Initialize
FoldersList.Clear
End If

If FolderID = "" Then

H_SFO.Download2("[URL]https://www.googleapis.com/drive/v3/files[/URL]", _
Array As String("access_token", TokenInfo.AccessToken, _
"corpora", "user", _
"q",$"mimeType='application/vnd.google-apps.folder' And trashed=false"$))

Else

H_SFO.Download2("[URL]https://www.googleapis.com/drive/v3/files[/URL]", _
Array As String("access_token", TokenInfo.AccessToken, _
"corpora", "user", _
"q",$"mimeType='application/vnd.google-apps.folder' and '${FolderID}' in parents and trashed=false"$))

End If

Wait For (H_SFO) JobDone(H_SFO As HttpJob)

If H_SFO.Success = True Then

Dim j As JSONParser
Dim Map1,FolderEntry As Map
Dim Folder As List

J.Initialize(H_SFO.GetString)
Folder.Initialize
Map1 = J.NextObject
Folder = Map1.Get("files")

For i = 0 To Folder.Size - 1
FolderEntry = Folder.Get(i)
FoldersList.Add(FolderEntry.Get("name") & ";" & FolderEntry.Get("id"))
Next

CallSubDelayed3(CallBack,Event_Name & "_ListFoldersComplete",True,FoldersList)

Else

CallSubDelayed3(CallBack,Event_Name & "_ListFoldersComplete",False,FoldersList)

End If

H_SFO.Release

Return Null

End Sub

'Restituisce Id del File ricercato
'SearchFile: File da cercare
'FolderID: Cartella padre dove cercare il File, passare "" se in File non è contenuto in una cartella
'<code>
'Wait For GoogleDrive_SearchFileIDComplete (Success As Boolean,FileId As String)
'</code>
Public Sub Search_FileID(SearchFile As String,FolderID As String) As ResumableSub

'Gestione Rete dati
If Check_NetworkState <> NetworkStates.Connected Then

IsReady = False

CallSubDelayed3(CallBack, Event_Name & "_SearchFileIDComplete",False, "")
CallSubDelayed2(CallBack,Event_Name & "_IsReady",False)
CallSubDelayed(CallBack,Event_Name & "_WaitingForNetwork")

Return Null

Else

IsReady = True

CallSubDelayed2(CallBack,Event_Name & "_IsReady",True)

End If

Dim H_SFI As HttpJob

H_SFI.Initialize("", Me)

If FolderID = "" Then

H_SFI.Download2("[URL]https://www.googleapis.com/drive/v3/files[/URL]", _
Array As String("access_token", TokenInfo.AccessToken, _
"corpora", "user", _
"q",$"mimeType!='application/vnd.google-apps.folder' and name='${SearchFile}' and trashed=false"$))

Else

H_SFI.Download2("[URL]https://www.googleapis.com/drive/v3/files[/URL]", _
Array As String("access_token", TokenInfo.AccessToken, _
"corpora", "user", _
"q",$"mimeType!='application/vnd.google-apps.folder' and name='${SearchFile}' and '${FolderID}' in parents and trashed=false"$))

End If

Wait For (H_SFI) JobDone(H_SFI As HttpJob)

If H_SFI.Success = True Then

Dim j As JSONParser
Dim Map1,FileEntry As Map
Dim Files As List
Dim FileID As String = ""
Dim Success As Boolean = False

J.Initialize(H_SFI.GetString)
Files.Initialize
Map1 = J.NextObject
Files = Map1.Get("files")
H_SFI.Release

For i = 0 To Files.Size - 1

FileEntry = Files.Get(i)

If FileEntry.Get("name") = SearchFile Then

FileID = FileEntry.Get("id")
Success = True
Exit ' Exit search if found

End If

Next

CallSubDelayed3(CallBack, Event_Name & "_SearchFileIDComplete",Success, FileID)

Else

CallSubDelayed3(CallBack, Event_Name & "_SearchFileIDComplete",False, "")

End If

H_SFI.Release

Return Null

End Sub

'Restituisce Id della Cartella ricercata
'SearchFolder: Cartella da cercare
'ParentFolderID: Cartella padre dove cercare la Cartella, passare "" se in Cartella non è contenuta in una Cartella
'<code>
'Wait For GoogleDrive_SearchFolderIDComplete (Success As Boolean,FolderId As String)
'</code>
Public Sub Search_FolderID(SearchFolder As String,ParentFolderID As String) As ResumableSub

'Gestione Rete dati
If Check_NetworkState <> NetworkStates.Connected Then

IsReady = False

CallSubDelayed3(CallBack, Event_Name & "_SearchFolderIDComplete",False, "")
CallSubDelayed2(CallBack,Event_Name & "_IsReady",False)
CallSubDelayed(CallBack,Event_Name & "_WaitingForNetwork")

Return Null

Else

IsReady = True

CallSubDelayed2(CallBack,Event_Name & "_IsReady",True)

End If

Dim H_SFO As HttpJob

H_SFO.Initialize("", Me)

If ParentFolderID = "" Then

H_SFO.Download2("[URL]https://www.googleapis.com/drive/v3/files[/URL]", _
Array As String("access_token", TokenInfo.AccessToken, _
"corpora", "user", _
"q",$"mimeType='application/vnd.google-apps.folder' and name='${SearchFolder}' and trashed=false"$))

Else

H_SFO.Download2("[URL]https://www.googleapis.com/drive/v3/files[/URL]", _
Array As String("access_token", TokenInfo.AccessToken, _
"corpora", "user", _
"q",$"mimeType='application/vnd.google-apps.folder' and name='${SearchFolder}' and '${ParentFolderID}' in parents and trashed=false"$))

End If

Wait For (H_SFO) JobDone(H_SFO As HttpJob)

If H_SFO.Success = True Then

Dim j As JSONParser
Dim Map1,FolderEntry As Map
Dim Folder As List
Dim FolderID As String = ""
Dim Success As Boolean = False

J.Initialize(H_SFO.GetString)
Folder.Initialize
Map1 = J.NextObject
Folder = Map1.Get("files")
H_SFO.Release

For i = 0 To Folder.Size - 1

FolderEntry = Folder.Get(i)

If FolderEntry.Get("name") = SearchFolder And FolderEntry.Get("mimeType") = "application/vnd.google-apps.folder" Then

FolderID = FolderEntry.Get("id")
Success = True
Exit

End If

Next

CallSubDelayed3(CallBack, Event_Name & "_SearchFolderIDComplete",Success,FolderID)

Else

CallSubDelayed3(CallBack, Event_Name & "_SearchFolderIDComplete",False, "")

End If

H_SFO.Release

Return Null

End Sub

#end region

#Region Rete dati

'Controlla la connessione Dati di rete e WiFi e restituisce Connesso se almeno una delle due reti è connessa
private Sub Check_NetworkState() As Int

Dim OperatorState As Int = NetworkStates.Disconnected
Dim WiFiState As Int = NetworkStates.Disconnected

Dim NetworkState As Int = NetworkStates.Disconnected

'Rete operatore
Select Phone.GetDataState

Case "DISCONNECTED"
OperatorState = NetworkStates.Disconnected

Case "CONNECTING"
OperatorState = NetworkStates.Connecting

Case "CONNECTED"
OperatorState = NetworkStates.Connected

Case "SUSPENDED"
OperatorState = NetworkStates.Suspended

End Select

'Rete WiFi se disconnesso = 127.0.0.1
If Network.GetMyWifiIP = "127.0.0.1" Then
WiFiState = NetworkStates.Disconnected
Else
WiFiState = NetworkStates.Connected
End If

If WiFiState = NetworkStates.Disconnected And OperatorState = NetworkStates.Disconnected Then

NetworkState = NetworkStates.Disconnected

Else If WiFiState = NetworkStates.Disconnected And OperatorState = NetworkStates.Connecting Then

NetworkState = NetworkStates.Connecting

Else If WiFiState = NetworkStates.Disconnected And OperatorState = NetworkStates.Suspended Then

NetworkState = NetworkStates.Suspended

Else

NetworkState = NetworkStates.Connected

End If

CallSubDelayed2(CallBack,Event_Name & "_NetworkState",NetworkState)

Return NetworkState

End Sub

private Sub CreateNetworkStatesTypes (Disconnected As Int, Connecting As Int, Connected As Int, Suspended As Int) As NetworkStatesTypes

Dim t1 As NetworkStatesTypes

t1.Initialize
t1.Disconnected = Disconnected
t1.Connecting = Connecting
t1.Connected = Connected
t1.Suspended = Suspended

Return t1

End Sub

#End Region
 

Fulvio75

Well-Known Member
Licensed User
GoogleOauth2

B4X:
'version: 2.11

Sub Class_Globals
    
    #if B4A
    
    Private LastIntent As Intent
    
    #end if
    
    Type TokenInformationDef (AccessToken As String, RefreshToken As String, AccessExpiry As Long, Valid As Boolean)
    Private TokenInformation As TokenInformationDef
    
    Private mTarget As Object
    Private mEventName As String = "GoogleOAuth"
    Private mClientId As String
    Private mClientSecret As String
    Private mScope As String
    
    Private Const TokenFile As String = "oauth2token.dat"
    Private TokenFolder As String
    Private PackageName As String 'ignore
    
#if B4J

    Private server As ServerSocket
    Private fx As JFX
    Private port As Int = 51067
    Private astream As AsyncStreams
    
#End if

End Sub

#Region Comandi

'Chiamare per inizializzare GoogleDrive
Public Sub Initialize (Target As Object, ClientId As String, Scope As String, ClientSecret As String, DataFolder As String)
    
    mTarget = Target
    mClientId = ClientId
    mScope = Scope
    
    #if B4A
    
    PackageName = Application.PackageName
    TokenFolder = File.DirInternal
        
    #Else If B4i
    
        TokenFolder = File.DirLibrary
        packageName = GetPackageName
        
    #Else If B4J
    
        TokenFolder = DataFolder
        mClientSecret = ClientSecret
        
    #End If
    
    'Cerca se esiste il File del Token e lo carica
    If File.Exists(TokenFolder, TokenFile) Then
        
        Dim raf As RandomAccessFile
        
        raf.Initialize(TokenFolder, TokenFile, True)
        TokenInformation = raf.ReadB4XObject(raf.CurrentPosition)
        
        raf.Close
        
    End If
    
End Sub

'Per Resettare il Token per cambio scopo
Public Sub ResetToken

    Functions.Log_Write("ResetToken","GoogleOAuth2", _
            "Reset Token ")
    
    TokenInformation.Valid = False
    SaveToken
    
End Sub

'Da chiamare prima dello scambio dati con GoogleDrive dopo l'inizializzazione
Public Sub GetAccessToken
    
    If TokenInformation.Valid = False Then
        
        ConsentAuthenticate
        
    Else If TokenInformation.AccessExpiry < DateTime.Now Then
        
        GetTokenFromRefresh
        
    Else
        
        RaiseEvent(True)
        
    End If
    
End Sub

'Da chiamare su Foreground della Pagina
Public Sub CallFromResume(Intent As Intent)
    
    If IsNewOAuth2Intent(Intent) Then
        
        LastIntent = Intent
        ParseBrowserUrl(Intent.GetData)
        
    End If
    
End Sub

#End Region

#Region Funzioni interne di OAuth2

Private Sub SaveToken
    
    Dim raf As RandomAccessFile
    
    raf.Initialize(TokenFolder, TokenFile, False)
    raf.WriteB4XObject(TokenInformation, raf.CurrentPosition)
    
    raf.Close
    
End Sub

Private Sub GetRedirectUri As String
    
    #if B4J
    
    Return "http://127.0.0.1:" & port
    
    #Else
    
    Return PackageName & ":/oath"
        
    #End If
    
End Sub

Private Sub ConsentAuthenticate
    
    'Evento di visualizzazione finestra Autenticazione
    ConsentOAuthEvent

#if B4J

    PrepareServer
    
#End If

    Dim link As String = BuildLink("https://accounts.google.com/o/oauth2/v2/auth", _
         CreateMap("client_id": mClientId, _
        "redirect_uri": GetRedirectUri, _
        "response_type": "code", "scope": mScope, "access_type":"offline"))
        
#if B4A

    Dim pi As PhoneIntents
    StartActivity(pi.OpenBrowser(link))
        
#else if B4i

    Main.App.OpenURL(link)
    
#else if B4J

    fx.ShowExternalDocument(link)
    
#end if

End Sub

#if B4J

Private Sub PrepareServer
    If server.IsInitialized Then server.Close
    If astream.IsInitialized Then astream.Close
    Do While True
        Try
            server.Initialize(port, "server")
            server.Listen
            Exit
        Catch
            port = port + 1
            Log(LastException)
        End Try
    Loop
    Wait For server_NewConnection (Successful As Boolean, NewSocket As Socket)
    If Successful Then
        astream.Initialize(NewSocket.InputStream, NewSocket.OutputStream, "astream")
        Dim Response As StringBuilder
        Response.Initialize
        Do While Response.ToString.Contains("Host:") = False
            Wait For AStream_NewData (Buffer() As Byte)
            Response.Append(BytesToString(Buffer, 0, Buffer.Length, "UTF8"))
        Loop
        astream.Write(("HTTP/1.0 200" & Chr(13) & Chr(10)).GetBytes("UTF8"))
        Sleep(50)
        astream.Close
        server.Close
        ParseBrowserUrl(Regex.Split2("$",Regex.MULTILINE, Response.ToString)(0))
    End If
    
End Sub

#else if B4A

Private Sub IsNewOAuth2Intent(Intent As Intent) As Boolean
    
    Return Intent.IsInitialized And Intent <> LastIntent And Intent.Action = Intent.ACTION_VIEW And _
        Intent.GetData <> Null And Intent.GetData.StartsWith(Application.PackageName)
        
End Sub

#else if B4I

Public Sub CallFromOpenUrl (url As String)
    If url.StartsWith(packageName & ":/oath") Then
        ParseBrowserUrl(url)
    End If
End Sub

Private Sub GetPackageName As String
    Dim no As NativeObject
    no = no.Initialize("NSBundle").RunMethod("mainBundle", Null)
    Dim name As Object = no.RunMethod("objectForInfoDictionaryKey:", Array("CFBundleIdentifier"))
    Return name
End Sub

#end if

Private Sub ParseBrowserUrl(Response As String)
    
    Dim m As Matcher = Regex.Matcher("code=([^&\s]+)", Response)
    
    If m.Find Then
        
        Dim code As String = m.Group(1)
        GetTokenFromAuthorizationCode(code)
        
    Else
        
        Functions.Log_Write("ParseBrowserUrl","GoogleOAuth2","Error parsing server response: " & Response)

        ResetToken
        RaiseEvent(False)
        
    End If
    
End Sub

private Sub ConsentOAuthEvent
    
    CallSub(mTarget, mEventName & "_ConsentOAuthShowed")

End Sub

Private Sub RaiseEvent(Success As Boolean)
    
    CallSubDelayed3(mTarget, mEventName & "_AccessTokenAvailable", Success, TokenInformation)
    
End Sub

Private Sub GetTokenFromAuthorizationCode (Code As String)
    
    Functions.Log_Write("GetTokenFromAuthorizationCode","GoogleOAuth2", _
            "Getting access token from authorization code...")
    
    Dim j As HttpJob
    j.Initialize("", Me)
    
    Dim postString As String = $"code=${Code}&client_id=${mClientId}&grant_type=authorization_code&redirect_uri=${GetRedirectUri}"$
    postString = AddClientSecret(postString)
    j.PostString("https://www.googleapis.com/oauth2/v4/token", postString)
        
    Wait For (j) JobDone(j As HttpJob)
    
    If j.Success Then
        
        TokenInformationFromResponse(j.GetString)
        
    Else
        
        ResetToken
        RaiseEvent(False)
        
    End If
    
    j.Release
    
End Sub

Private Sub GetTokenFromRefresh
    
    Functions.Log_Write("GetTokenFromRefresh","GoogleOAuth2", _
            "Getting access token from refresh token...")

    Dim j As HttpJob
    j.Initialize("", Me)
    
    Dim postString As String = $"refresh_token=${TokenInformation.RefreshToken}&client_id=${mClientId}&grant_type=refresh_token&redirect_uri=${GetRedirectUri}"$
    postString = AddClientSecret(postString)
    j.PostString("https://www.googleapis.com/oauth2/v4/token", postString)
    
    Wait For (j) JobDone(j As HttpJob)
    
    If j.Success = True Then
        
        TokenInformationFromResponse(j.GetString)
        
    Else
        
        RaiseEvent(False)
        
    End If
    
    j.Release
    
End Sub

Private Sub AddClientSecret (s As String) As String
    
    If mClientSecret <> "" Then
        s = s & "&client_secret=" & mClientSecret
    End If
    
    Return s
    
End Sub

Private Sub TokenInformationFromResponse (s As String)
    
    Dim jp As JSONParser
    jp.Initialize(s)
    
    Dim m As Map = jp.NextObject
    TokenInformation.AccessExpiry = DateTime.Now + m.Get("expires_in") * 1000 - 5 * 60 * 1000
    TokenInformation.AccessToken = m.Get("access_token")
    
    If m.ContainsKey("refresh_token") Then TokenInformation.RefreshToken = m.Get("refresh_token")
    
    TokenInformation.Valid = True
    
    Functions.Log_Write("TokenInformationFromResponse","GoogleOAuth2", _
            "Token Information: " & _
            TokenInformation.AccessExpiry & _
            TokenInformation.AccessToken & _
            TokenInformation.RefreshToken & _
            TokenInformation.Valid)
    
    SaveToken
    
    RaiseEvent(True)
    
End Sub

Private Sub BuildLink(Url As String, Params As Map) As String
    
    Dim su As StringUtils
    Dim sb As StringBuilder
    
    sb.Initialize
    sb.Append(Url)
    
    If Params.Size > 0 Then
        
        sb.Append("?")
        
        For Each k As String In Params.Keys
            sb.Append(su.EncodeUrl(k, "utf8")).Append("=").Append(su.EncodeUrl(Params.Get(k), "utf8"))
            sb.Append("&")
        Next
        
        sb.Remove(sb.Length - 1, sb.Length)
        
    End If
    
    Return sb.ToString
    
End Sub

#End Region
 

Fulvio75

Well-Known Member
Licensed User
Io la uso per i miei progetti privati in test mode per cui su distribuzione non so se funziona o se viene bloccato, anche perchè in questo modo riesco a copiare tutti i file che voglio su cloud. L'ho scritto copiando vari pezzi di codice funziona da molto tempo
 

Paperinik

Member
Licensed User
Longtime User
Io la uso per i miei progetti privati in test mode per cui su distribuzione non so se funziona o se viene bloccato, anche perchè in questo modo riesco a copiare tutti i file che voglio su cloud. L'ho scritto copiando vari pezzi di codice funziona da molto tempo

Alla fine l'unica soluzione rimane quella di usare le API.
Grazie mille Fulvio per aver condiviso il codice, come ho un attimo lo provo!
 
Top