如何访问应用程序特定文件夹并使用它来备份或某些应用程序特定数据?迅速

2024-02-19

我想创建一个应用程序,其中某些类型的数据将同步到应用程序特定文件夹中的谷歌驱动器,并且可以进一步访问它以检索数据并填充到应用程序中。如果不知何故用户的手机丢失并且用户使用另一部手机,并且当用户登录同一谷歌帐户时,应该获取该数据。

My problem is I am not aware the steps to follow to do this, I am able to create the app folder over google drive and this is showing to end user over drive enter image description here

现在,当我尝试在其中插入数据时出现范围错误。 我使用的代码是:

import Foundation
import GoogleAPIClientForREST

enum GDriveError: Error {
    case NoDataAtPath
 }

class ATGoogleDrive {

private let service: GTLRDriveService

init(_ service: GTLRDriveService) {
    self.service = service
}

public func listFilesInFolder(_ folder: String, onCompleted: @escaping (GTLRDrive_FileList?, Error?) -> ()) {
    search(folder) { (folderID, error) in
        guard let ID = folderID else {
            onCompleted(nil, error)
            return
        }
        self.listFiles(ID, onCompleted: onCompleted)
    }
}

private func listFiles(_ folderID: String, onCompleted: @escaping (GTLRDrive_FileList?, Error?) -> ()) {
    let query = GTLRDriveQuery_FilesList.query()
    query.pageSize = 100
    query.q = "'\(folderID)' in parents"

    service.executeQuery(query) { (ticket, result, error) in
        onCompleted(result as? GTLRDrive_FileList, error)
    }
}

public func uploadFile(_ folderName: String, data: Data, MIMEType: String, onCompleted: ((String?, Error?) -> ())?) {

    search("config.json") { (folderID, error) in

        if let ID = folderID {
            self.upload(ID, data: data, MIMEType: MIMEType, onCompleted: onCompleted)
        } else {
            self.createFolder(folderName, onCompleted: { (folderID, error) in
                self.upload("", data: data, MIMEType: MIMEType, onCompleted: onCompleted)
            })
        }
    }
}

private func upload(_ parentID: String, data: Data, MIMEType: String, onCompleted: ((String?, Error?) -> ())?) {

    let metadata: GTLRDrive_File = GTLRDrive_File()
    metadata.name = "config.json"
    metadata.parents = ["appDataFolder"]

    let uploadParameters: GTLRUploadParameters = GTLRUploadParameters(data: data, mimeType: "application/json") 
    uploadParameters.shouldUploadWithSingleRequest = true;
    let query: GTLRDriveQuery_FilesCreate = GTLRDriveQuery_FilesCreate.query(withObject: metadata, uploadParameters: uploadParameters)//[GTLRDriveQuery_FilesCreate queryWithObject:metadata
     query.fields = "id"
     self.service.executeQuery(query) { (ticket, fileN, error) in
        print(ticket)
        print(fileN)
        print(error)
        if let f = fileN as? GTLRDrive_File {
            if (error == nil) {
                print("File ID %@", f.identifier);
            } else {
                print("An error occurred: %@", error);
            }
        } 
      }
    }

public func listFromAppFolder(_ parentID: String, data: Data, MIMEType: String, onCompleted: ((String?, Error?) -> ())?) {
    let file = GTLRDrive_File()
    file.name = "\(Date().timeIntervalSince1970)"
    file.parents = ["appfolder"]

    let uploadParams = GTLRUploadParameters.init(data: data, mimeType: MIMEType)
    uploadParams.shouldUploadWithSingleRequest = true

    let query = GTLRDriveQuery_FilesCreate.query(withObject: file, uploadParameters: uploadParams)
    query.fields = "id"

    self.service.executeQuery(query, completionHandler: { (ticket, file, error) in
        print(ticket)
        print(file)
        print(error)
        onCompleted?((file as? GTLRDrive_File)?.identifier, error)
    })
}

public func download(_ fileID: String, onCompleted: @escaping (Data?, Error?) -> ()) {
    let query = GTLRDriveQuery_FilesGet.queryForMedia(withFileId: fileID)
    service.executeQuery(query) { (ticket, file, error) in
        onCompleted((file as? GTLRDataObject)?.data, error)
    }
}

public func search(_ fileName: String, onCompleted: @escaping (String?, Error?) -> ()) {
    let query = GTLRDriveQuery_FilesList.query()
    query.pageSize = 1
    query.q = "name contains '\(fileName)'"

    service.executeQuery(query) { (ticket, results, error) in
        onCompleted((results as? GTLRDrive_FileList)?.files?.first?.identifier, error)
    }
}

public func createFolder(_ name: String, onCompleted: @escaping (String?, Error?) -> ()) {
    let file: GTLRDrive_File = GTLRDrive_File()
    file.name = "config.json"
    file.parents = ["appfolder"]
    let query = GTLRDriveQuery_FilesCreate.query(withObject: file, uploadParameters: nil)
    query.fields = "id"

    service.executeQuery(query) { (ticket, folder, error) in
        onCompleted((folder as? GTLRDrive_File)?.identifier, error)
    }
}

public func delete(_ fileID: String, onCompleted: ((Error?) -> ())?) {
    let query = GTLRDriveQuery_FilesDelete.query(withFileId: fileID)
    service.executeQuery(query) { (ticket, nilFile, error) in
        onCompleted?(error)
    }
  }
 }

并用于登录并使用下面的类

import UIKit
import GoogleSignIn
import GoogleAPIClientForREST

class ViewController: UIViewController {

@IBOutlet weak var resultsLabel: UILabel!

fileprivate let service = GTLRDriveService()
private var drive: ATGoogleDrive?

override func viewDidLoad() {
    super.viewDidLoad()

    setupGoogleSignIn()

    drive = ATGoogleDrive(service)

    view.addSubview(GIDSignInButton())
}

private func setupGoogleSignIn() {
    GIDSignIn.sharedInstance().delegate = self
    GIDSignIn.sharedInstance().uiDelegate = self
    GIDSignIn.sharedInstance().scopes = [kGTLRAuthScopeDriveFile]
    GIDSignIn.sharedInstance().signInSilently()
}


@IBAction func uploadAction(_ sender: Any) {
    if let documentsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last {
        let dataImg: Data = UIImageJPEGRepresentation(UIImage(named: "logo.png")!, 1.0)!
        drive?.uploadFile("config.json", data: dataImg, MIMEType: "image/png") { (fileID, error) in
            print("Upload file ID: \(fileID); Error: \(error?.localizedDescription)")
        }
       }
     }

    @IBAction func listAction(_ sender: Any) {
    drive?.listFilesInFolder("config.json") { (files, error) in
        guard let fileList = files else {
            print("Error listing files: \(error?.localizedDescription)")
            return
        }

        self.resultsLabel.text = fileList.files?.description
        print(fileList)
        for nFile in fileList.files! {
            if nFile.mimeType == "image/jpeg" {
                self.drive?.download(nFile.identifier!, onCompleted: { (data, error) in
                    print(data)
                    print(error)
                })
              }
            }
          }
        }
      }

     // MARK: - GIDSignInDelegate
     extension ViewController: GIDSignInDelegate {
     func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
    if let _ = error {
        service.authorizer = nil
    } else {
        service.authorizer = user.authentication.fetcherAuthorizer()
        service.shouldFetchNextPages = true
    }
  } 
 }

    // MARK: - GIDSignInUIDelegate
    extension ViewController: GIDSignInUIDelegate {}

每当我尝试上传任何文件时,都会出现错误:

Error Domain=com.google.GTLRErrorObjectDomain Code=403 "The granted scopes do not allow use of the Application Data folder." UserInfo={GTLRStructuredError=GTLRErrorObject 0x281515d10: {message:"The granted scopes do not allow use of the Application Data folder." errors:[1] code:403}, NSLocalizedDescription=The granted scopes do not allow use of the Application Data folder.}

您需要设置谷歌驱动器配置的范围,

GIDSignIn.sharedInstance().scopes = [kGTLRAuthScopeDriveAppData]

参考 驱动范围 https://developers.google.com/drive/api/v3/about-auth#what-scope-or-scopes-does-my-app-need-?

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何访问应用程序特定文件夹并使用它来备份或某些应用程序特定数据?迅速 的相关文章

  • Swift - UICollectionView 重复(重复)单元格

    你好 我有一个数组 其中包含从 flickr 获取的 100 张图片 url 当我使用 UICollectionView 时 我显示 100 个单元格 屏幕上只有 8 个单元格 当我向下滚动查看下一个 8 个单元格时 它们与前一个单元格相同
  • Swift 在调试和发布模式下的行为不同

    不确定这是否是 Swift XCode 或 Alamofire 的问题 但我认识到我的混合 Swift Objc 应用程序中不同地方的奇怪行为 它只发生在用 Swift 编写并使用闭包 网络的部分 这是发生这种情况的示例代码 Alamofi
  • SwiftUI:为表单中的单元格添加动画

    我正在尝试动画化我的Form或者更确切地说是其中的细胞 我的问题是 下面的代码给了我一个很好的插入动画 但是对于删除 单元格在看起来很丑陋的延迟后突然被删除 import SwiftUI struct ContentView View St
  • 在 swift 中发送自定义 HTTP 标头

    我设法从服务器获取 json 但现在我想通过 http 标头添加额外的安全性 这就是我的代码现在的样子 let urlPath http www xxxxxxxx com let url NSURL string urlPath let s
  • 使用 Google Advanced Drive 服务通过 Apps 脚本在文件夹中创建新文件

    创建新文件有四种方法 DocsList 显示为DocsList在主列表中 内置于 Apps 脚本中 DriveApp 显示为Drive在主列表中 内置于 Apps 脚本中 驱动器 API 也显示为Drive在主列表中 必须添加到 Apps
  • 在 iOS Swift 2 中实现“阅读更多”按钮以展开 UITextView 的最简单方法?

    我希望实现一个 阅读更多 按钮 该按钮将扩展 UITextView 以便有人可以根据需要阅读整个文本 我还没有找到一种简单的方法来实现这一目标 我尝试 玩弄 容器的高度 但它没有给我想要的结果 我真的很感激任何想法 我会推荐你 ilyapu
  • 快速检查网络速度

    我想从我的 swift 应用程序检查网络速度 我发现很多帖子描述了Reachability特别是查找连接是否可达以及是 WIFI 连接还是 WWAN 连接的方法 我的问题 是否可以检测 WWAN 的类型 2G 3G 4G 你可以用以下命令检
  • 我可以在 Swift 3 项目中使用 Swift 2.3 框架吗?

    在我的项目中 我将所有私有 swift 2 3 文件迁移到 swift 3 我想使用用 swift 2 3 编写的遗留框架 直到它们有 swift 3 版本 我尝试添加 使用旧版 Swift 版本 是 清除 构建我的项目 但我仍然遇到一些麻
  • SwiftUI 上带有 TextField 的可删除表

    环境 Xcode 11 2 1 11B500 Problem 为了在 SwiftUI 中实现带有 TextField 的可编辑表格 我使用了ForEach 0
  • SwiftUI:如何让项目的拖放重新排序起作用?

    我有以下 SwiftUI 视图 struct ContentView View State var model Model var body some View ScrollView LazyVGrid columns columns sp
  • Swift UI 导出画布内容

    我有一个画布 用户可以在上面画东西 我想导出用户在画布上绘制的任何内容 并且我正在使用以下扩展从视图中获取图像 extension View func snapshot gt UIImage let controller UIHosting
  • SwiftUI 检测用户何时截取屏幕截图或屏幕录制

    On UIViewController我们可以轻松地将观察者添加到控制器 喜欢 class ViewController UIViewController override func viewDidLoad super viewDidLoa
  • Swift 中的 @autoreleasepool 相当于什么?

    在 Swift 中 我注意到没有 autoreleasepool 构造 尽管 Swift 确实使用了 ARC 在 Swift 中管理自动释放池的正确方法是什么 或者它是否因某种原因被删除 语法如下 autoreleasepool code
  • 是否可以对 UILabel 的文本颜色变化进行动画处理? [复制]

    这个问题在这里已经有答案了 UIView animateWithDuration 5 animations myLabel textColor UIColor redColor 标签文本颜色立即改变 Try this UIView tran
  • 如何在 Swift 中使用 deltaTime 正确计算 1 秒

    我正在尝试计算经过的秒数deltaTime但我不知道该怎么做 因为我的deltaTime不断打印 0 0166 或 0 0167 这是我的代码 override func update currentTime CFTimeInterval
  • 视频中的图像/文本叠加 swift

    我正在使用 swift 在视频中使用图像叠加来实现水印效果 我正在使用AVFoundation为此 但不知何故我没有成功 以下是我的覆盖图像 文本的代码 let path NSBundle mainBundle pathForResourc
  • 如何找到安全区域的高度和宽度?

    我正在尝试以编程方式为某些标签 按钮和文本字段设置相对于安全区域的高度和宽度的约束 例如 我希望将标签到安全区域顶部的距离设置为安全区域高度的 10 如何检索安全区域的高度和宽度 这是一个合理的方法吗 我的想法是 无论 iOS 设备如何 我
  • 通过 IOS Google Drive SDK 列出 Google Drive 的所有文件夹

    实际上我将 google drive sdk 与我的 ios 应用程序集成了 我可以通过适用于 iOS 的 google drive sdk 在 Google Drive 上上传指定文件 此外 我想提供一个功能 用于从可用文件夹中选择一个文
  • 从 HealthKit 获取昨天的步数

    我正在构建一个供个人使用的应用程序 目前我正致力于如何从 healthkit 中准确获取昨天的步数 然后从那里将其放入变量中 我知道应该很容易 我有一个 HealthKitManager 类 它从视图内部调用该函数 然后将其附加到同一视图中
  • 无法在 Swift 的 Storyboard 中加载 UIViewController XIB 文件

    我读了使用 XCode 故事板实例化使用 XIB 进行设计的视图控制器 https stackoverflow com questions 9155719 using xcode storyboard to instantiate view

随机推荐

  • 寻找用于在细分域上进行数值积分的 Python 包

    我想知道是否有人知道基于 numpy scipy 的 python 包 可以在镶嵌域 在我的具体情况下 由 voronoi 单元格界定的 2D 域 上对复杂的数值函数进行数值积分 过去 我使用了 matlab 文件交换之外的几个包 但如果可
  • Netbeans 外部控制台错误

    我正在尝试使用 netbeans 在 Windows 10 中 在 C 中编译一个简单的 hello world 程序 但是出现以下错误 sh cygdrive c Users myuser 1 AppData local Temp dli
  • 如何获得随机数,每个数字都有自己的概率[重复]

    这个问题在这里已经有答案了 例如 我想从集合 S 0 1 2 3 中获取随机数 但现在每个数字都有不同的概率 而不是每个数字都有相同的显示概率 即 25 比如说 50 30 20 10 我该如何编码 在 Java 或 C 中 我更喜欢 C
  • 在共享内存中初始化 pthread 互斥体

    我可以使用初始化器初始化静态内存中的互斥体 pthread mutex t mymutex PTHREAD MUTEX INITIALIZER 但是如何在共享内存中初始化一个变量 在该内存中我必须与初始化变量分开分配内存 我可以执行 mem
  • 怎样才能让到处下雨呢?

    我想创建一个下雨效果我的天气应用程序 https thewthr app 仅使用 CSS 然而 尽管我在外观上取得了令人满意的结果 但我似乎无法让它们连续覆盖整个屏幕 而不仅仅是随机的块 我该怎么办 body overflow hidden
  • 获取 Dexie 中的 GroupBy 计数

    我有一个索引数据库下表接受以下结构化 JSON 作为一行 id 1 name doc1 createdDate 2018 08 08 我想计算表中每个可用日期的数量 IE groupby 日期然后计数 预期示例输出的格式为 2018 08
  • 如何区分堆栈 DICOM 图像和概览图像?

    I have a stack of DICOM coronal images where I have used the Image Position Patient 0020 0032 tag to sort the images in
  • PHPUnit 接收系统日志消息吗?

    我正在使用打开日志的方法测试记录器类 如下所示 openlog this gt identifier this gt option this gt facility syslog level message closelog The fac
  • 将库的文档添加到手册页

    我正在使用 Ubuntu 12 04 1 我正在学习使用 C 中的 FFmpeg 库制作一个基本的视频播放器 我的手册页没有显示库的标题 函数的任何条目 有人可以告诉我一种将文档添加到我的手册页的方法吗 这样搜索比每次都在网页上搜索要容易得
  • 如何检查groovy脚本的编译错误[重复]

    这个问题在这里已经有答案了 我们可以使用下面的代码在运行时创建并运行 groovyscript import groovy lang GroovyClassLoader import groovy lang GroovyObject imp
  • 如何将数据传递到 MSBuild 任务的 ITaskItem 属性?

    我有一个自定义任务 我在其中使用MSBuild 效果很好 以前 我有一些属性接受一些string数据 有人建议我应该将它们更改为ITaskItem的 这样 如果我有空间 就不会有问题 以前的代码 public class Compresso
  • 使用 facebook-android-sdk 4 未触发登录回调

    我有一个活动供用户使用 Facebook 登录 我使用 facebook android sdk v4 0 0 但是当用户点击登录按钮时 不会触发登录回调 显示进度条后 自动开始之前的活动 日志上不显示任何错误 而不是触发登录回调 在注册活
  • WCF 如何启用元数据?

    我正在尝试让我的 svc 文件在 IIS 下工作 在我的项目中 当我按 F5 时 svc 就开始工作了 所以我知道一切都好 对吗 IIS 除外 我正在 Windows XP Pro 计算机上工作 并在 IIS 中添加了一个虚拟目录 这是我的
  • Android MapView 带有滑动菜单遮挡菜单

    我在使用此滑动菜单的活动中有一个 android 地图 api v2 的地图视图https github com iPaulPro SlidingMenu https github com iPaulPro SlidingMenu 除了在地
  • WSO2 ESB - 用 Base64 写入文件

    我有一个代理 它接受包含 Base64 编码文件的 XML 文件 例如 XML 如下所示
  • Async Servlet - 首选实现

    最近 在研究异步处理时Servlets 我至少遇到了三种实现方法 使用这种方法的一些功能 问题是 哪一个是最好的 也许其中一些方法不推荐 也许还有另一种方法比下面提到的所有方法更好 找到的方法 Using AsyncContext star
  • Flutter安装在windows环境变量中

    我在尝试首先在桌面上安装 flutter 时遇到问题 出现以下错误 不被识别为内部或外部命令可操作程序或批处理文件 然后我打开系统环境变量并将 flutter 添加到用户变量路径 并将所有 flutter git system32 添加到系
  • silverlight/wcf ria 中的部分实体加载和管理

    我有一个 Silverlight 4 应用程序 它使用 WCF RIA 服务从数据库中提取实体 这些数据对象相当简单 只有几个字段 但其中一个字段包含任意大小的二进制数据 应用程序基本上需要在用户登录后尽快访问这些数据 以在列表中显示 启用
  • X509 主题备用名称 (subjectAltName) IP 地址字段

    X509v3 可以包含IP地址字段在subject Alternative Name扩大 作为验证服务器身份的应用程序 IP地址字段应该如何验证 DNS 名称和 IP 地址是否都存在 是否存在对其中一种的偏好 有什么用dirName fie
  • 如何访问应用程序特定文件夹并使用它来备份或某些应用程序特定数据?迅速

    我想创建一个应用程序 其中某些类型的数据将同步到应用程序特定文件夹中的谷歌驱动器 并且可以进一步访问它以检索数据并填充到应用程序中 如果不知何故用户的手机丢失并且用户使用另一部手机 并且当用户登录同一谷歌帐户时 应该获取该数据 My pro