しがないエンジニアのブログ

技術的な内容をメモ代わりにつらつら

twitterのOAuth認証ではまったこと

最近twitter APIを使ってOAuth認証しようとしたら、以下のようなエラーが出てハマった。

Callback URL not approved for this client application.

これは、callback URLが間違ってるよみたいなこと
2018.6.13以降はちゃんと対応させないとだめになった
なので、アプリ登録したページから、以下のcallback URLを設定
https://developer.twitter.com/en/apps

f:id:turgure:20180907222004p:plain

その後、ソースを変更

twitter.getOAuthRequestToken("app://");

AndroidManifest.xmlも設定してたら変更

<intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="app" />
</intent-filter>

これでヨシ


参考URL

Google Cloud Messaging(GCM)からFirebase Cloud Messaging(FCM)への移行(android)

GCM/FCMとは

GCMとは、android端末のpush通知をサポートするクラウドサービスのこと
しかし、GCMは2019.4.11でサポートが完全に停止する

そのかわり、googleは新しくFCMの利用を呼びかけている
またFCMはandroidだけでなく、iOSもサポート対応のクロスプラットフォームである

移行のきっかけ

なぜ移行しようという話になったのかだが、サポート終了するっていうのは調べ始めてから発覚したこと。
そもそもの理由としては、targetSdkVersion 26以上じゃないとだめだよっていうgoogleのお達しがあったので、バージョンあげたことが発端だった。
2018年8月からtargetSdkVersionをAPIレベル26(Android 8.0)以上にする必要がある

バージョンアップをしたところ、バックグラウンドでの通知が届かなくなってしまったのである。
アプリが開いている状態なら問題なく通知が届くのだが、アプリを終了すると以下のようにエラーがでて落ちてしまっていた。

f:id:turgure:20180904182731p:plain:w300

そしてログもめっちゃ吐かれてた

09-03 16:30:23.564 27698-27698/your-package E/AndroidRuntime: FATAL EXCEPTION: main
    Process: your-package, PID: 27698
    java.lang.RuntimeException: Unable to start receiver com.google.android.gcm.GCMBroadcastReceiver: java.lang.IllegalStateException: Not allowed to start service Intent { act=com.google.android.c2dm.intent.RECEIVE flg=0x1000010 pkg=your-package cmp=your-package/.GCMIntentService (has extras) }: app is in background uid UidRecord{a11f8da u0a520 RCVR idle procs:1 seq(0,0,0)}
        at android.app.ActivityThread.handleReceiver(ActivityThread.java:3267)
        ...

社内の人に相談したところ、「FCM使ってますけどそんなの見たことないですよ?」って言われたので、FCMに移行することにした。

移行の手順

基本的には以下のURLの通りに進めれば問題ない
Migrate a GCM Client App for Android to Firebase Cloud Messaging  |  Cloud Messaging  |  Google Developers

1 . 以下のURLからfirebaseプロジェクトの作成
  https://console.firebase.google.com

google-services.jsonをプロジェクトに追加する必要があるため、その手順

1.1. 対象のプラットフォームを選ぶ(この記事ではandroidを扱う)
f:id:turgure:20180904174238p:plain:w400

1.2. 必要事項の入力
f:id:turgure:20180904171149p:plain:w400

証明書の確認は以下のように行う

$ keytool -v -list -alias androiddebugkey -keystore ~/.android/debug.keystore
$ keytool -v -list -alias <your-key-name> -keystore <path-to-production-keystore>

https://developers.google.com/android/guides/client-auth

1.3. google-services.jsonをダウンロード
  app/直下に配置する
f:id:turgure:20180904171615p:plain:w400

1.4. それぞれのbuild.gradeに追記してsync
  最新のバージョンがあればandroid studioが教えてくれるのでそれに合わせる
f:id:turgure:20180904171857p:plain:w400

1.5. アプリを実行、同期確認
f:id:turgure:20180904172228p:plain:w400

2 . build.gradleの変更
3 . AndroidManifest.xmlの変更

自分が行ったものをdiff形式でぺたり

4 . server endpointsの変更

https://android.googleapis.com/gcm/send

http://fcm.googleapis.com/fcm/send

に変更

5 . その他設定
  それぞれの実装状況に合わせて対応部分を修正

自分の所属プロジェクトでは、真ん中の
Optional: migrate your GcmListenerService
が修正対象でした

簡単に説明すると、AndroidManifest.xmlの変更と、serviceの変更

remoteMessageからデータを取得するとき、一般的な記事ではgetNotification()とかを使ったら値がnullになっていた
そこで、従来どおりintent経由で取得する方法として、toIntent()というまさに求めていた機能があったのでこれを利用
(あとで確認したらgetData()の方にはデータが入ってたのでこっち使ったほうがいいかも?)

Bundle extras = intent.getExtras();

Bundle extras = remoteMessage.toIntent().getExtras();

認証まわりはPHPを使ってたので元から特に書いてなかった

これで無事に今までどおり通知が届くようになった


参考URL

claspを使ったGoogle App Scriptのローカル開発・自動コンパイル

claspとは

claspは、Google App Script(GAS)をローカル環境で開発するためのgoogle製ツールである
ローカルで作業できる一番のメリットは、やはりgitとの連携が可能になることだろう

しかし、gasはES6には対応しておらず、イマドキのjsのコーディングスタイルは使えない
そこで本記事では、本ブログの前回の記事を利用して、

  1. ES6対応のjsコードで開発
  2. babelを使ってECMAScript5へコンパイル
  3. claspを使ってコンパイルしたファイルをgas上のスクリプトと同期(push)

をすべて自動で行えるようにする

claspのセットアップ

1 . claspのインストール

npm install -g @google/clasp

googleアカウントをプロジェクトごとに使い分ける場合はローカルにインストールし、package.jsonのscriptにloginみたいなのを作ればいいと思う

2 . 以下のサイトでGoogle Apps Script APIをオンにする
  https://script.google.com/home/usersettings

f:id:turgure:20180820145215p:plain

3 . ログインする

clasp login

ここまでの作業は最初の一度だけ行えばよい

ローカル環境の構築

claspの設定

clasp create <project_name>

とすれば、gasが連携したアカウントのgoogle drive上に作成され、ローカルに.clasp.jsonappsscript.jsonの2つのファイルが生成される

それぞれ以下のようなファイルになっている


.clasp.jsonに記述するscript idを取得し、手動で作成する
idの場所は
  ・ gasのURL
  ・ ファイル > プロジェクトのプロパティの「スクリプトID」
のいずれかから取得する(どちらも同じid)

前まではプロジェクトキーを使っていたが、現在は変わったらしい
古いプロジェクトだとurlがプロジェクトキーのものになっていて使えないので要注意

f:id:turgure:20180820155836p:plain
f:id:turgure:20180820170546p:plain

そして

clasp pull

を実行することで、google drive上のgasファイルをローカルに同期することができる

.claspignoreの追加

基本的に、ローカルのファイルをgas上に同期(push)しようとすると、すべてのファイルが同期されてしまう
そのため、.claspignoreファイルを作成することで、どのファイルをpushするかを決める(.gitignoreと同じ役割)
このとき、pushするファイルにはappsscript.jsonが必ず含まれていなくてはいけない
以下のようなファイルを作成するとよい(main.jsはgas上に同期するファイル)

(余談)
本来なら、.claspignoreなど作らずとも、.clasp.jsonのプロパティにrootDirなるものが存在し、それを指定すれば自動的にそのディレクトリ内のファイルのみをターゲットとしてpushするファイルを決めてくれるはず、だった。
しかし、appsscript.jsonがどう頑張ってもignoreされてしまい、2018/08/20現在まだその問題が続いている

$ clasp status
Not ignored files:
└─ dist/main.js

Ignored files:
└─ dist/appsscript.json

なので、今は諦めて.claspignoreを使おう
Command Failed: clasp push · Issue #281 · google/clasp · GitHub

babelの設定

前回の記事を参考に構築
そして、package.jsonを以下のように書き換える

"scripts": {
  "start": "watch 'npm run build' src/",
  "build": "node index.js && npm run push",
  "push": "clasp push"
}

build後にclasp pushを実行するコマンドを追加


これで、前回同様

$ npm start

を実行すれば、自動的にgas上のファイルの変更まで行うことができる

gasのファイルを変更しても、ブラウザ更新しないと反映されないので一瞬ドキッとする…
なにか組み合わせてできないものだろうか


参考サイト