ttlog

日々の開発で得た知見の技術メモ。モバイルアプリネタが多いです。

GitのリモートURLをクリップボードにコピーする(macOS Only)

リモートリポジトリをcloneする際、既にある別のローカルリポジトリからリモートURLをコピー&ペーストして末尾を少し書き換えてcloneするということをよくやるのですが、

  1. git remote -vでURL表示
  2. マウスで選択して⌘+cでコピー

とやっていたので地味に面倒でした。

ということで、コマンド一発でコピー出来るスクリプトRubyで書いてみました。 originブランチのリモートURLをクリップボードにコピーします。

即席&Rubyほぼ初心者なのでかなり適当です。 また、内部でmacOSpbcopyコマンドを使用しているため、macOSでのみ動作します。

#!/usr/bin/env ruby

git_command = 'git remote -v'
git_result = `#{git_command}`
if git_result.empty?
  puts "Failed to run command: '#{git_command}'"
  exit
end

url = git_result.split("\n")
  .select {|line| line.start_with?("origin")}.first
  .split(" ")[1]

`printf #{url} | pbcopy`

puts "Copied '#{url}'"

初めて知りましたが、String.split(" ")(半角スペース1文字)で空白文字を全部分割してくれるんですね。 なんという便利機能...

docs.ruby-lang.org

fastlaneでAdHoc配布用ipaの作成

環境

  • macOS: 10.14.2(Mojave)
  • Xcode: 10.1(10B61)
  • fastlane: 2.112.0
  • Ruby: 2.5.3

laneの定義

gymアクション(もしくはbuild_ios_appアクション)でビルドやパッケージングに関する処理が出来ます。lane名はここではadhocとします。

gym - fastlane docs

また、署名周りの設定はあらかじめXcode上で完了させておきます。確認時はAutomatic Signingを使用しました。

default_platform(:ios)

platform :ios do

  ...

  desc 'Generate IPA file for AdHoc'
  lane :adhoc do
    gym(
      project: 'XXX.xcodeproj',
      configuration: 'Debug',
      scheme: 'XXX',
      clean: true,
      include_bitcode: false,
      output_directory: './build',
      output_name: 'XXX.ipa',
      export_method: 'ad-hoc'
    )
  end
  
  ...
  
end
  • project: プロジェクトファイル(.xcodeproj)のパスを指定。
  • configuration: Build Configuration(Debug/Release)を指定。
  • scheme: Scheme名称を指定。必ずShared指定になっていることを確認すること。
  • clean: ビルド前にクリーンするかどうか。念の為クリーンするようにしておく。
  • include_bitcode: bitcodeを含めるかどうか。AdHoc配布であれば恐らく不要だと思うのでここでは含めない。
  • output_directory: ipaの出力先ディレクトリ。
  • output_name: ipaファイル名。
  • export_method: AdHoc配布なので'ad-hoc'を指定。

もしworkspace(.xcworkspace)を使っている場合は引数のprojectworkspaceに変更すれば良いでしょう。

gym(
  workspace: XXX.xcworkspace`,
  ...
)

実行

$ fastlane adhoc

以上でプロジェクトルート直下にbuildディレクトリが作成され、その中にipaファイル(XXX.ipa)が作成されるかと思います。

コマンドラインからのiOS Simulator画面のスクリーンショット/録画

simctlコマンドを使用します。

スクリーンショット

$ xcrun simctl io booted screenshot xxx.png

画面の録画

$ xcrun simctl io booted recordVideo xxx.mov

Ctrl+cで録画終了。

バイスの指定

上記コマンド中のbootedの部分は起動中のデバイスを表す特殊文字になるのですが、シミュレータを複数起動中の場合、起動中のデバイスの中からいずれかが勝手に選ばれるようです。この部分をデバイスのUUIDに置き換えることで、シミュレータを複数起動中の場合でも任意のデバイスから取得することが可能です。

バイスのUUIDは以下のコマンドで確認することが出来ます。

$ xcrun simctl list | grep Booted
    iPhone 8 (6F651DD2-XXXX-XXXX-XXXX-XXXXXXXXXXXX) (Booted)
    iPhone XS Max (B437EFCB-XXXX-XXXX-XXXX-XXXXXXXXXXXX) (Booted)
    Phone: iPhone XS Max (B437EFCB-XXXX-XXXX-XXXX-XXXXXXXXXXXX) (Booted)

()内の文字列を使用し、以下のように取得します。

$ xcrun simctl io 6F651DD2-XXXX-XXXX-XXXX-XXXXXXXXXXXX screenshot xxx.png

Xcode10のちょっとした変更点: StoryboardからOutlet/Actionを作成する際のデフォルトConnection

Xcode10でStoryboard上のUIButtonからコード上にConnection(Outlet/Action)を作成する際、挿入位置によってデフォルトで選択済のConnectionが変わるようになっていました。(以前は"Outlet"固定だったかと思います)

具体的には、コードのViewControllerクラスに定義しているメソッドの下に挿入すると、デフォルトのConnectionが"Action"に変わるようです。

  • メソッドの上に挿入しようとする場合、Outletがデフォルトになる

f:id:tommy10344:20181029124357j:plain

  • メソッドの下に挿入しようとする場合、Actionがデフォルトになる

f:id:tommy10344:20181029124410j:plain

メソッド以外の場合は以前までと同様に"Outlet"がデフォルトになるようです。 以下の要素の下に挿入しようとする場合でも、"Outlet"がデフォルトになることを確認しました。

  • Stored Properties
  • Computed Properties
  • Nested Types

ちょっとしたことではありますが、Actionを作ろうとして間違ってOutletを作ってしまったり、いちいちActionに切り替える等の面倒だったことが改善される良い変更だと思います。

Androidエミュレータで動作させるSystem Imageの違い

Android開発時にインストールするエミュレータのSystem Imageの違い、特に「Google APIs」と「Google Play」の違いがよく分かっていなかったのでメモしておきます。

f:id:tommy10344:20181025155133p:plain

Google Play System Image

  • Google Play Storeがインストールされており、実機と同じようにアプリがStoreからインストール出来る
  • root化されていない
  • イメージを動作させる仮想デバイスに制限がある。電話端末だと以下が対応しているようです。(Android Studio 3.2.1時点)

実機に近い環境だと思うので、基本的にはこちらを選択しておけば良さそうですね。

Google APIs System Image

CPU命令セットの違い

参考

Windowsで高速AVDを利用するまでの手順をものすごく詳しく解説

android - Difference between Google API intel x86 atom and Google Play intel x86 atom sytem image - Stack Overflow

adb shellでアプリのプライベートデータを確認する方法

備忘録です。

アプリのプライベートデータは(確認した環境では)/data/data/[アプリのパッケージ名]内にあるようですが、通常のadb shellだけだとパーミッションエラーで中身を確認することが出来ませんでした。

手順

  • adb shell でシェルを起動し、
  • run-as [アプリのパッケージ名]パーミッションを取得する
$ adb shell
shell@xxx:/ $ run-as com.example.foo

(パッケージ名がcom.example.fooの場合)

以上でアプリのプライベートデータを確認することが出来ます。

Android(Xamarin) 文字列の横幅取得方法

Androidにおける文字列の横幅(dp)を取得する方法のメモです。 親Layoutの横幅と比較して、1行に何文字表示出来るか等の計算が出来たりします。

現在Xamarinで開発中のため、コードもXamarin(C#)になってしまっていますが、Android Nativeでも書き方はそう変わらないかと思います。

文字列のサイズ取得

TextViewクラスから取得出来るPaintオブジェクトを使い、MeasureText()を呼び出します。

measureText)

using Android.App;
using Android.Content.Res;
using Android.Util;
using Android.Widget;

namespace XXX
{
    public class StringWidthCalculator
    {
        public double CalculateStringWidth(string str, double fontSize)
        {
            var textView = new TextView(Application.Context);
            textView.SetTextSize(ComplexUnitType.Sp, (float)fontSize);
            var widthOfPixel = textView.Paint.MeasureText(str);
            return widthOfPixel / Resources.System.DisplayMetrics.Density;
        }
    }
}

TextViewにフォントサイズを設定しておくことでフォントサイズに応じた文字列のサイズが取得出来るようです。 ComplexUnitType.Spとしているため、ユーザのフォントサイズ設定に応じて横幅が変動します。

また、MeasureText()で返却される横幅はpixel単位のため、この関数から返却する際にdpに変換しています。

使い方

var str = "abcde";
double fontSize = 13;
var calculator = new StringWidthCalculator();
var width = calculator.CalculateStringWidth(str, fontSize);

サンプルコード

github.com