React NativeのAndroid版のJSブリッジはどうやってるの?

本日はおひさしぶりにyidev に参加。
今回も始終和やかな雰囲気で和みました。

その中で@motokiee さんのReact Nativeの発表を受け、React NativeのAndroid版はどうやってJSとブリッジしているのだろう?という疑問が私を含む一部で湧いたので、Android詳しいわけでもないのですが、軽く調査。

メモ程度ですが何かのお役に立てば幸い。

com/facebook/react/bridge

ふむ、この辺に色々ありますな。。

react-native/ReactAndroid/src/main/java/com/facebook/react/bridge at 9ee815f6b52e0c2417c04e5a05e1e31df26daed2 · facebook/react-native · GitHub

com/facebook/jni

お、jniがいるということは。。

react-native/ReactAndroid/src/main/java/com/facebook/jni at 9ee815f6b52e0c2417c04e5a05e1e31df26daed2 · facebook/react-native · GitHub

ReactCommon/cxxreact/JSCExecutor.cpp

いましたーそれっぽいc++のクラス。loadApplicationScriptという関数でJSをロードしているっぽいですね。

react-native/JSCExecutor.cpp at 1c249e4804030b5691adf508751c369bf0036f1c · facebook/react-native · GitHub

loadApplicationScript内のJSCreateCompiledSourceCode 関数

JSCreateCompiledSourceCodeという関数が使われており、名前からしてこいつがJSから実行形態に動的にコンパイルしているっぽい。しかしこの関数、ググっても出てこない。jscというモジュールがそれっぽいのだけど。

react-native/JSCExecutor.cpp at 1c249e4804030b5691adf508751c369bf0036f1c · facebook/react-native · GitHub

com/facebook/react/bridge/JavaJSExecutor.java

で、こいつがJSCExecutor.cppにブリッジしている子っぽいです。アプリ側からはこいつを介してJSオブジェクト取ってきたりJSの関数実行したりとかやるわけですね。

react-native/JavaJSExecutor.java at 9ee815f6b52e0c2417c04e5a05e1e31df26daed2 · facebook/react-native · GitHub

ひとまずここまでですー。詳しい方是非とも教えてください!

SoLoader (別のライブラリ)

ちなみにこの記事の話題とは直接関係ないですが、jni層(.so)のロードにはfacebook/SoLoaderというのが使われているようでした。

GitHub - facebook/SoLoader: Native code loader for Android

READMEを読むと、

SoLoader is a native code loader for Android. It takes care of unpacking your native libraries and recursively loads dependencies on platforms that don’t support that out of the box.

と書いてあり、どうやら再帰的に.soの依存関係を解決してくれるらしいです。へー何だそれどうなってんだ。

そういえばお久しぶりの投稿になりました。今後も気が向いた時にゆるく投稿していければと思います。

Bitriseをオープンソースプロジェクトで利用したい!

最近Travisのワーカーが一部で不足しており、Xcode8.1をターゲットにすると、ビルドが始まるまで1時間待たされるなんてことがありました。 これではちょっと回らないと思ったので、お試しでBitriseに乗り換えてみました。普段仕事では有料契約をして使っているので、問題ないだろう、と。 なおBitriseは、iOSAndroidに特化したCI/Deliverlyサービス(PaaS)です。

しかし、現状オープンソースで使うには以下の問題があることが判明しました。

  • ビルド結果とログはオーナー及びメンバー以外は見れない。フリープランだとオーナーに対して2名しか登録できない。しかもオーナーアカウントに対して2名までで、プロジェクトに対して2名までではない。 => 2017.1.13追記:変更されたかも
  • ビルド自動再実行の機能がない。Travisだと、プルリクClose->Reopenでビルドが再スタートしますよね。
  • 200 builds/month (これもオーナーのアカウント単位)の制限があり、すぐに超過してしまいそう。超過分はFailedになります。

これではコントリビュータが増えてくると使えないので、slackチャンネルで問い合わせてみました。すると、すぐに以下の回答がありました。

viktorbenei [7:50 PM]  
@toshi0383 thanks for the request/infos!
for the first point please vote & comment here: https://bitrise.uservoice.com/forums/235233-general/suggestions/8795035-allow-public-or-publicly-viewable-apps
for the auto rebuild: please create a new feature request
for unlimited builds per month for OSS project: just send us an email and we can do this for you (if you have one)

というわけで

ビルド結果とログの公開

みなさんvoteよろしく!!!

2017-02-10 追記:URLが変更になりました。 discuss.bitrise.io

ビルド自動再実行機能

機能リクエストしてくれとのことなので、頑張っちゃおうかな!!1 => 機能リクエスト投稿しました。voteよろしく!!

completed
I suggest you ...
  • 1 vote
  • 1 comment

`auto rebuild` for a failed build received from non-authorized users

Closing and Reopening the PullRequest triggers a rebuild like Travis is doing.
Arbitrary PullRequest can trigger a build, so Reopening PullRequest should too.
This way PullRequest's author can restart build without creating Bitrise account.

bitrise.uservoice.com

2017-02-10 追記: discuss.bitrise.io にvoteが足りず移行されなかったので、放置することにします。多分、"allow public build" に含まれる想定でいいのだと思います。

OSSプロジェクトのビルド数制限解除

なんと、言えば対応してくれるらしい!!!神!!!

まとめ

以上、速報でした。 ちなみにBitriseのslack/emailのサポートは対応が神なので、もし何かわからないときは気軽に問い合わせてみると良いと思います。

GitHub開発時の複数リポジトリ横断の課題・ドキュメント管理について

GitHub開発時の複数リポジトリ横断の課題・ドキュメント管理について悩んでいます。

現在のところ最善はこんな感じかしらと書いてみたので、ぜひコミュニティの皆さんのご意見をいただきたいな、と。

よろしくお願いいたします。

ちなみに以前こんなのをQiitaに書きました。

バグトラッキングシステム比較 - Qiita

これまでの社内の標準的な運用は、Backlogで全て解決!です。 社内のやり取りも対外のやり取りも基本Backlogですが、とりあえず社内の部分だけもう少し効率化したいなという状況です。

Backlogではなくtracだ、とか色々あると思いますが、適宜読み替えていただければな、と。

エクセルなどの仕様書の管理

選定条件は、バージョン管理、編集中のロックもしくは同時編集ができることです。 エクセルのマージとかしたくないですよね?

gitを利用すると編集中のロックも同時編集もできないため、Subversionが良いのかな、と。

というわけでここはこれまで通りBacklogのまま。

Wiki

Backlogはマークダウンが特殊で扱いづらいので、GitHub Flavorで書けるのがいいなーと模索中。 あとは非プログラマでも編集できることが条件。

プロジェクト単位のWikiGitHub wikiでもいいですが、部内横断的なWikiの場合、リポジトリ単位だと扱いづらい。

今度これを試してみようと思っています。 https://github.com/GitbookIO/gitbook

まあここはこれまで通りBacklogでもそこまで生産性に影響するものでもないとは思っています。

課題管理

Backlogの課題機能は「通知機能がイケてない、jsの処理が重たい、障害頻度高い、カンバン形式にできない」というのが問題点。

Trelloはリポジトリ関係なく使えて良さそうなのですが、GitHub連携などプラグイン利用時は$9.99 per user / monthで有料。 ボード上でプルリクがグリーンかレッドかが一目でわかるのは良さそうですけど。

カンバン形式でGitHub連携が無料でできるのは、現時点ではwaffle.ioのみ。

例: https://waffle.io/waffleio/waffle.io

ちなみにwaffle.ioは例えばhoge_iOShoge_Androidという風にリポジトリが分かれてしまう場合は、 統合するための親となるhogeリポジトリを別途立て、hoge_iOS, hoge_Androidを子プロジェクトとして追加することで、 統合した課題管理ができます。

https://github.com/waffleio/waffle.io/wiki/FAQs#multirepo

よってwaffle.ioに軍配があがるかなと。

追記

Trelloの場合、リポジトリに権限がなくてもボードは閲覧できるので、何もしなくても1段階の権限管理ができると考えることもできますね。 例えばデザイン会社さんやテスト会社さんにも課題表だけは公開したい、ソースコードは公開したくないみたいな場合にも、Trelloなら気軽にそれができる、と。 うーむ。

そのた

正直言って、IaaSやSaaSでJIRAとかRedmine立てれば解決するような気もしています。あ、でもRedmineプラグイン入れないとカンバンないか。。?

あとGitHub Enterpriseでwaffle使えるのかと思って探したらこんなのを見つけました。お値段しますね。

takeout.waffle.io

できれば、エクセルもWikiソースコードも一箇所でまとめて管理したいところですが、なかなか難しいものですね。

Apple Pay ? In-App Purchase ?

Apple Payが話題になっており、メルカリさんでは既に導入されたとのこと。

あれ、そういえばアプリ外で課金させちゃダメなんじゃなかったっけ。。この辺りのルールがよくわからん!となったので、調べてみました。

結論から言うと、

  • アプリ内で消費するコンテンツに関してはアプリ外課金ダメ。(IAP(アプリ内課金)使ってね)
  • アプリ外で消費するコンテンツに関してはIAP(アプリ内課金)ダメ。(クレジットカードとかApple Pay使ってね。)

ということでした。

ソースはこちら。

アプリ内で消費するコンテンツに関してはアプリ外課金ダメ。

3.1.1 In-App Purchase: If you want to unlock features or functionality within your app, (by way of example: subscriptions, in-game currencies, game levels, access to premium content, or unlocking a full version), you must use in-app purchase.

アプリ外で消費するコンテンツに関してはIAP(アプリ内課金)ダメ。

3.1.5 Physical Goods and Services Outside of the App: If your app enables people to purchase goods or services that will be consumed outside of the app, you must use purchase methods other than IAP to collect those payments, such as Apple Pay or traditional credit card entry. Apps may facilitate transmission of approved virtual currencies (e.g. Bitcoin, DogeCoin) provided that they do so in compliance with all state and federal laws for the territories in which the app functions.

https://developer.apple.com/app-store/review/guidelines/#physical-goods-and-services

と言っても出品されたら取引できちゃうじゃん?と一瞬思いましたが、メルカリの規約にも禁止されている出品物の記述がありました。

  • 物品ではないもの(情報、サービスの提供等)

なるほど。しかし曖昧な。。

  • メルカリ事務局で不適切と判断される商品

ア、ハイなんでもないです。

以上、初歩的でしたがアプリとお金に関する情報でした。

LGTM iOS版をリリースしました

f:id:toshi0383:20161014153142p:plain

どうも @toshi0383 です。この度めでたくLGTM のiOS版をリリースしましたのでお知らせ致します。

LGTM - 高速LGTM画像ピッカー -

LGTM - 高速LGTM画像ピッカー -

  • Toshihiro Suzuki
  • エンターテインメント
  • 無料

早いもので、mac版をリリースしてからもう1年経っていたんですね。

LGTM Macアプリを作りました - 業界とコミュニティに貢献するブログ

こちらはランディングページです。結構かっこいいだろう。

LGTM - LGTM image picker for OSX/macOS

iOS版の見た目はmac版とほぼ同じですが、お気に入りの同期機能を先行して盛り込んでいます。

もともと仕事のプロジェクトチーム内でプルリクエストにおもしろ画像を貼るのが流行っていたというのが元になっているので開発者用ツールとも言えるのですが、単純に使っているだけでもちょっと楽しいので、エンターテインメントのカテゴリにしました。

みなさんのおもしろ画像検索の助けになれば幸いです。

この楽しさをもっと色んな人に共有したいと思い、iOS版は基本無料とし、mac版も少しの間値下げしました。 この機会に面白画像を閲覧して楽しんで見てはいかがでしょうか。

開発の様子

この機会に中のコードを全てSwift2.2からSwift3に移行しました。正直そろそろアプリもライブラリもBreaking Changeが面倒臭いので早いとこObjective-Cくらい枯れてきてほしいものですね、なんて。。

お気に入り機能は、出たばかりのRealm Mobile Platformを利用しています。 今回本当にタイミングが良くて、ちょうどiOS版の開発に取り掛かろうという時に公開されて、そのままエイヤ!で導入しました。 我ながら、新しいものはとりあえずソッコーで使ってみないと気が済まないタイプなのだな、と。。 アプリ側のコードは認証のコードが増えたくらいで済んだので、Realm使っていてよかったーと思いました。

最初Realmのサーバをどこに立てようか迷ったのですが、Realmのslackチャンネルで質問したところDigitalOceanが手軽で良さそうとのことだったので、試して見ています。Realmのslackチャンネルはたくさんの方が参加していて、いち開発者としてとても心強い存在です。

DigitalOcean自体セットアップはとても簡単でした。環境ごとにチュートリアルの記事が充実していて、ほぼコマンドをコピーペーストしただけで終わりました。

あと開発者目線的なポイントとしては、iPad対応でしょうか。近い将来、Xcodeなどの開発環境がiPadに載ることを見越して(載るのか??)、LGTMとしてはiPadマルチタスク対応は外せないと考えていました。時間かかるかと思ってたんですが、全てstoryboardで実装したところ、サイズクラスのことはほとんど気にすることなく勝手にあの縦長の画面に対応することができました。storyboardの威力を改めて思い知った気がします。ま、iPad用のデザインをしていないからというのが大きいのでしょうけど。

まとめ

mac版をリリースした頃はiOSXcodeもまだまだ不慣れでしたが、今では経験も積んで、随分と開発スピードも上がりました。これもひとえに普段勉強会やSNSでお世話になるiOSコミュニティの皆さんのおかげだと思っています。これからも楽しんでアプリ開発続けていければと思っておりますので、宜しくお願い申し上げます。

あと、よかったらストアのレビュー書いてください!😉

LGTM - 高速LGTM画像ピッカー -

LGTM - 高速LGTM画像ピッカー -

  • Toshihiro Suzuki
  • エンターテインメント
  • 無料

クロージャでプロパティを初期化する

Caution! この記事はまだSwift2.2です!

普段何気なく使っているのですが、たぶん初めて見た人は混乱するだろうなと思ったので。

extension UIImage {
    private static var contentPlaceholder: UIImage = {
        return UIImage(named: "placeholder_b.png")!
    }()
    private static var personPlaceholder: UIImage = {
        return UIImage(named: "placeholder_a.png")!
    }()

    private var data: NSData {
        let provider = CGImageGetDataProvider(self.CGImage)
        return CGDataProviderCopyData(provider)!
    }

    var isPlaceholder: Bool {
        return self.data.isEqualToData(UIImage.contentPlaceholder.data)
            || self.data.isEqualToData(UIImage.personPlaceholder.data)
    }
}

一回メモリに載せたらそのあとはそのまま取っておきたいような時は通常普通にstatic変数でいいと思うのですが、初期化処理が1行で書けないみたいな時にこういう書き方ができます。(上の例は1行で書けそうですが)

なお上の場合それが目的ではないですが、lazyロードになりますね。

どこかでこの static varlazy var に再代入した後の挙動についてのスライドを見た記憶があるんですが、見つけられませんでした。

tvOS-10-Sampler

Hey guys I just created a tiny sample app demonstrating tvOS 10 new APIs.

github.com

I open-sourced it because the AVContentProposal API is still buggy and I wanted feedbacks from other developers from the world.

So this is the crash you can experience in tvOS10 Simulator. gyazo.com

The same app won't crash on the device, but user will left with weird screen like this. f:id:toshi0383:20160924190748j:plain

Sorry my AppleTV is in Japanese, but you can see the ContentProposalViewController in front of the first view.

This is the stacktrace.

2016-09-24 19:01:29.520 TVOSTest[87178:254281] Presenting view controllers on detached view controllers is discouraged <TVOSTest.ViewController: 0x7fb02c026e00>.
2016-09-24 19:01:29.543 TVOSTest[87178:254281] *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to activate constraint with anchors <NSLayoutXAxisAnchor:0x60800086f280 "AVFocusProxyView:0x7fb02b542db0.left"> and <NSLayoutXAxisAnchor:0x60800086f540 "AVPlayerLayerView:0x7fb02b40ec50.left"> because they have no common ancestor.  Does the constraint or its anchors reference items in different view hierarchies?  That's illegal.'
*** First throw call stack:

It's obviously AutoLayout's error, but there is nothing I can do because I'm not using any AutoLayouts in this app...

So it's depends on you whether you should use AVContentProposal or not. I will update if I found any workarounds.

Happy tvOS development!!!