読者です 読者をやめる 読者になる 読者になる

Androidはワンツーパンチ 三歩進んで二歩下がる

Android卵プログラマーの記録ブログ

ちよだニャンとなる会&千代田区共催「ちよだ猫まつり2017」に行ってきました

ねこ Save Animal

以前のエントリでご紹介したイベントに行ってきました。

chiyoda-nekofes.jp

sakura-bird1.hatenablog.com


直前まで別の用事があったのですが、幸い千代田区役所に近い場所にいたので終了1時間前に駆け込みました。
千鳥ヶ淵を歩いていたら少しだけ桜が咲いていました。

立派な千代田区役所
f:id:sakura_bird1:20170219155611j:plain

f:id:sakura_bird1:20170219155702j:plain

私が行った時はもう終了間近だったんですが、とても盛況でした。
公式のFacebookでも盛り上がっている様子がわかります。
小池都知事も来てたんですね〜。
愛犬家らしいしちょっと好感度あがっちゃう。

公式Facebookより
https://www.facebook.com/chiyodanekofes/


イベントは、猫グッズなどの販売・展示物・講演・譲渡会・企業のブースなどで成り立っており、収益が飼い主のいない猫の医療費などに使われるようになっています。
写真でどんな雰囲気だったかご紹介します。
猫グッズはかわいいものがたくさんあって見ているだけで楽しかったです。

戦利品
f:id:sakura_bird1:20170219231134j:plain


ネコロジーコーナー
f:id:sakura_bird1:20170219155707j:plain

入り口にでかいコーナーが。アルフィー(懐かしくて涙が出るリアルタイム世代。゚(゚´Д`゚)゚。)の坂崎幸之助さんが保護猫活動がまだまだマイナーだった頃に出版した本の新装版の販売コーナーがありました。
「理想は、世の中から不幸なノラ猫が1匹もいなくなること。猫写真とエッセイで綴る、心温まる保護猫たちとの日々。」
販売をなさっていた方から伺ったのですが、ちよだ猫まつりで販売する分は全額寄付だそうでこれは買うしか無いだろうと。
まだ読んでないんですが、Amazonのレビューを見ると非常に良い内容らしく坂崎さんの素晴らしさが伝わってきましたよ。
ハンカチ用意して読もうと思っています(笑)

↓アフィのリンクですいません。普通の商品ページへのリンクがキレイに出来ず。。。


ちよだニャンとなる会のチャリティくじ。はがきが当たりました。
f:id:sakura_bird1:20170219155746j:plain



日本羊毛アート学園佐藤法雪生徒作品展。すばらしくリアルで「おお~」と自然に声が出ます。
表情がすごい。猫を知っている人達が作ったとわかる。
f:id:sakura_bird1:20170219155833j:plain

f:id:sakura_bird1:20170219155839j:plain

f:id:sakura_bird1:20170219155841j:plain

f:id:sakura_bird1:20170219155852j:plain



イベントの目玉であるリアル猫ヘッド。ホントにリアルなんですよ!
f:id:sakura_bird1:20170219160549j:plain



里親さんの家庭で暮らす猫さんの写真展。みんな良かったねえ。
f:id:sakura_bird1:20170219160627j:plain


猫グッズなどの販売コーナーの一部。店舗数多かったです。
f:id:sakura_bird1:20170219155919j:plain


f:id:sakura_bird1:20170219155941j:plain


f:id:sakura_bird1:20170219155945j:plain


f:id:sakura_bird1:20170219160058j:plain


f:id:sakura_bird1:20170219160109j:plain


f:id:sakura_bird1:20170219160115j:plain


f:id:sakura_bird1:20170219160135j:plain


f:id:sakura_bird1:20170219160151j:plain


f:id:sakura_bird1:20170219160320j:plain


f:id:sakura_bird1:20170219160330j:plain


f:id:sakura_bird1:20170219160411j:plain


f:id:sakura_bird1:20170219160524j:plain


短い間だったけど実際に活動してる人をみると自分も何か!って思って良かったです。
最近はボランティア活動といっても明らかに優れたビジネス的なセンスをお持ちの方々を見るにつけ、外の世界を巻き込んで仕組みを作れるってすごいなあ、猫も助かるなあって感心していたところなのですがこちらでもそう感じました。
色々と自分を振り返って思うことがありますが、それはそれでまた!
主催の方々、参加者の方々、千代田区さん、本当にお疲れ様でした。

AndroidのTextUtilsのisEmptyメソッドとJavaのStringのisEmptyメソッドはわりと違う

Android Java

年がら年中使っているAndroidのTextUtilsのisEmptyメソッドとJavaのStringのisEmptyメソッドですが、同じ名前で何が違うのか調べたメモです。
TextUtilsクラスのメソッドは全てstaticで定義されていて、JavaのisEmptyメソッドはインスタンス変数から使用する形になっているという違いはありますが、中身はどうでしょう。
それぞれのコードはこのようになっています。

java.lang.String

   public boolean isEmpty() {
        return count == 0;
    }

※countはfinal int の変数で、Stringオブジェクト初期化時にセットされる文字数です。

android.text. TextUtils

   public static boolean isEmpty(@Nullable CharSequence str) {
        if (str == null || str.length() == 0)
            return true;
        else
            return false;
    }

大きな違いは、TextUtilsのisEmptyメソッドはnullチェックがなされている部分です。
メソッドの引数がnullのオブジェクトが渡されてきてもjava.lang.NullPointerExceptionで落ちませんが、JavaのisEmptyメソッドではインスタンス変数がnullの場合は当然落ちます。

例えば次のコードはNullPointerExceptionが発生します。

    public void onFinish(String example) {
        example = null;
        if (example.isEmpty()) {
            Log.d("Example","exampleがemptyです");
        }

以上です。




「ちよだニャンとなる会」さまが「ちよだ猫まつり2017」を開催するそうです+寄付報告

ねこ Save Animal

こんにちは。さくらです。
2月って猫の月という感じがしますよね。2/22はにゃんにゃんにゃん!ということで猫の日ですし。

f:id:sakura_bird1:20161208110243j:plain

今日は4ヶ月ぶりぐらいに一般社団法人ちよだニャンとなる会に5000円寄付しました。
f:id:sakura_bird1:20170202195445p:plain


前回のエントリはこれです。
sakura-bird1.hatenablog.com

この頃はポケモンGoにはまっていたんですね。
最近は前ほどやらなくなってしまいました。
レベルは31まで上がっていますが、つい数日前やっとメタモンを捕獲したのがニュースって感じですっかり遅れを取っています。
他にも楽しんだスマホゲームあるけど、1ヶ月以上なかなか続かないですね。世の中のおばちゃんたちはどんなゲームを楽しんでいるのでしょう(・・?



ちよだニャンとなる会と千代田区の主催で「ちよだ猫まつり2017」が開催されるそうです!
同時に猫さんの譲渡会も開催するそうです。
chiyoda-nekofes.jp

千代田区|猫|一般社団法人ちよだニャンとなる会|News & Topics 【2月18日(土曜日)、19日(日曜日)に「ちよだ猫まつり2017」を開催します】

千代田区|猫|一般社団法人ちよだニャンとなる会|News & Topics 【2月19日(日曜日)「ちよだ猫まつり2017」会場にて譲渡会を開催します!】


2月18日と19日の二日間に渡って、東京都千代田区役所で開催されるそうです。
昨年は1万2千人もの来場者があったそうで、大変アツいイベントみたいですよ!
収益は、飼い主のいない猫の医療費などに活用されるそうです。

私は両日とも予定があるのですが、もしかしたら19日行けるかも。
行きたいな。こういった活動に携わっている方々に実際お目にかかりたいという気持ちがあります。
ネコ活もそうなのですが、実際に足を運んでみることで違う世界が広がったり、猫や他の動物を大切に思う気持ちが深まったり、携わっている方々へのリスペクトがガッツリ上がったりするので(●´ϖ`●)

超気軽に出来る二時間以内のボランティア、ねこ活に参加してきました - Androidはワンツーパンチ 三歩進んで二歩下がる


ところでなぜこのイベント情報を知ったかというと、以前寄付してから会報を送ってくださっているからです。
逆に言うとこういうアクションをくださらなかったら知ることはなかったので、情報収集について工夫しないとなと思いました。
あと郵送ってやっぱり強いですね。メールで送られたら見落としそう。

会報をちょっとご紹介します。
新しい家族として迎えられた猫さんのエピソードなどが載っています。

f:id:sakura_bird1:20170202143902j:plain

f:id:sakura_bird1:20170202143942j:plain


以上です。





にゃねっとCLUB 会員登録キャンペーン実施中!

歩きやすくて快適だワン!【ドッグランコーティング】

通院・災害時でもペットを思いやれるリュック【ペットキャリー GRAMP】

【Comelu. for Pet ペット向け乳酸菌サプリ】



EventBusライブラリを使っていた箇所をRxJavaで書き換えたよ

Android

もう2年前になりますが、Androidコンポーネント間でイベントを送受信する方法としてEventBusというライブラリを使ってみた記事を書きました。
sakura-bird1.hatenablog.com


似たようなライブラリにOttoというものがありますが、こちらはRxJava・RxAndroidで代替できるためDeprecatedになっています。EventBusライブラリを使ったコードももちろんRxJavaで代替できます。
今更感はありますが、上記記事中のサンプルコードをRxJavaを使って書き換えましたのでご紹介します。
RxJavaの理解が甘かったりするかと思いますが、まろやかなツッコミをいただければ嬉しいです(●´ϖ`●)
RxJavaは1.x系と2.x系で割りと変化していますがこのエントリでは2.x系でコードを書いています。

サンプルコードの仕様

上記のエントリーで作ったサンプルプロジェクトをRxJavaを使ってリファクタリングしています。
(環境のアップデートをしていたり画面のボタンの文言を変えている部分が若干ありますが、機能的には同じものです)
github.com

このサンプルプロジェクトで何をしているかといいますと
・ワーカースレッドからUIスレッドへのイベント通知
・BroadcastReceiver内からFragmentへイベント通知
を行い、イベントを受け取ったFragment内でイベントオブジェクトがもっているStringを画面に表示しています。

画面の動き的には、ボタンを押すと画面に文字が表示されたり、電源のコードを抜き差しすると画面に文字が表示されるという単純なものです。
今回の書き換え時にJackを有効にしてJava8を使用しています。

サンプルコードのGithubリポジトリ

書き換え前のコード全体はこちらです。
GitHub - sakurabird/Android-MyExamEventBus at b1d63ff6533938fab3d95efd050481815e7bb0a1
書き換え後のコード全体はこちらです。
GitHub - sakurabird/Android-MyExamEventBus at use-RxJava-instead-eventbus

実装

イベント発生時に投げるオブジェクトはEventBus版、RxJava版共に共通です。

public class ThreadEvent {
    public final String message;

    public ThreadEvent(@NonNull String message) {
        this.message = message;
    }
}

RxJava版ではイベント送信用のパイプラインになるクラスを作成します。

public class RxBus {

    private static RxBus instance;

    private PublishSubject<Object> subject = PublishSubject.create();

    public static RxBus instanceOf() {
        if (instance == null) {
            instance = new RxBus();
        }
        return instance;
    }

    public void post(Object object) {
        subject.onNext(object);
    }

    public Observable<Object> getObservable() {
        return subject;
    }
}

イベント発生時にイベントオブジェクトを投げる箇所

EventBus版では次のようになります。

EventBus.getDefault().post(new ThreadEvent("スレッドからの通知"));

RxJava版では次のようになります。

RxBus.instanceOf().post(new ThreadEvent("スレッドからの通知"));

イベント受信部分の実装

EventBus版では次のようになります。

       @Override
        public void onStart() {
            super.onStart();
            // EventBusを登録する
            EventBus.getDefault().register(this);
        }

        @Override
        public void onStop() {
            // EventBusを登録解除する
            EventBus.getDefault().unregister(this);
            super.onStop();
        }

ーーー中略ーーー

        public void onEventMainThread(@NonNull final ThreadEvent event){
            ((TextView) getView().findViewById(R.id.TextView)).setText(event.message);
            Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show();
        }

RxJava版では次のようになります。

        @Override
        public void onStart() {
            super.onStart();

            // イベント監視をスタートする
            RxBus.instanceOf().getObservable()
                    .subscribeOn(Schedulers.newThread())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(mThreadEventObserver);

        @Override
        public void onDestroy() {
            super.onDestroy();
            mThreadEventObserver.onComplete();
        }

ーーー中略ーーー

        // Subscriberは再利用できないので、Observerを使う
        private Observer<? super Object> mThreadEventObserver = new Observer<Object>() {
            @Override
            public void onSubscribe(Disposable d) {
            }

            @Override
            public void onNext(Object value) {
                if (value instanceof ThreadEvent) {
                    ThreadEvent event = (ThreadEvent) value;
                    ((TextView) getView().findViewById(R.id.TextView)).setText(event.message);
                    Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show();
                }
            }

            @Override
            public void onError(Throwable e) {
            }

            @Override
            public void onComplete() {
            }
        };

        }

参考サイト様

実装はこちらを参考にさせていただきました。
GitHub - nuuneoi/RxEventBus: A code example of the implementation of RxAndroid & RxJava as an EventBus on Android

RxJavaでイベントバスの機能を実装する考え方はこちらを参考にさせていただきました。
OttoからRxJavaへの移行ガイド - Qiita
RxJava as event bus, the right way – Dionysis’ Lorentzos blog

RxJavaに3日で入門し、Androidアプリのリスト操作、非同期処理、変更通知の課題を解決した話 - Qiita


以上です。





超気軽に出来る二時間以内のボランティア、ねこ活に参加してきました

ねこ Save Animal

こんにちは、さくらです。あっという間に年末ですね。

体調はいかがですか?風邪などお気をつけ下さい。

猫さんたちも寒さに負けないでほしいです。

f:id:sakura_bird1:20161222162511j:plain

 

 

先月記事を書きました。

sakura-bird1.hatenablog.com

 

今月も行ってまいりました。

NPO法人 東京キャットガーディアン〜子猫の里親募集〜

さまで月一で行われているプチボランティア、ネコ活です。

tcg.ldblog.jp

 

22日に開催だからもう5日前なんですが、なんだかんだでブログに書くのが遅くなってしまいました。

 22日も直前までいけるかどうか微妙だったのですが、締切1時間ぐらい過ぎてしまったのにお願いしたら参加させてくださいました。

ネコ活コーディネーター的なTさんは、いつも素晴らしくわかりやすく猫のことを教えてくれる方ですが、私が早く着いたらスカイシェルター(大塚にある東京キャットガーディアンさんの猫カフェ)に居てもよいとメールに書いてくれました。

 

当日は寄付の物資を持って行ってきました。

寄付の物資はホームページ上で不足している支援物資が載っているので参考にしました。古タオルが余っているのを送るだけで支援になるので、お宅で眠っているものがあれば送ってみてください!

支援物資・支援金の募集 - NPO法人 東京キャットガーディアン〜子猫の里親募集〜

 

f:id:sakura_bird1:20161222151628j:plain

上の写真は自宅から持っていったものです。

・古タオルたくさん

・45リットルゴミ袋100枚入り

・ボトム用ハンガー

・薄いビニール手袋100枚入り

・箱ティッシュ10個

すごーーーーく重かったです。

 

猫モフを目当てに2時間は早く行きました。

スカイシェルターに入る際に2千円ほど寄付の箱にいれました。

 

ここの猫達はペットショップとは違って片目が不自由だったり、毛がかなり抜けてしまっていたり、年齢の高めの子も混じっています。雑種が多いですが、血統書がありそうな感じの猫も多いですね。保護猫ですから、殺処分になってもおかしくなかった子ばかりなのですがものすごく可愛い(●´ω`●)

ケージで休んでいるにゃんこも、すきまから手を出してくれたりして

まだまだ我々はこれからの人生なんだ〜〜〜

と叫んでいるようです。

 どうかどうか良いご縁がありますように。

 

 

f:id:sakura_bird1:20161222164218j:plain

 

 

f:id:sakura_bird1:20161222164230j:plain

 

猫さんにかまってもらったよ〜

パソコン開いてたらキーボードの上に乗っかる猫さん。

非常に猫らしい行動にきゅんとします。

 

f:id:sakura_bird1:20161222172221j:plain

 

写真が暗いのは会場が間接照明のみのアダルトな明るさだからです。

猫さんのためを思ってのことと思います。

そして大抵の猫のいる場所では写真のフラッシュが禁止されていますが、こちらもです。

ちなみにここは人間にとっては暑いのですが、猫さんにとっての快適温度を設定しているためだそうです。

おかげで光熱費がすごいらしいですよ。

 

f:id:sakura_bird1:20161222164138j:plain

 

スカイシェルターに行くときは、脱ぎ着で暑さを調節できる服を着ていくようにした方がいいです。

 

今回もタオルを小さく切りました。

収納する場所に当然のように入る猫さんです。

f:id:sakura_bird1:20161222182221j:plain

 

15人近いボランティアが集まりました。

動物病院からいらした方もいて、盛り上がりました。

コーディネーターのTさんが猫のことや保護活動のことについて何でもわかりやすくお答えしてくださるので、非常にためになります。

20年近く猫と暮らしていてもまだまだ知らないことがありますねー。

保護活動の経費なんかも教えてくれるんですよ。

すごいと感心したり大変そうだなと思ったり、好奇心を刺激されます。

猫好きの方、一緒に参加しませんか?

 

f:id:sakura_bird1:20161222181514j:plain

 

東京都豊島区大塚にある東京キャットガーディアンさんのシェルターの1Fはリサイクル店になっており、猫グッズ他がお得に手に入るし運営費の一部になるそうです。

5Fの猫カフェ部分では手作りの猫グッズが販売されており、クオリティ高くて可愛いものがたくさんあります。

この日のネコ活参加の方で手作り品を寄付なさっていた方もいらっしゃいました。

色んな形で支援できます( ´∀`)

 

f:id:sakura_bird1:20161222161118j:plain

 

f:id:sakura_bird1:20161222162002j:plain

 

f:id:sakura_bird1:20161222162027j:plain

 

ということで、2016年も何かと至らない私でしたがお世話になりました。

来年もよろしくお願いいたします!

 

緯度・経度から郵便番号を取得する

Android

Geocoderクラスを使って緯度と経度から郵便番号を取得する方法です。
題名は郵便番号を取得するとなっていますが、住所も取得できます。
自分が郵便番号というキーワードで検索していたため自分用メモです。
developer.android.com


Gercoderを使用して住所(郵便番号)を使用する場合はバックエンドサービスを使用するので、インターネットに繋がっていないと取得が出来ません。
Gercoderが使用可能かどうかはisPresent()メソッドで確認します。
コードのサンプルはこんな感じです。

    private String retrievePostalCode(Location location) {
        final Geocoder geocoder = new Geocoder(getApplicationContext());
        if (geocoder.isPresent()) {
            try {
                List<Address> addresses = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1);
                if (addresses != null) {
                    for (Address address : addresses) {
                        if (address.getLocality() != null && address.getPostalCode() != null) {
                            Log.i(TAG,address.getPostalCode());
                            return address.getPostalCode();
                        }
                    }
                } else
                    Log.i(TAG,"No location found..!");
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            Log.i(TAG,"Geocoder is not present");
        }
        return null;
    }





Rails + Grapeを使って超単純なapiを作ってみる

ruby on rails

初心者の勉強記録です。
「〜らしい」や「っぽい」などの語尾が多くなっています。
手順を書き残すため、主題とは外れた内容も含みます。
間違ったり知識が最新でなかったりすると思いますのでツッコミ大歓迎でございます。


何をやりたいのか

Androidアプリのサンプル用に単純なAPIを作りたい→Grapeというgemを発見した
現在Railsに興味を持って勉強中なのでRailsを使いたい
サーバーにもデプロイしたい

Grapeの何がいいのか

Rest-LikeなAPIを簡単に作れるDSLらしい
きれいなコードを書けるらしい
使っている人が多そうで情報が豊富そう

Railsとgrapeを組み合わせる利点はあるのか

いい感じの形式を強制されるので、一度導入すれば後で拡張と保守が楽になりそう

サンプルで何を作るのか

固定のjson文字列を返すのみのAPIを作る

GET /api/v1/dummy_api/status
{ code: 1 }

公式サイトを拾い読みメモ

APIバージョンをパスに含める構造を取る
APIに関するコードベースをAPIモジュール配下に設置する
・format は:jsonが推奨されているらしく、xml
# We don't like xml anymore とか言われているが使用不可かどうかまでは調べてない

Controllerの定義は次のような形式になる

# app/controllers/api/v1/hussars.rb
module API
  module V1
    class Hussars < Grape::API
      version 'v1' # path-based versioning by default
      format :json # We don't like xml anymore

      resource :hussars do
        desc "Return list of hussars"
        get do
          Hussar.all # obviously you never want to call #all here
        end
      end
    end
  end
end

このコードだとクライアントから呼び出すパスは/v1/hussars.jsonで終わる

/v1/wings.json で終わるパスであればクラスの定義は↓になる。
API::V1::Wings → app/controllers/api/v1/wings.rb
/v2/hussars.json なら
API::V2::Hussars → app/controllers/api/v2/hussars.rb

APIバージョンについて、すべてのリソースをマウントする集約クラスが必要。

# app/controllers/api/v1/base.rb
module API
  module V1
    class Base < Grape::API
      mount API::V1::Hussars
      mount API::V1::Wings
    end
  end
end

v2だと app/controllers/api/v2/base.rb.

すべてのAPIバージョンを集約するクラスが1つ必要。

# app/controllers/api/base.rb
module API
  class Base < Grape::API
    mount API::V1::Base
    mount API::V2::Base
  end
end

最後に集約クラスをroutes.rbに記述する

# config/routes.rb
Monterail::Application.routes.draw do
  # ...
  mount API::Base => '/api'
  # ...
end

ルーティングはこのようになる

/api/v1/hussars.json -> API::V1::Hussars
/api/v1/wings.json -> API::V1::Wings
/api/v2/hussars.json -> API::V2::Hussars

ファイル構造はこのようになる


その他

簡単なアプリではクラスが多くなりすぎるように思えるが、すぐに元が取れる
rescue_from というのが例外のハンドリングメソッド
Swaggerと結合できる

実装を開始する

Railsアプリを新規で作成

$ rails new hogehoge

Railsにgrapeをインストール

Gemfileに記述する

gem 'grape'

$ bundle install ←記述後に実行しておく

config/application.rbを編集

config.paths.add File.join('app', 'api'), glob: File.join('**', '*.rb')
config.autoload_paths += Dir[Rails.root.join('app', 'api', '*')]

app/api配下にapiを作るので、このフォルダを読み込むためにこの記述が必要

ルーティング

config/routes.rbを編集

mount API => '/'

APIクラスを設置する(リソースを集約したクラスでもある)

class API < Grape::API
  prefix 'api'
  version 'v1', using: :path
  format :json

  helpers do
    def dummy_code
      { code: 1 }
    end

    def err401
      error!('401 Unauthorized', 401)
    end
  end

  resource :dummy_api do

    get :status do
      dummy_code
    end

    get :secret do
      err401
    end
  end
end

rake routesと実行すると次のように表示される。Controllerのルーティングと違う。

$ rake routes
Prefix Verb URI Pattern Controller#Action
   api      /           API

このサイト様によると
・「desc〜」で機能の説明を記述できる
・「get」「post」「put」「delete」と、HTTPのメソッドに対応した処理を定義できる
・「params〜」でパラメータを定義し、「require」で必須かを定義している

プライベートメソッドはhelpers内で行うことになっているらしい

検証

ローカルサーバーを立ち上げる
$ rails s

curlコマンドで確認する
$ curl localhost:3000/api/v1/dummy_api/status
{"code":1}
目論見どおり文字列が返ってくる

サーバーにデプロイする

herokuのアカウントを持っているのでそこにデプロイ

$ heroku login
$ heroku create sakurabird1-grape-example
Creating ⬢ sakurabird1-grape-example... done
https://sakurabird1-grape-example.herokuapp.com/ | https://git.heroku.com/sakurabird1-grape-example.git

$ git push heroku master

このようなエラーメッセージが出るので

remote:        Make sure that `gem install sqlite3 -v '1.3.12'` succeeds before bundling.
remote:  !
remote:  !     Failed to install gems via Bundler.
remote:  !     
remote:  !     Detected sqlite3 gem which is not supported on Heroku.
remote:  !     https://devcenter.heroku.com/articles/sqlite3
remote:  !
remote:  !     Push rejected, failed to compile Ruby app.

deployment - Errors of pushing rails app to Heroku error occurred while installing sqlite3, and Bundler cannot continue - Stack Overflow
を参考にGemfileを直す

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug'
  gem 'sqlite3'
end

group :production do
  gem 'pg’
end

$ bundle install ←記述後に実行しておく

変更をcommitした後、最新のコードをHerokuにpush

$ git push heroku master

検証

$ curl https://sakurabird1-grape-example.herokuapp.com/api/v1/dummy_api/status
と実行すると
{"code":1}
とレスポンスが返ってくるので成功

このサンプル置き場

github.com