Galaxy Note 8 は割と使いにくい形をしている

先週くらいに、念願だったGalaxyNote 8を買った。 1ヶ月前くらいから予約してまで買ったのはこれが初めてだ。 ただ、一週間程度しか使ってなくても、少し後悔し始めている。

まえおき(蛇足)

私はわりとGalaxy Noteのファンのようで、

をこれまで買って使ってきた。

買ってないやつにも理由はあって、 Note4, Note5は動作がモッサリしてたので買ってない。 Note7は買おうとしていたら販売停止になってしまったw

という感じで、だいぶGalaxy Noteを買ってる方だとは思う。

Note 7を買えなかったときから、Note 8はどんな形であろうと買おうと決めていた。 ただファンだったから…。

いざ使ってみると…

f:id:YusukeIwaki:20170930081721j:plain

こんなにペンの使いづらいGalaxy Noteは初めてかも、と感じた。

デザイン重視なのか、ベゼルレスなのがものすごく使いにくいのである。 ペンを使う以上は両手で使うことになるのだけど、左手で持つ時に確実にディスプレイのエリアを持つことになる。また、右手でメモをとるにも宙に浮かせて文字を書くとか無理なので、やっぱり画面に手を置くことになる。 そうなると、この大画面にもかかわらず、まともにメモを取れるエリアが恐ろしく少なくなるのである。これは困る。

あと、端末が全体的にとても滑りやすい加工をされていて、電車の中で揺れたら落としてしまいそうになる。これも困る。

ということで、今のところSペンをまともに使いこなせていない。こんなGalaxy Noteは初めてである。

SペンのないGalaxy S8+で十分だったのではないかと後悔している。

「ちょうどいいサイズ感」は一体どこへ…?

Note 8、開封してさわったときから、実は第一印象があまりよくなかった。

重い & デカい

f:id:YusukeIwaki:20170930082737j:plain

Xperia Z ultraに比べると一回り小さくて軽い。のだけど、左手で持って右手で使うように設計されているZ ultraとは違って、GalaxyNote8はあくまで片手操作の設計だ。

3本の指で支えて親指で操作するには中途半端にでかくて重い。 サイズ感でいうとGalaxy Note 3~5くらいのほうが圧倒的に良かったと思う。

ということで

これから買う方は、 爆発しなくなったGalaxy Note 7 あたりも視野に入れてみてはどうでしょうか。

Railsのxxx_pathとかxxx_urlの引数を調べた

リファレンス読んでもいまいちわからなかったので、そういうときはRailsそのもののソースを読むに限る。

_pathgrepしてみると、

# actionpack/lib/action_dispatch/routing/route_set.rb

  def add(name, route)
    key       = name.to_sym
    path_name = :"#{name}_path"
    url_name  = :"#{name}_url"

    if routes.key? key
      @path_helpers_module.send :undef_method, path_name
      @url_helpers_module.send  :undef_method, url_name
    end
    routes[key] = route
    define_url_helper @path_helpers_module, route, path_name, route.defaults, name, PATH
    define_url_helper @url_helpers_module,  route, url_name,  route.defaults, name, UNKNOWN

    @path_helpers << path_name
    @url_helpers << url_name
  end

bundle exec rake routes したときに出てくるルート情報っぽいものを作ってる場所なんだけど、そこで define_url_helper ってのがあった。きっとこれだ。

# actionpack/lib/action_dispatch/routing/route_set.rb

  # Create a URL helper allowing ordered parameters to be associated
  # with corresponding dynamic segments, so you can do:
  #
  #   foo_url(bar, baz, bang)
  #
  # Instead of:
  #
  #   foo_url(bar: bar, baz: baz, bang: bang)
  #
  # Also allow options hash, so you can do:
  #
  #   foo_url(bar, baz, bang, sort_by: 'baz')
  #
  def define_url_helper(mod, route, name, opts, route_key, url_strategy)
    helper = UrlHelper.create(route, opts, route_key, url_strategy)
    mod.module_eval do
      define_method(name) do |*args|
        last = args.last
        options = \
          case last
          when Hash
            args.pop
          when ActionController::Parameters
            args.pop.to_h
          end
        helper.call self, args, options
      end
    end
  end

ここでさらに UrlHelper というのが出てくる。

# actionpack/lib/action_dispatch/routing/route_set.rb

  def initialize(route, options, route_name, url_strategy)
    @options      = options
    @segment_keys = route.segment_keys.uniq
    @route        = route
    @url_strategy = url_strategy
    @route_name   = route_name
  end

  def call(t, args, inner_options)
    controller_options = t.url_options
    options = controller_options.merge @options
    hash = handle_positional_args(controller_options,
                                  inner_options || {},
                                  args,
                                  options,
                                  @segment_keys)

    t._routes.url_for(hash, route_name, url_strategy)
  end

handle_positional_args… (そろそろメタっぽいコードを見るのが辛くなってきた)

# actionpack/lib/action_dispatch/routing/route_set.rb

  def handle_positional_args(controller_options, inner_options, args, result, path_params)
    if args.size > 0
      # take format into account
      if path_params.include?(:format)
        path_params_size = path_params.size - 1
      else
        path_params_size = path_params.size
      end

      if args.size < path_params_size
        path_params -= controller_options.keys
        path_params -= result.keys
      end
      inner_options.each_key do |key|
        path_params.delete(key)
      end

      args.each_with_index do |arg, index|
        param = path_params[index]
        result[param] = arg if param
      end
    end

    result.merge!(inner_options)
  end

本気で困ったときにもう一回見直すことにしよう・・。

imakaraでやりたかったことなど

昨日、imakaraっていうアプリをリリースしてみた。

play.google.com

きっかけ

「いまから行くからね〜」って言ってから、

「いまどこ?」「○○過ぎたとこ〜」

「いまどこ?」「電車が遅れてて、△△駅でとまってる」

f:id:YusukeIwaki:20170525110500p:plain

↑相手のイメージw

みたいなやりとりをいちいちメッセンジャーでやるのは面倒だ。 そんなやり取りをする時間があるなら、ふつうにネットサーフィンしていたい。

位置情報はべつにいつ抜かれても構わないから、相手が自分の位置を知りたいときに知れるシステムを作ろう、というのがきっかけでした。

やりたかったこと

いわゆる「待ち合わせアプリ」などは、常時測位している。これはものすごく効率が悪い。

GPS測位というのはスマホにおいては非常に電力を食う操作なので、 相手が私の場所を知りたいというのはせいぜい2,3秒であるとすると、その前後数秒だけ測位を行うようにするのが最も効率がいいのです。

サーバーの設計

カッコいいアーキテクチャを使おうとかは全然考えてなくて、 シンプルにRailsでHTTPサーバー1つ作るだけで完結させたい、という意図が強かった。Workerとかは状態管理が面倒なのでなるべく動かしたくない。ということで、

f:id:YusukeIwaki:20170525103823p:plain

イメージ的にはこんな感じでプッシュを使いつつ実現する、ということをやってみました。

アプリの設計

常時測位しない、というのが最大の特徴なのですが、AndroidFLP(Fused Location Provider)のAPI

のように、常時測位を前提としたものしかありません。 なので、

requestLocationUpdateして、1回でも位置情報が取れたらそこでremoveLocationUpdateする という測位サービスを作り、 「測位して〜」プッシュを受け取ったときに、そのサービスを一発叩くようにしました。

あとは、画面ベースでてきとうにつくりました。

より広く使ってもらうために

追跡URLにはディープリンクが仕込んであって、アプリがインストールされていたら、位置をワンショットで示すだけでなく「新しい測位結果」プッシュを受け取って最新の位置情報をつねに見ることができるようになっています。

ただ、「Google playからimakaraっていうアプリをインストールして、それからこのURLを見てね」っていうと、大抵の人はGoogle playでimakaraを見つけられず、単純にブラウザでURLを見て満足してしまいます。 そこで、Firebase Dynamic Linksというのを使って、「アプリが入っていない人にはストアに飛ばし、アプリインストール後、ディープリンクを開く」というのを実現しました。

これにより、Androidにそこまで詳しくない人とか面倒くさがりな人でも、Google Playに飛ばされたときに「インストール」するだけなので、かなりスムーズに追跡URLをアプリで見るところまで到達できます。

さいごに

デザインは超絶適当なんで、フィードバックとかぷるりとかお待ちしています(てきとうw

github.com