2023年6月20日火曜日

Google Drive api v3で例外発生

久しぶりに、はまりました。自分でも忘れないように残しておきます。


機能の更新のついでにSDKを33に、gradle-wrapper.propetiesを8.0に上げて、リリース前に念のため、releaseモードで動かしてみたら、Google Drive api V3を使用したバックアップと復元がエラーとなってしまうことに気付きました。

例外の内容は以下です。

com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
{
  "code" : 403,
  "errors" : [ {
    "domain" : "global",
    "message" : "The request is missing a valid API key.",
    "reason" : "forbidden"
  } ],
  "message" : "The request is missing a valid API key.",
  "status" : "PERMISSION_DENIED"
}

API keyなんていままで使っていなかったので、この例外の意味は分かりませんでした。

しかし、releaseモードだけでおかしくなるのは、大抵は、難読化が原因です。


結論から書くと、proguard-rules.proに以下を追加すれば、正常に動作します。
-keep class com.google.api.services.drive.** {*;}
-keep class com.google.api.client.http.HttpHeaders {*;}



1行目は以前から記述していたのですが、今回2行目を追加しました。ここに行きつくのは結構大変でした。

まずは、世界中の誰かが解決していれば楽なので、ネット検索したのですが、見つかりませんでした。

例外の内容に従って、API keyを作成して、設定してみましたが、新たな例外になってしまいました。

あるいは、drive.files.list()等の実行時にトークンが消えているようなので、drive.files.list()実行時にトークンを渡してみると動くが、ダウンロードを行う以下の部分が違うエラーになってしまいました。
drive.files().get(fileId).executeMediaAndDownloadTo()

その他にも四苦八苦したのですが埒が明かないので、大変面倒くさいですが、debugモードとreleaseモードでデバッグをして、ライブラリ内の変数の中身を比較することにしました。
releaseモードでのデバッグは、appのbuild.gradleのbuildTypesのreleaseに以下を追加でできます。

buildTypes {
    release {
        :
        debuggable true
        :
    }
}

そして、com.google.api.client.http.HttpHeaders関連がreleaseモードでは、空になっている部分があり、そのせいで、トークンが消えていたことが分かりました。
proguard-rules.proに前述のkeepの行を追加して動かすと、バックアップも復元も全て正常に動作しました。

以上です。