Google drive api 如何在Google Drive中查看隐藏的应用程序数据?

Google drive api 如何在Google Drive中查看隐藏的应用程序数据?,google-drive-api,Google Drive Api,我有一个Android应用程序,可以在其中存储我的笔记。我想导出我的笔记,因此问题很简单: 如何访问特定应用程序的Google Drive中隐藏的应用程序数据 用户无法直接访问隐藏应用程序文件夹中的数据,只有应用程序可以访问这些文件夹。这是为用户不应直接操作的配置或其他隐藏数据而设计的。(用户可以选择删除数据以释放数据使用的空间。) 用户访问它的唯一方式是通过特定应用程序公开的某些功能。事实上,谷歌不允许您直接访问这个隐藏的应用程序数据文件夹 但是,如果你可以获得应用程序的客户端ID/客户端机密

我有一个Android应用程序,可以在其中存储我的笔记。我想导出我的笔记,因此问题很简单:


如何访问特定应用程序的Google Drive中隐藏的应用程序数据

用户无法直接访问隐藏应用程序文件夹中的数据,只有应用程序可以访问这些文件夹。这是为用户不应直接操作的配置或其他隐藏数据而设计的。(用户可以选择删除数据以释放数据使用的空间。)


用户访问它的唯一方式是通过特定应用程序公开的某些功能。

事实上,谷歌不允许您直接访问这个隐藏的应用程序数据文件夹

但是,如果你可以获得应用程序的客户端ID/客户端机密/数字签名,用于对谷歌服务器进行身份验证,那么是的,你基本上可以模拟应用程序,并使用驱动器API访问谷歌驱动器中的隐藏数据

它在Android中的工作原理 通常,当安卓应用程序想要访问谷歌API(例如,游戏或谷歌登录-并非所有都受支持)时,它会与进行通信,然后谷歌会代表应用程序从谷歌获得访问令牌。该访问令牌随后随每个请求一起发送到API,以便Google知道谁在使用它以及允许他对您的帐户做什么()。为了第一次获得此访问令牌,Google Play服务向
android.clients.Google.com/auth
发送一个HTTPS POST请求,其中包含以下字段(以及其他详细信息):

  • Token
    -一种“主令牌”,用于标识Google帐户,基本上允许对其进行完全访问
  • app
    -应用程序包名称,如
    com.whatsapp
  • client\u sig
    -应用程序的数字签名(作为SHA1发送)
  • 设备
    -设备的
  • 服务
    -应用程序希望拥有的(权限)
因此,在我们开始以特定应用程序的名义使用驱动API之前,我们需要知道它的签名和我们帐户的主令牌。幸运的是,可以很容易地从
.apk
文件中提取签名:

shell> unzip whatsapp.apk META-INF/*
       Archive:  whatsapp.apk
          inflating: META-INF/MANIFEST.MF    
          inflating: META-INF/WHATSAPP.SF    
          inflating: META-INF/WHATSAPP.DSA
shell> cd META-INF
shell> keytool -printcert -file WHATSAPP.DSA   # can be CERT.RSA or similar
       .....
       Certificate fingerprints:
       SHA1: 38:A0:F7:D5:05:FE:18:FE:C6:4F:BF:34:3E:CA:AA:F3:10:DB:D7:99
       Signature algorithm name: SHA1withDSA
       Version: 3
接下来我们需要的是主代币。当添加新的google帐户时(例如,首次设置手机时),通过向同一URL发出类似请求,通常会接收并存储此特殊令牌。不同之处在于,现在请求权限的应用程序是Play services应用程序本身(
com.google.android.gms
),谷歌还获得了额外的
Email
Passwd
参数来登录。如果请求成功,我们将取回主令牌,然后将其添加到用户的应用程序请求中

有关身份验证过程的更多详细信息,请参阅

把它们放在一起 现在,我们可以直接使用这两个HTTP请求编写身份验证代码——一个可以使用任何Google帐户浏览任何应用程序文件的代码。只需选择您最喜欢的编程语言和。我发现使用以下方法更容易:

require\uuuuuu DIR\uuuuuuuuu.'/供应商/autoload.php';//谷歌硬盘API
//HTTPS身份验证
$masterToken=getMasterTokenForAccount(“您的_username@gmail.com“,“您的密码”);
$appSignature='38A0F7D505FE18FEC64FBF343ECAAF310DBD799';
$appID='com.whatsapp';
$accessToken=getGoogleDriveAccessToken($masterToken、$appID、$appSignature);
如果($accessToken==false)返回;
//初始化Google驱动器客户端
$client=新的Google_客户端();
$client->setAccessToken($accessToken);
$client->addScope(Google\u Service\u Drive::Drive\u APPDATA);
$client->addScope(谷歌服务驱动::驱动文件);
$client->setClientId(“”;//客户端id和客户端机密可以留空
$client->setClientSecret(“”;//因为我们假装是安卓客户端
$service=新的谷歌服务驱动器($client);
//打印最多10个文件的名称和ID。
$optParams=阵列(
“空格”=>“appDataFolder”,
'字段'=>'下一个GetOken,文件(id,名称)',
“页面大小”=>10
);
$results=$service->files->listFiles($optrams);
如果(计数($results->getFiles())==0)
{
打印“找不到文件。\n”;
} 
其他的
{
打印“文件:\n”;
foreach($results->getFiles()作为$file)
{
打印$file->getName()。“(“$file->getId()。”)\n”;
}
}
/*
$fileId='1KTFG5TMGIGTPJUVYNWHKXXLPGZ32QNPJCE5JXL8DTN0';
$content=$service->files->get($fileId,array('alt'=>'media'));
echo var_dump($content);
*/
函数getGoogleDriveAccessToken($masterToken、$appIdentifier、$appSignature)
{
如果($masterToken==false),则返回false;
$url='1https://android.clients.google.com/auth';
$deviceID='0000000000000000';
$requestedService='oauth2:https://www.googleapis.com/auth/drive.appdata https://www.googleapis.com/auth/drive.file';
$data=array('Token'=>$masterToken',app'=>$appIdentifier',client\u sig'=>$appSignature',device'=>$deviceID',google\u play\u services\u version'=>'8703000',service'=>$requestedService',has\u permission'=>'1');
$options=array(
“http'=>数组(
“标题”=>“内容类型:应用程序/x-www-form-urlencoded\r\n连接:关闭”,
'方法'=>'发布',
'content'=>http\u build\u query($data),
“忽略错误”=>TRUE,
“协议_版本”=>“1.1”,
//'代理'=>'tcp://127.0.0.1:8080“,//用于调试的可选代理
//'request_fulluri'=>true
)
);
$context=stream\u context\u create($options);
$result=file\u get\u contents($url,false,$context);
if(strpos($http\u response\u头[0],'200ok')==false)
{ 
/*处理错误*/
打印“请求访问令牌时出错:”。$result。“\r\n”;
返回false;
}
$startsAt=strpos($result,“Auth=”)+strlen(“Auth=”);
$endsAt
Files:
gdrive_file_map (1d9QxgC3p4PTXRm_fkAY0OOuTGAckykmDfFls5bAyE1rp)
Databases/msgstore.db.crypt9    (1kTFG5TmgIGTPJuVynWfhkXxLPgz32QnPJCe5jxL8dTn0)
16467702039-invisible (1yHFaxfmuB5xRQHLyRfKlUCVZDkgT1zkcbNWoOuyv1WAR)
Done.
private void listFiles() {
        Query query =
                new Query.Builder()
                        .addFilter(Filters.or(Filters.eq(SearchableField.MIME_TYPE, "text/html"),
                                Filters.eq(SearchableField.MIME_TYPE, "text/plain")))
                        .build();
        getDriveResourceClient()
                .query(query)

                .addOnSuccessListener(this,

                        new OnSuccessListener<MetadataBuffer>() {
                            @Override
                            public void onSuccess(MetadataBuffer metadataBuffer) {
                                //mResultsAdapter.append(metadataBuffer);

                                for (int i = 0; i <metadataBuffer.getCount() ; i++) {
                                    retrieveContents(metadataBuffer.get(i).getDriveId().asDriveFile());
                                }
                            }
                        }

                )
                .addOnFailureListener(this, new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        Log.e(TAG, "Error retrieving files", e);
                        MainActivity.this.finish();
                    }
                });

    }
public void retrieveContents(DriveFile file) {

        Task<DriveContents> openFileTask =
                getDriveResourceClient().openFile(file, DriveFile.MODE_READ_ONLY);



        openFileTask.continueWithTask(new Continuation<DriveContents, Task<Void>>() {
            @Override
            public Task<Void> then(@NonNull Task<DriveContents> task) throws Exception {
                DriveContents contents = task.getResult();

                try (BufferedReader reader = new BufferedReader(
                        new InputStreamReader(contents.getInputStream()))) {
                    StringBuilder builder = new StringBuilder();
                    String line;
                    while ((line = reader.readLine()) != null) {
                        builder.append(line).append("\n");
                    }

                    Log.e("result ", builder.toString());
                }

                Task<Void> discardTask = MainActivity.this.getDriveResourceClient().discardContents(contents);
                // [END drive_android_discard_contents]
                return discardTask;
            }
        })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {

                    }
                });


    }