くま's Tech系Blog

基本的には技術で学んだことを書き留めようと思います。雑談もやるかもね!

Androidでビルドのターゲット分けを行う

今回は、Androidでビルドのターゲット分けを行うようにするにはどうしたらいいのかを書いていきます。

ビルドのターゲット分けというのは開発環境と本番環境など向き先を変えるとうことです。

例えば、開発環境でapkを出力したり、本番環境で出力したりと変更できるようになります。

 ちなみに、iOSで同様なことを行う場合には下記を参照してみてください

kumaskun.hatenablog.com

Androidでターゲットを分ける場合にはプロダクトフレーバーを利用します。

プロダクトフレーバーに関しては、こちらに記載されています。

developer.android.com

では、実際にどうやってプロダクトに追加するか見ていきましょう!

プロダクトフレーバーの設定

プロダクトで設定をする前だとAPKを出力する際には下記のようになっていると思います。

f:id:kumaskun:20210711101839p:plain

実際の設定は下記です。build.gradle(app)で行います。

android {
    flavorDimensions "test"

    defaultConfig {
        applicationId "com.example.myapp"
    }

    productFlavors {
        development {
            dimension "test"
            applicationIdSuffix ".development"
        }

        production {
            dimension "test"
        }
    }
}

公式ドキュメントには下記のように記載があります。

プロダクト フレーバーの作成方法はビルドタイプと同じで、ビルド構成の productFlavorsブロックにプロダクトフレーバーを追加して必要な設定を含めます。defaultConfig が実際には ProductFlavorクラスに属しているため、プロダクト フレーバーでは defaultConfig と同じプロパティがサポートされます。

なので、flavorDimensionsで設定した名前をproductFlavorsdimensionで設定します。

productFlavors配下には開発用と本番用ということでdevelopmentproductionを作成しています。

developmentの方にはapplicationIdSuffixという値が設定されていると思います。

applicationIdSuffixを追加することによってapplicationIdを変更させることができます。

今回の場合だと、開発環境のapplicationIdは「com.example.myapp.development」となります。

プロダクトの指定する内容によって変更してください。

ここまで指定して、ビルドもしくはsyncが成功するとAPKを出力する際には下記のようになると思います。

f:id:kumaskun:20210711103646p:plain

今回追加したdevelopmentとproductionそれぞれで元々あったDebug、Releaseが選択できるようになったと思います。

では、ビルドタイプによって設定値を変えたりする場合にはどうしたらいいでしょうか?

ビルドタイプによって定義を変える

ここでの定義を変えるというのは例えば、APIやWEB画面のURLを変えたりなど、設定値を環境によって変えるということです。

まず、Android Studioでファイル構成をプロジェクトに変えましょう。

そしたら、app配下にproductFlavorsで設定した名前でフォルダを作成します。今回の場合はdevelopmentとproductionでフォルダを作成します。

次に作成したフォルダそれぞれにjavaフォルダを作成して、javaフォルダ配下はapplicationIdの値でフォルダを作成します。

f:id:kumaskun:20210711105307p:plain

それぞれ、applicationIdの値でフォルダを作成したらその配下にConstantファイルなど定義を設定したファイルを作成します。

設定したファイルの値を呼び出せるようになると思うので、それで完成です。

結構シンプルにターゲット分けが行えるので試してみてください

Custom URL Schemeでアプリを起動する

今回はCustom URL Schemeでアプリを起動する方法を書いていきたいと思います。

iOSでは、 cm-app:// のような、アプリ固有のCustom URL Schemeを実装することで、 リンクをタップしてアプリを起動することができます。( ディープリンクとも言います)

ディープリンクを使用すると、スキーム(上記の例ではcm-app)でアプリを識別して起動できます。

また、//( スラッシュ)以降のURL部分でアプリに対して情報を受け渡すことや、Webページからだけでなくアプリ間の遷移にも応用できます。

設定

まずはCustom URL Schemeの設定方法からです。下記、2つの方法があります。

  • info.plistから設定する方法
  • URL Typesから設定する方法

どちらで設定しても同じ結果になります。

今回は、cm-testというスキームを追加します。

①info.plistから設定

まずは、info.plistから設定する方法です。

info.plistに下記のように追加します。

URL Schemesには今回追加するcm-testを設定します。(複数指定できます)

URL identifireにはユニークな識別文字列を設定します。今回はBundle Identifierを設定しました。

②URL Typesから設定

次に、URL Typesから設定する方法です。

TARGET > info > URL Types の+で追加します。

設定後は下記のようになります。

これで、アプリを入れている端末のブラウザで cm-test:// と入力するとアプリを起動するか求められると思います。

起動後の流れ

では、アプリを起動するか求められた後に許可した場合にはどういう流れになるのかみていきたいと思います。

起動したらAppDelegate内の open url メソッドが実行されます。

func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
    print(url)
    print(url.scheme)
    print(url.host)
    print(url.path)
    print(url.query)

    return true
}

上記printしているのはURLのデータが渡ってきているかの確認のためです。

下記に詳細を記載します。(URLはcm-test://hoge/huga?userId=1を仮定します)

  • scheme -> cm-test
  • host -> hoge
  • path -> huga
  • query -> userId=1

このように値が渡ってくるため、渡ってきた情報を使って処理を行うことがほとんどだと思います。

さらに、open url メソッド内で画面遷移の処理を行えば、画面遷移できます。(rootViewなどに気を付けてください)

補足

アプリがインストールされているか知りたい場合にはcanOpenURLメソッドを使用します。

if UIApplication.shared.canOpenURL(URL(string: "アプリに設定してあるスキーム://")!) {
    // アプリがインストールされている
} else {
    // アプリがインストールされていない
}

ただし、info.plistのLSApplicationQueriesSchemesスキーマを設定する必要があります。 LSApplicationQueriesSchemesのTypeをArrayにしてvalueにアプリのスキームを設定してください。

また、アプリがインストールされていない場合にアプリの設定画面に遷移するようにすると思いますが、次のように対象のアップルIDを設定することで アップルストアに遷移することができます。

guard let url = URL( string: "itms-apps://itunes.apple.com/app/id{AppleID}" ) else { return }
UIApplication.shared.openURL( url )

そして、対象のアプリを起動したい場合にはカスタムスキーマを設定した状態でopenURLを実行すると起動できます。

guard let url = URL(string: "xxx://") else { return }
UIApplication.shared.openURL(url)

参照

[Swift] カスタムURLスキームによるアプリ間連携

qiita.com

ラベル(Text)のカスタマイズを行う【iOS】

更新なかなかできず・・・・

定期的には更新したいと思っています

今回はiOSでのラベルテキストのカスタマイズについてです。

わかりやすいようにラベルで記載していきますが、例えば、ボタンのテキストなども同様にカスタマイズできますのでぜひ応用してみてください。

デフォルトのラベルだと下記のようになると思います。

これだと場合によっては要件を満たせずに困ることがあると思います。

今回はそんな時のためにあるAttributedに関する説明です。

ラベルのInspectorを見てみるとTextがPlainになっていると思います。

f:id:kumaskun:20210704201228p:plain

Plainだとラベルのテキストのサイズやフォント色などは指定できますが、できることが限られます。

そこでAttributedに設定を変更してみると設定画面が少し変わると思います。

f:id:kumaskun:20210704201324p:plain

そこでどんなことができるのか少しみてみましょう!

部分的に文字の色を変える

Attributedに設定を変更すると部分的に色を変更することができます。

表示するテキストで色を変えたい部分を選択した状態で赤枠の色を変更する箇所で色を変更することができます。

f:id:kumaskun:20210704202030p:plain

変更するとこんな感じです。

 同様に選択した状態で右クリックするとフォントを変えたりできます。

f:id:kumaskun:20210704203541p:plain

行間を設定する

設定がPlainだと行間がありません。

行間を設定しないと2行分作るときにラベルを2つ設定しないといけなくて大変です。

どうやるかというと、下記の右のボタンを押すと詳細の設定ができる欄が表示されます。その中でSpacingで行間を設定できます。

f:id:kumaskun:20210704204425p:plain

Spacingで10を設定すると下記のようになります。

その他色々設定できるので、ぜひ試してみてください。

今回は個人的によく使うものを記載しましたが、その他様々なことができますので、試してみてください。

また、Attributedソースコードでも実現できるので、必要があれば確認してみてください。

iOSアプリでライセンス表示機能を作る

今回はライセンス機能についてです。

OSSのライブラリをiOSのアプリで利用している場合、使用したライブラリのライセンスをしかるべき場所に記載する必要があります。

ライブラリを追加する度にそれらを手動で更新すると手間になるので、それらをCocoaPodsの仕組みを使いながら自動で更新するようにしたいと思います。

Settings.bundleの作成

Settings.bundleという仕組みを使うことで、簡単にアプリの設定画面を実装することができます。

今回はSettings.bundleを使ってアプリの設定画面を実装し、その中にAcknowledgement(謝辞、ライセンス情報)を表示するようにしたいと思います。

さっそくSettings.bundleを作ってみます。Projectフォルダを右クリックし、 New FileのオプションからSettings Bundleを選択し、ファイルを作成してください。

f:id:kumaskun:20210425163754p:plain

Settings.bundleができたら、その中にあるRoot.plistを書き換えます。

Root.plistはアプリの設定に表示させる項目を設定するファイルです。

Root.plistを右クリックし、Open as > Source Code を選択してください。

下記は一例ですが、下記のように修正してください。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>StringsTable</key>
    <string>Root</string>
    <key>PreferenceSpecifiers</key>
    <array>
        <dict>
            <key>Type</key>
            <string>PSGroupSpecifier</string>
            <key>Title</key>
            <string>Group</string>
        </dict>
        <dict>
             <key>Title</key>
             <string>About</string>
             <key>Type</key>
             <string>PSGroupSpecifier</string>
             <key>FooterText</key>
             <string>Copyright © 2021 sample All Rights Reserved.</string>
         </dict>
         <dict>
             <key>Type</key>
             <string>PSTitleValueSpecifier</string>
             <key>DefaultValue</key>
             <string>1.0.0</string>
             <key>Title</key>
             <string>Version</string>
             <key>Key</key>
             <string>sbVersion</string>
         </dict>
         <dict>
             <key>Type</key>
             <string>PSChildPaneSpecifier</string>
             <key>Title</key>
             <string>Acknowledgements</string>
             <key>File</key>
             <string>Acknowledgements</string>
         </dict>
    </array>
</dict>
</plist>

FooterTextはその名の通り、Footerに表示させる機能で、Versionはバージョンを表示させる機能、Acknowledgementsは謝辞を表示させるためにあります。

続いて、ライセンス用のplistファイルを作成します。

Settings.bundle配下にAcknowledgement.plistを作成します。

Projectのフォルダーを右クリックしNew FileからProperty Listを作成してください。名前はAcknowledgements.plistで いいと思います。

f:id:kumaskun:20210425164639p:plain

作成したら、そのファイルをSettings.bundleの配下に移動させておきましょう。

CocoaPodsによるAcknowledgementsの書き出し

次に、CocoaPodsからOSSのライセンスの情報を直接書き出します。

PodFileに下記設定を追加しましょう。

post_install do | installer |
  require 'fileutils'
  FileUtils.cp_r('Pods/Target Support Files/Pods-(プロジェクト名)/Pods-(プロジェクト名)-acknowledgements.plist', '(Acknowledgements.plistのパス)', :remove_destination => true)
end

上記の設定を追加することでpod installやpod updateでライブラリの更新があった場合に変更が反映されます。

pod installやpod updateを行うことで、Acknowledgements.plistにライセンス情報が格納されます。

上記の設定が終われば、アプリをビルドするとアプリの設定画面から今回の設定した項目が確認できます。

アプリの設定に表示させたくない場合には該当のタグの中身を削除しましょう

アプリの中でライセンスを表示させる場合にはAcknowledgements.plistからライセンスの情報を取得すれば可能です。

Acknowledgements.plistは下記のように追加されているはずです。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>
        <key>PreferenceSpecifiers</key>
        <array>
            <dict>
                <key>FooterText</key>
                <string>○○○○○○○○○○○○○○○○○○○○○○</string>
                <key>License</key>
                <string>MIT</string>
                <key>Title</key>
                <string>○○○○○○</string>
                <key>Type</key>
                <string>PSGroupSpecifier</string>
            </dict>
        </array>
    </dict>
</plist>

FooterTextがライセンス表記、Licenseがライセンス種類、Titleがライブラリ名となります。

info.plistから情報を取得するのと同じようにタグの情報を取得して画面に表示させることが可能です。

if let path = Bundl.url(foeResource: "Acknowledgements", withExtension: "plist", subdirectory: nil, in: Bundle.main.url(forResource: "Settings", withExtensions: "bundle")!) {

    var items: [Any] = []
    
    let acknowledgements = NSDictionary(contentsOf: path)!
    items = acknowledgements["PreferenceSpecifiers"] as! [Any]

    items.removeFirst()
    items.removeLast()
}

removeFirst()とremoveLast()をしているのは最初と最後には関係のない情報が入っているためです。

最後に

ここまでライセンス表記の方法について説明しましたが、LicensePlistというライブラリで実現する方が便利かもしれません。

github.com

ライブラリをforkして使う

今回はライブラリをforkして使う方法です。

あまり使うことはないと思いますが、使いたいライブラリが更新されずに機能を追加したいけどできない場合に一部カスタマイズして使うために使ったりします。

まずは使いたいライブラリを下記をタップして、forkします。

forkすると自分のGithubに取り込まれるはずです。

f:id:kumaskun:20210413104843p:plain

次にPodFileで下記のように記載します。

pod 'ライブラリ名', :git => 'リポジトリのURL', :branch => 'ブランチ(masterなど)'

リポジトリのURLは下記のようにCodeを押すと確認できます。

f:id:kumaskun:20210413104853p:plain

この状態でpod install するとforkしたライブラリが取り込まれるのでカスタマイズしましょう。

そもそもforkせずにpod installして修正すればいいじゃんと思う方もいると思うのですが、そうするとライブラリを更新した際に修正が消えてしまうので、ライブラリをforkして使う方がいい方法と言われています。

iOSアプリのビルドのターゲット分けを行う

今回はiOSアプリのビルドのターゲット分けについて記載しようと思います。

例えば、開発環境と本番環境で処置を分けたい場合やAPIのURLを分けたい場合があると思います。

そんなときに1つのプロジェクトで複数の環境を管理するためにターゲット分けを行います。

ターゲットの作成

まずはターゲットの作成を行います。

下記のように既存のターゲットを右クリックしてDuplicateを選択してターゲットを複製します。

f:id:kumaskun:20210328213103p:plain

ターゲットを複製するとinfo.plistファイルも複製されるので、必要に応じて削除しましょう。(1つのファイルで管理する方が楽だと思います)

設定の追加

次に、Other Swift Flags-D TARGET名を設定します。

この値はプログラム内でTARGET毎に処理を切り替えたい場合に、どのTARGETでビルドされているかを判定するために使います。

Build SettingのOther Swift FlagsにTARGET名を定義します。

f:id:kumaskun:20210405231207p:plain

定義したTARGET名で下記のように条件分岐を行うことができます。

#if DEVELOP
//
#elseif STAGING
//
#endif

Schemeの設定

各TARGETが設定できたら、起動のためのSchemeを作成します。

Schemeを作成することでターゲットごとにビルドすることができます。

まず、Xcode左上のScheme名のところからManage Schemesを選択して、Schemeの一覧を表示します。

f:id:kumaskun:20210405232003p:plain

表示したときに名前が複製したときのものになっている可能性があるので、下記の赤枠で追加・削除することができるのでターゲットを修正しましょう。

f:id:kumaskun:20210405232230p:plain

f:id:kumaskun:20210405232322p:plain

補足

今回のように手間をかけなくてもプロジェクトを新規作成した場合にはDebugReleaseの2種類のターゲットが作られます。

f:id:kumaskun:20210405232621p:plain

なので、下記のようにソースコードで分岐は可能です。

#if Debug
//
#elseif Release
//
#endif

ただ、下記のような場合はターゲット分けの方がやりやすいので、個人的にはおすすめです。

・アプリに含めるリソースを変えたい

・Bundle IdentifierをTARGET毎に変えたい

・ホーム画面に表示されるアプリ名をTARGETによって変えたい

プッシュ通知の許可状況を確認する

今回は小ネタです

プッシュ通知を許可しているかどうか知りたいときありませんか?

そんなときに許可状況を確認するための実装です

 if UIApplication.shared.isRegisteredForRemoteNotifications {
      print("許可している")
} else {
      print("許可していない")
 }

本当に小ネタですが、勉強になったので、ブログにしました!

apkファイルをインストールする

今回はapkファイルをインストールする方法についてです

たまに開発中のものをapkファイルに渡すということありませんか?

そして、渡されたものをインストールして動きを確認することはありませんか?

今回はそんなときにインストールをする方法です

大前提として、端末の「提供元不明のアプリ」を許可してください

adbコマンドを使う

AndroidStudioを使っていることが前提ですが、adbコマンドを使ってapkファイルをインストールすることができます

adbコマンドを使うためには以下の設定が必要です

vi ~/.bash_profile

// Android SDKのパスを記入します
export PATH=$PATH:/Users/ユーザ名/Library/Android/sdk/platform-tools

※SDKのパスはAndroid Studioで「File」>「Other Settings」>「Default Project Structure…」に記載されています

// bash_profileを再度読み込む
source ~/.bash_profile

adbコマンドを使えるようになったら、adbコマンドでapkファイルをインストールします

adb install xxx.apk

xxx.apkはapkファイルを配置しているパスまで移動するかフルパスを指定します

サービスを経由してapkファイルを取り込む

AndroidStudioを持ってなくても端末にapkファイルを取り込むことができます

外部サービスを使えばいいのです

例えば、GmailやSlackやGoogle Driveなどです

ただし、容量の関係で取り込めない可能性があるので、注意です