ionic(cordova) iOSでのtwitterログインで403 Forbidden の対応
はじめに
アプリのコードいじってないのにアプリで実装していたTwitterログインができなくなった。
使っていたプラグインはこちら
https://github.com/ManifestWebDesign/twitter-connect-plugin
エラー内容
error: Request failed: forbidden (403) Error Domain=TWTRNetworkingErrorDomain Code=-1011 "Request failed: forbidden (403)" UserInfo={NSErrorFailingURLKey=https://api.twitter.com/oauth/request_token, NSLocalizedDescription=Request failed: forbidden (403), NSLocalizedFailureReason=Twitter API error : <?xml version="1.0" encoding="UTF-8"?><errors><error code="415">Callback URL not approved for this client application. Approved callback URLs can be adjusted in your application settings</error></errors> (code (null))}
原因
https://apps.twitter.com/
こちらの画面から設定する「Callback URLs」が今までアプリから使用する際は適当な値(http://example.com とか)をセットしていた。が、これにちゃんとした値をセットしないとダメになったというのが原因だった。じゃあアプリから呼び出す際には何をセットすればいいのか?というのでハマった。
対応
https://another.rocomotion.jp/15293882415732.html
こちらのページに救われた。以下をそれぞれ設定する必要がある
Callback URLs (Twitterアプリの設定画面)
twitterkit-xxxxxxx:// (xxxxxxxはtwitterアプリのConsumerKey)
info.plistに以下を追加(Xcode)
<key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleURLSchemes</key> <array> <string>twitterkit-xxxxxxx</string> </array> </dict> </array> ・・・ <key>LSApplicationQueriesSchemes</key> <array> <string>twitter</string> <string>twitterauth</string> </array>
swiftとかで開発していたらこれでOKだけれどもCordovaの場合、プラグイン自体がそのまま使えなかったのでプラグイン自体対応が必要だった。まず、上記のURLから取得したTwitterKitのSDKが古いぽくて動かなかった。Forkしてるリポジトリを探しているとちゃんとSDKも更新してくれてる人がいたのでそれを更にForkしてちょこっといじって解決。上記で書いたinfo.plistへの追記もプラグインが勝手にやってくれる。
そのまま使えるプラグインがこちら
GitHub - nrikiji/twitter-connect-plugin: Cordova/PhoneGap plugin to use Twitter Single Sign on
インストール
$ ionic plugin add https://github.com/nrikiji/twitter-connect-plugin --variable FABRIC_KEY=<Fabric API Key> --variable TWITTER_KEY=<Twitter Consumer Key> --variable TWITTER_SECRET=<Twitter Consumer Secret>
loginとlogoutしか実装されてないので画像の取得とかは必要なら実装しないとならない。以上です
cordova-androidで生成したプロジェクトにSupport Libraryを追加
cordova-androidのバージョンは7.1
プロジェクト作成
$ cordova-android/bin/create android_demo test.android_demo
Gradle Scripts > build.gradle (Module: app)
dependencies { implementation fileTree(include: '*.jar', dir: 'libs') // SUB-PROJECT DEPENDENCIES START implementation project(path: ':CordovaLib') // SUB-PROJECT DEPENDENCIES END }
↓
dependencies { implementation fileTree(include: '*.jar', dir: 'libs') // SUB-PROJECT DEPENDENCIES START implementation 'com.android.support:design:26.1.0' # ★追加 implementation 'com.android.support:appcompat-v7:26.1.0' # ★追加 implementation project(path: ':CordovaLib') // SUB-PROJECT DEPENDENCIES END }
以上です
phpでローカルでwebサーバーを起動して別端末からアクセスする
macでのみ検証した。ビルドインwebサーバーというらしい。あくまで開発支援のための機能なので本番では使わないでねってマニュアルに書いてあった。
同じ端末からのみアクセスする
# サーバー起動 $ php -S localhost:8080 -t path/to/document_root
別端末からもアクセスする
# 自分のip調べる(grepは適当) $ ifconfig | grep 192 inet 192.168.1.110 netmask 0xffffff00 broadcast 192.168.1.255 # サーバー起動 $ php -S 0.0.0.0:8080 -t path/to/document_root
http://192.168.1.110:8080 でアクセスできるようになる。スマホからもみれるし手軽なのがいいね。以上です。
【Javascript】contenteditableなdivでカーソル位置が指定できなかった原因
contenteditableなdivに「今日はいい天気だ」というテキストが存在して「は」の後ろ(前から3文字目)にカーソルを置きたかった。以下のようなコードで実験したけどなぜかカーソルが先頭にきてしまった。
<div id="editor" contenteditable="true"> 今日はいい天気だ </div> <script> window.onload = function() { var editor = document.getElementById('editor') var selection = window.getSelection() var range = document.createRange() range.setStart(editor.firstChild, 3) range.collapse(true) selection.removeAllRanges() selection.addRange(range) editor.focus() } </script>
原因は改行コードとスペースが含まれていたからそこも含めた位置だったというオチだった。。
<div id="editor" contenteditable="true">今日はいい天気だ</div>
ちなみにブラウザからスペースを挿入すると「 」が挿入されるので表示もスペースで表示される。以上です
【Javascript】iOSでblur時にSelection.rangeCountが取得できなかったときに調べたこと
今回やりたかったのはfocusが外れるときの要素を保存しておき、再びfocusがセットされるときにカーソル位置を戻すということ
試したのはこんなコード
<div id="editor" contenteditable="true"></div> <input type="button" id="restore-range" value="restore range" /> <script> var saveRange $('#editor').on('blur', function() { var s = window.getSelection() if (0 < s.rangeCount) { saveRange = s.getRangeAt(0) } }) $('#restore-range').on('click', function() { if (saveRange) { var s = window.getSelection() if (0 < s.rangeCount) { s.removeAllRanges() } s.addRange(range) } }) </script>
PC版のChromeやAndroid端末では期待通りに動くものの、iOS では s.rangeCount の部分が0のため動かず。
iOSではwindow.getSelection().rangeCount や getRangeAtが使えないのかと困っていたが以下のコードだとちゃんと取得できる。
$('#editor').on('mousedown mouseup keydown keyup', function() { var s = window.getSelection() if (0 < s.rangeCount) { range = s.getRangeAt(0) } })
きっとblurの前に更新されてしまうのだろうという想像。どのタイミングがベストかわからないけどとりあえず上記のコードでやりたいことはできるかな。以上です
【cordova】cordovaFileTransfer で params も付けてファイルアップロード
ngCordovaの$cordovaFileTransferの使い方メモ
https://github.com/apache/cordova-plugin-file-transfer のラッパー
$cordovaFileTransfer.upload( 'https://xxx.yyy.zzz/path/to/api' 'path/to/upload_file', { fileKey: 'image', // アップロードするファイル名 httpMethod: 'POST', headers: { // 任意のHTTPヘッダー header1: 'xxxxxx', header2: 'xxxxxx' } params: { // 任意のパラメータ param1: 'xxxxx', param2: 'xxxxx', } } ).then(function() { // success }).catch(function(err) { // failed })
以上です