Alex Totolici
Alex Totolici

Reputation: 366

How to create and save Json file to Google Drive with the googleapis in flutter

So I have a Map<> of objects witch I want to save as a .json file in Google Drive using the googleapis plugin. But the documentation is soo poor and I just can't figure it out.

I've tried these tutorials/examples https://qiita.com/aoinakanishi/items/6ff8222847fcf934a64a(it's a Chinese one lol) https://github.com/dart-lang/googleapis_examples/blob/master/drive_upload_download_console/bin/main.dart

They have some pieces that work and some that don't

class GoogleDriveDatabase{

   GoogleSignIn googleSignIn ;
   GoogleHttpClient client;
   drive.DriveApi api;

   String fileId = "";

    static Future<GoogleDriveDatabase> init(BuildContext context) async{



GoogleDriveDatabase _googleDriveDatabase = GoogleDriveDatabase();

_googleDriveDatabase.googleSignIn = GoogleSignIn(
  scopes:  < String > [ 
  drive.DriveApi . DriveFileScope ,
  ], 
);

GoogleSignInAccount googleSignInAccount = await 
  _googleDriveDatabase.googleSignIn.signInSilently();
if(googleSignInAccount == null){
  launchPage(context, WelcomePage());
  return null;
}
Map authHeaders  = await googleSignInAccount.authHeaders;
_googleDriveDatabase.client = GoogleHttpClient(authHeaders);
_googleDriveDatabase.api = drive.DriveApi(_googleDriveDatabase.client);



return _googleDriveDatabase;

  }

  Future createDatabaseToDrive(String jsonFileName) async{
    drive.File file = drive.File.fromJson({"name":jsonFileName});

    drive.GeneratedIds generatedIds =await api.files.generateIds(space: 
 "drive",count: 1);
generatedIds.ids.forEach((f){
  file.id = f;
});

return api.files.create(
    file,
);
  }

  Future updateDbToDrive(Future<File> jsonFileFuture, String jsonFileName) 
async{
drive.File file = drive.File.fromJson({"name":jsonFileName});
file.id=jsonFileName;

File jsonFile = await jsonFileFuture;

//if it doesn't work catch the error on future
return (api.files.update(
    file,
    jsonFileName,
    uploadMedia: drive.Media(jsonFile.openRead(),jsonFile.lengthSync())
));
}

// Download a file from Google Drive.
  Future downloadFile(String jsonFileName)async {

bool fileExists = false;

    var fileList = await api.files.list();
    fileList.files.forEach((f)async{
        var files = await api.files.list();

        files.files.forEach((f){
          fileId= f.id;
          fileExists = true;
        });
      });

      var file;

      if(!fileExists){
        file = await createDatabaseToDrive( jsonFileName);
      }else{
        file =await api.files.get(jsonFileName);
      }


     return client.readBytes(file.downloadUrl).then((bytes) {
        IOSink stream = new File(jsonFileName).openWrite()..add(bytes);
        return stream.close();
      });
}




}


class GoogleHttpClient extends IOClient {
  Map<String, String> _headers;

  GoogleHttpClient(this._headers) : super();

  @override
  Future<StreamedResponse> send(BaseRequest request) =>
      super.send(request..headers.addAll(_headers));

  @override
  Future<Response> head(Object url, {Map<String, String> headers}) =>
      super.head(url, headers: headers..addAll(_headers));

}

For now i just want a method that i can pass my updated map object, turn it into a .json file and save or create it to drive, and another method to get the file and read it as a Map<> object(without knowing the id of the file, I just tried that by looping trough all the files as you've seen in the code snippet).

Upvotes: 2

Views: 1873

Answers (1)

Alex Totolici
Alex Totolici

Reputation: 366

Found it:

class DriveHelper{
  GoogleSignInAccount  currentUser ;

// Specify the permissions required at login
  GoogleSignIn  _googleSignIn  =  new  GoogleSignIn (
    scopes:  < String > [
      DriveApi . DriveFileScope ,
    ],
  );



  static init(BuildContext buildContext)async{
    DriveHelper driveHelper=DriveHelper();

    driveHelper._googleSignIn.onCurrentUserChanged.listen(( GoogleSignInAccount  account )  {
      driveHelper.currentUser=account ;
    } );
    await driveHelper._googleSignIn.signInSilently ();

    return driveHelper;
  }

  // google sign in
  Future < Null >  handleSignIn ()  async  {
    await  _googleSignIn . signIn ();
  }

  Future handleSignOut()async{
    await _googleSignIn.signOut();
  }




  // Upload a file to Google Drive.
  Future uploadFile(BuildContext buildContext)async {

    if(currentUser==null){
      launchPage(buildContext, WelcomePage());
      return;
    }

    io.Directory documentsDirectory = await getApplicationDocumentsDirectory();
    String path = join(documentsDirectory.path, DatabaseHelper.dataBaseName);

    //
    GoogleHttpClient client = GoogleHttpClient(await currentUser.authHeaders);
    var api = new drive.DriveApi(client);

    var localFile = new io.File(path);
    var media = new drive.Media(localFile.openRead(), localFile.lengthSync());
    drive.File driveFile = new drive.File()..title = DatabaseHelper.dataBaseName;
    return  (await api.files.insert(driveFile, uploadMedia: media,)).id;


  }

  // Upload a file to Google Drive.
  Future deleteFile(BuildContext buildContext,drive.File file)async {

    if(currentUser==null){
      launchPage(buildContext, WelcomePage());
      return;
    }

    //
    GoogleHttpClient client = GoogleHttpClient(await currentUser.authHeaders);
    var api = new drive.DriveApi(client);

    await api.files.delete(file.id);


  }

// Download a file from Google Drive.
  Future downloadFile(BuildContext buildContext,drive.File file) async{

    if(currentUser==null){
      launchPage(buildContext, WelcomePage());
      return false;
    }

    io.Directory documentsDirectory = await getApplicationDocumentsDirectory();
    String path = join(documentsDirectory.path, DatabaseHelper.dataBaseName);

    performDriveRequest(
        buildContext: buildContext,
        file: io.File(path),
        headers: await currentUser.authHeaders,
        url: file.downloadUrl??'',
    );

    return true;
    //
  }

  Future<List<File>> getAllFiles(BuildContext buildContext)async{
    if(currentUser==null){
      launchPage(buildContext, WelcomePage());
      return [];
    }
    GoogleHttpClient client = GoogleHttpClient(await currentUser.authHeaders);
    var api = new drive.DriveApi(client);

    return  (await api.files.list()).items;
  }


  Future performDriveRequest({@required BuildContext buildContext,@required io.File file,@required Map<String,String> headers,@required String url})async{
    HttpClient httpClient = new HttpClient();

    HttpClientRequest request = await httpClient.getUrl(Uri.parse(url));

    headers.forEach((k,v){
      request.headers.set(k, v);
    });

    HttpClientResponse response = await request.close();

    if(response.statusCode==200){
      var _downloadData = List<int>();
      response.listen((d) => _downloadData.addAll(d),
          onDone: () {
            file.writeAsBytes(_downloadData).then((v){
              showDistivityDialog(buildContext, actions: [getButton('Refresh', onPressed: (){
                MyApp.dataModel=null;
                DistivityRestartWidget.restartApp(buildContext);
              })], title: 'Calendars and events downloaded', stateGetter: (ctx,ss){
                return getText('Your calendars and your events from your last saved file from drive are now on your device');
              });
            });
          }
      );
    }else{
      return null;
    }
  }




}


class GoogleHttpClient extends IOClient {
  Map<String, String> _headers;

  GoogleHttpClient(this._headers) : super();

  @override
  Future<IOStreamedResponse> send(BaseRequest request) =>
      super.send(request..headers.addAll(_headers));

  @override
  Future<Response> head(Object url, {Map<String, String> headers}) =>
      super.head(url, headers: headers..addAll(_headers));

}

Upvotes: 2

Related Questions