2016年12月10日土曜日

[Firebase]Admin Database API -> 引数には何を指定する? Listを御一考

- 私の公開しているandroidアプリでFirebase Realtime Databaseを利用しています
- androidアプリからはイベントの開催情報を読み込むのみです(書き込みはしません)



- 開催情報は定期的にかわるのでFirebase Realtime Databaseの内容は都度更新していく必要があります
- 開催情報を.jsonにする単純なRubyスクリプトをつくってRaspberry piで定期実行させていました
- Firebase Realtime Databaseの更新は手動でインポートしていました……
- 当然ある日、インポートを忘れてしまいました……

- インポートまで自動化できないか調べてみました
- 以前からできたのでしょうが……

- 2016/11/09あたり? Bringing Firebase To Your Server からAdmin SDKというのが紹介されていてこれを使えばうまくいきそうです
- Admin SDKは、NODE.JSとJavaがあって私はNODE.JSがよくわからないのでJavaを使いました(まあどの言語もよくわからないのですが……)

- 詳しくはAdd the Firebase Admin SDK to your ServerGet StartedとかSave Data 等の公式ドキュメントを読んでいただいたほうが正確ですし確実だとおもいますのでそちらをご参照されてください

- 前置きが長くなりましたがなぜ私が記事にしようかとおもったかというと、DatabaseReference#setValue(Object) の引数がよくわかりませんでした
- 公式サンプルだとMap<String, User>になっていて、Mapのkeyを何にすればよいのでしょうか?

- 上の画像には0, 1, 2とか書いてありますが実際の.jsonにはそんなものはありません
- インポートしたあとにRealtime Databaseのほうでつけている? とかもおもいましたがエクスポートしてみて確認してみるとそんなものついていません
- とりあえずmap.put("0", event0); map.put("1", event1);みたいな感じで整数を連番でふってみるとうまくいきました!
- その後、 DatabaseReference#setValue(Object) リファレンスをよくみるとList<Object>もいけると書いてあります!
- 結局List<Event>を指定するとうまくいきました
- ほとんど公式サンプルとかわりありませんが部分的に貼っておきます
DatabaseReference#setValue(Object) を実行すると、DatabaseReferenceが指しているところ以下をすべて書き換えるようです(私はこれを望んでいるのでよかったです)


Map<String, Object> auth = new HashMap<>();
auth.put("uid", "my-service-worker");

FirebaseOptions options = new FirebaseOptions.Builder()
      .setDatabaseUrl("https://databaseName.firebaseio.com")
      .setServiceAccount(new FileInputStream("path/to/serviceAccountCredentials.json"))
      .setDatabaseAuthVariableOverride(auth)
      .build();

FirebaseApp.initializeApp(options);

DatabaseReference ref = FirebaseDatabase
      .getInstance()
      .getReference();

List<Event> events = ...;

DatabaseReference eventsRef = ref.child("events");
eventsRef.setValue(events);



@Setter // Project Lombok
@Getter // Project Lombok
public class Event {

    private String title;
    private String place;
    private String range;
    private long start;
    private long end;

    public Event() {
        super();
    }

    public Event(String title, String place, String range, long start, long end) {
        this();
        this.title = title;
        this.place = place;
        this.range = range;
        this.start = start;
        this.end = end;
    }
}



2016年9月26日月曜日

[Mac]brew updateしてもbrew doctorで警告がでる

$ brew doctor
Please note that these warnings are just used to help the Homebrew maintainers
with debugging if you file an issue. If everything you use Homebrew for is
working fine: please don't worry and just ignore them. Thanks!

Warning: Your Homebrew is outdated.
You haven't updated for at least 24 hours. This is a long time in brewland!

To update Homebrew, run `brew update`.


brew update すればいいのね → 何回やってもbrew doctorで同じこと言われます。

/usr/local/Homebrew/README.md に
## Update Bug なるものが書いてありました。

cd "$(brew --repo)" && git fetch && git reset --hard origin/master && brew update

をやると無事、解決しました。

$ brew doctor
Your system is ready to brew.

---
OS X El Capitan(10.11.6)
iMac (21.5-inch, Late 2012)
---

2016年7月4日月曜日

[Android]android.os.FileUriExposedException

拙著「読書日記」で本の表紙をカメラで撮って、本を検索したり、保存したりする機能があります。
カメラ機能自体は自前では作らず他のアプリを利用しています。

ここに書き込んでくださいね というのを下記のメソッドでUriにして指定していたのですがandroid Nでは動かなくなりました。
android.net.Uri::fromFile(File)

Caused by: android.os.FileUriExposedException: file:///storage/emulated/0/Pictures/jp.torifuku.actionimagecapturesample/1467635903900.jpg exposed beyond app through ClipData.Item.getUri()
  at android.os.StrictMode.onFileUriExposed(StrictMode.java:1799)
  at android.net.Uri.checkFileUriExposed(Uri.java:2346)

ここに議論がありますが、Issueではないそうです。

ファイル システムのパーミッションの変更 というものに該当するそうです。

どうすればいいかというと、概要は下記の通りです。
* android:name="android.support.v4.content.FileProvider"(provider)をAndroidManifest.xmlに追加
* android.support.v4.content.FileProvider::getUriForFile(Context, String, File)でFile -> Uriにする

Android Developersのガイドではここにあります。

今回作ったサンプルをGithubに公開しておきます。
(ポイントを絞って短いサンプルにするつもりが、Runtime Permissionsをやっているとそれなりの長さになってしまいました……)

ラムダ式つかいました。

2016年5月4日水曜日

[android]Secure connection is not supported on Java 6

・MacにAndroid Studio 2.1をインストールして使用していると「Secure connection is not supported on Java 6」というエラーに出くわしました
・Macの場合、IDE(Android Studio)はデフォルトでJava 6を使うようになっているようです

・答えは以下にありました
http://tools.android.com/tech-docs/configuration/osx-jdk
http://stackoverflow.com/questions/36529638/android-studio-cannot-use-secure-connection-for-update-complaining-the-use-of-j

・ターミナルで以下のコマンドを打つとIDEがJava 8を使うようになって、「Secure connection is not supported on Java 6」はでなくなりました

$ export STUDIO_JDK=/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk
$ open /Applications/Android\ Studio.app

※JDKのインストール場所、バージョンは環境にあわせて読み替えてください。

・私は以下のスクリプト(ruby)で起動することにしました


#! /usr/bin/env ruby
INSTALL_DIR = '/Library/Java/JavaVirtualMachines'
LATEST_JDK = Dir::entries(INSTALL_DIR).select { |n| n =~ /^jdk/ }
              .sort_by { |n| n =~ /^jdk(\d+?)\.(\d+?).(\d+?)_(\d+?)\.jdk$/; Regexp.last_match.captures.map(&:to_i) }
              .reverse.first
p LATEST_JDK
EXPORT_STUDIO_JDK = "export STUDIO_JDK=#{INSTALL_DIR}/#{LATEST_JDK}"

`#{EXPORT_STUDIO_JDK}`
`#{'open /Applications/Android\ Studio.app'}`


・上のスクリプトをandroid_studio.rb で保存して chmod +x android_studio.rbしておいて

$ ./android_studio.rb
しています。

Enjoy android!