Google 드라이브 앱 데이터 백업
구글 로그인
앱 데이터 읽기 및 쓰기 범위에는 Google 계정 로그인이 필요합니다. 세부 구현은 를 참조할 수 있습니다.
드라이브 API 사용
사이드 메뉴에서
Enabled APIs & Services로 이동하여 + ENABLE APIS AND SERVICES를 클릭합니다.
검색
google drive api .

활성화
Google Drive API를 클릭합니다.
Flutter 프로젝트 구성
flutter pub add googleapis를 실행하여 googleapis 플러그인을 프로젝트에 추가합니다.GoogleDriveAppData 라는 클래스를 만듭니다. 로그인 논리도 이 클래스에 포함됩니다. Google 드라이브의 앱 데이터 저장소를 사용할 것이므로 범위를 drive.DriveApi.driveAppdataScope 에 추가합니다.import 'package:google_sign_in/google_sign_in.dart';
import 'package:googleapis/drive/v3.dart' as drive;
class GoogleDriveAppData {
/// sign in with google
Future<GoogleSignInAccount?> signInGoogle() async {
GoogleSignInAccount? googleUser;
try {
GoogleSignIn googleSignIn = GoogleSignIn(
scopes: [
drive.DriveApi.driveAppdataScope,
],
);
googleUser =
await googleSignIn.signInSilently() ?? await googleSignIn.signIn();
} catch (e) {
debugPrint(e.toString());
}
return googleUser;
}
///sign out from google
Future<void> signOut() async {
GoogleSignIn googleSignIn = GoogleSignIn();
await googleSignIn.signOut();
}
}
드라이브 API를 클라이언트와 함께 사용하기 위해 드라이브 API 요청과 함께 인증 정보를 전달하기 위한
GoogleAuthClient 클래스를 생성합니다.실행
flutter pub add http하여 http 패키지를 가져옵니다.import 'package:http/http.dart' as http;
class GoogleAuthClient extends http.BaseClient {
final Map<String, String> _headers;
final _client = http.Client();
GoogleAuthClient(this._headers);
@override
Future<http.StreamedResponse> send(http.BaseRequest request) {
request.headers.addAll(_headers);
return _client.send(request);
}
}
GoogleDriveAppData 클래스로 돌아갑니다.드라이브 클라이언트 인스턴스를 생성하는 기능을 추가합니다.
import 'package:google_drive_app_data/google_auth_client.dart';
class GoogleDriveAppData {
...
///get google drive client
Future<drive.DriveApi?> getDriveApi(GoogleSignInAccount googleUser) async {
drive.DriveApi? driveApi;
try {
Map<String, String> headers = await googleUser.authHeaders;
GoogleAuthClient client = GoogleAuthClient(headers);
driveApi = drive.DriveApi(client);
} catch (e) {
debugPrint(e.toString());
}
return driveApi;
}
}
Google 드라이브에는 특히 앱의 파일 저장을 위한 앱 데이터 폴더가 있습니다. 파일이
appDataFolder에 저장됩니다.파일의 기본 이름을 쉽게 가져오기 위해 경로 패키지를 추가하려면 실행
flutter pub add path하십시오.drive.File는 드라이브가 가지고 있는 파일 정보를 저장하고 있습니다.io.File는 장치가 가지고 있는 로컬 파일인 io 파일입니다.파일이 이전에 드라이브에 업로드된 경우
driveFileId를 사용하여 드라이브에 최신 버전 파일을 업데이트할 수 있습니다.import 'dart:io' as io;
import 'package:path/path.dart' as path;
class GoogleDriveAppData {
...
/// upload file to google drive
Future<drive.File?> uploadDriveFile({
required drive.DriveApi driveApi,
required io.File file,
String? driveFileId,
}) async {
try {
drive.File fileMetadata = drive.File();
fileMetadata.name = path.basename(file.absolute.path);
late drive.File response;
if (driveFileId != null) {
/// [driveFileId] not null means we want to update existing file
response = await driveApi.files.update(
fileMetadata,
driveFileId,
uploadMedia: drive.Media(file.openRead(), file.lengthSync()),
);
} else {
/// [driveFileId] is null means we want to create new file
fileMetadata.parents = ['appDataFolder'];
response = await driveApi.files.create(
fileMetadata,
uploadMedia: drive.Media(file.openRead(), file.lengthSync()),
);
}
return response;
} catch (e) {
debugPrint(e.toString());
return null;
}
}
}
ID, 버전 및 수정 시간과 같은 드라이브의 파일 정보를 얻으려면 다음 기능을 사용하여 파일 목록을 가져오고 파일 이름을 업로드된 파일과 비교할 수 있습니다.
class GoogleDriveAppData {
...
/// get drive file info
Future<drive.File?> getDriveFile(
drive.DriveApi driveApi, String filename) async {
try {
drive.FileList fileList = await driveApi.files.list(
spaces: 'appDataFolder', $fields: 'files(id, name, modifiedTime)');
List<drive.File>? files = fileList.files;
drive.File? driveFile =
files?.firstWhere((element) => element.name == filename);
return driveFile;
} catch (e) {
debugPrint(e.toString());
return null;
}
}
}
드라이브 파일을 로컬로 다운로드하려면 다음 기능을 사용할 수 있습니다. 기본적으로 데이터 스트림을 다운로드하고 새 파일에 씁니다.
class GoogleDriveAppData {
...
/// download file from google drive
Future<io.File?> restoreDriveFile({
required drive.DriveApi driveApi,
required drive.File driveFile,
required String targetLocalPath,
}) async {
try {
drive.Media media = await driveApi.files.get(driveFile.id!,
downloadOptions: drive.DownloadOptions.fullMedia) as drive.Media;
List<int> dataStore = [];
await media.stream.forEach((element) {
dataStore.addAll(element);
});
io.File file = io.File(targetLocalPath);
file.writeAsBytesSync(dataStore);
return file;
} catch (e) {
debugPrint(e.toString());
return null;
}
}
}
전체
GoogleDriveAppData 클래스는 다음과 같습니다.import 'dart:io' as io;
import 'package:flutter/foundation.dart';
import 'package:google_drive_app_data/google_auth_client.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:googleapis/drive/v3.dart' as drive;
import 'package:path/path.dart' as path;
class GoogleDriveAppData {
/// sign in with google
Future<GoogleSignInAccount?> signInGoogle() async {
GoogleSignInAccount? googleUser;
try {
GoogleSignIn googleSignIn = GoogleSignIn(
scopes: [
drive.DriveApi.driveAppdataScope,
],
);
googleUser =
await googleSignIn.signInSilently() ?? await googleSignIn.signIn();
} catch (e) {
debugPrint(e.toString());
}
return googleUser;
}
///sign out from google
Future<void> signOut() async {
GoogleSignIn googleSignIn = GoogleSignIn();
await googleSignIn.signOut();
}
///get google drive client
Future<drive.DriveApi?> getDriveApi(GoogleSignInAccount googleUser) async {
drive.DriveApi? driveApi;
try {
Map<String, String> headers = await googleUser.authHeaders;
GoogleAuthClient client = GoogleAuthClient(headers);
driveApi = drive.DriveApi(client);
} catch (e) {
debugPrint(e.toString());
}
return driveApi;
}
/// upload file to google drive
Future<drive.File?> uploadDriveFile({
required drive.DriveApi driveApi,
required io.File file,
String? driveFileId,
}) async {
try {
drive.File fileMetadata = drive.File();
fileMetadata.name = path.basename(file.absolute.path);
late drive.File response;
if (driveFileId != null) {
/// [driveFileId] not null means we want to update existing file
response = await driveApi.files.update(
fileMetadata,
driveFileId,
uploadMedia: drive.Media(file.openRead(), file.lengthSync()),
);
} else {
/// [driveFileId] is null means we want to create new file
fileMetadata.parents = ['appDataFolder'];
response = await driveApi.files.create(
fileMetadata,
uploadMedia: drive.Media(file.openRead(), file.lengthSync()),
);
}
return response;
} catch (e) {
debugPrint(e.toString());
return null;
}
}
/// download file from google drive
Future<io.File?> restoreDriveFile({
required drive.DriveApi driveApi,
required drive.File driveFile,
required String targetLocalPath,
}) async {
try {
drive.Media media = await driveApi.files.get(driveFile.id!,
downloadOptions: drive.DownloadOptions.fullMedia) as drive.Media;
List<int> dataStore = [];
await media.stream.forEach((element) {
dataStore.addAll(element);
});
io.File file = io.File(targetLocalPath);
file.writeAsBytesSync(dataStore);
return file;
} catch (e) {
debugPrint(e.toString());
return null;
}
}
/// get drive file info
Future<drive.File?> getDriveFile(
drive.DriveApi driveApi, String filename) async {
try {
drive.FileList fileList = await driveApi.files.list(
spaces: 'appDataFolder', $fields: 'files(id, name, modifiedTime)');
List<drive.File>? files = fileList.files;
drive.File? driveFile =
files?.firstWhere((element) => element.name == filename);
return driveFile;
} catch (e) {
debugPrint(e.toString());
return null;
}
}
}
결과
로그인으로 간단한 위젯을 만들고 업로드 기능을 호출해 봅시다.
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final GoogleDriveAppData _googleDriveAppData = GoogleDriveAppData();
GoogleSignInAccount? _googleUser;
drive.DriveApi? _driveApi;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
GoogleAuthButton(
onPressed: () async {
if (_googleUser == null) {
_googleUser = await _googleDriveAppData.signInGoogle();
if (_googleUser != null) {
_driveApi =
await _googleDriveAppData.getDriveApi(_googleUser!);
}
} else {
await _googleDriveAppData.signOut();
_googleUser = null;
_driveApi = null;
}
setState(() {});
},
),
ElevatedButton(
onPressed: _driveApi != null
? () {
FilePicker.platform.pickFiles().then((value) {
if (value != null && value.files[0] != null) {
File selectedFile = File(value.files[0].path!);
_googleDriveAppData.uploadDriveFile(
driveApi: _driveApi!,
file: selectedFile,
);
}
});
}
: null,
child: Text('Save sth to drive'),
),
],
),
),
);
}
}

업로드 성공 후 드라이브 웹 포털로 이동하여 설정을 클릭하면.

사이드바에서
Manage Apps를 선택하면 앱 목록에 앱이 나타납니다.
참고: 이전 기사에서 한 번 로그인한 경우 계정에 드라이브 앱 데이터 권한이 포함되어 있지 않은 경우 파일을 업로드할 때 403이 발생할 수 있습니다. 계정에서 앱 데이터 권한을 허용하려면 한 번 로그아웃했다가 로그인하거나 다른 방법으로 계정을 허용해야 합니다.
내용이 마음에 드셨다면 지원해주세요🍖
연결🍻
Reference
이 문제에 관하여(Google 드라이브 앱 데이터 백업), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/maylau/google-drive-app-data-backup-2bnh텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)