20200426のAndroidに関する記事は7件です。

Unityのモバイルゲーム向けクラッキングが行われるポイントを整理してみた

免責事項

この記事に記載されている内容を、実際に試して発生した損害に対していかなる責任も負いません(補償しません)。
すべて自己責任のもとで行ってください。

リリースされているアプリやゲーム、ソフトウェア利用許諾契約(EULA)やアプリケーション利用規約などでリバースエンジニアリングは禁止されています。
実際に試す場合は、自分で開発しているアプリやゲームや脆弱性確認用でリリースされているアプリやゲームを使いましょう。

勘違いして理解しており、誤ったことを記載しているところもあるかもしれません。
実際に対策を行うときは、専門家に相談してください。

はじめに

目的

Unityのモバイルゲーム向けセキュリティ関連覚書 - Qiita」の資料を全部読むのは大変です。 1
理解が進みやすいように、クラッキングが行われる目的ポイント対策を整理してみました。
なるべく一般的な名称を使っているつもりです。長くなるため細かく解説をつけていません。
必要に応じて、覚書で調べるか、ググっていただけると助かります。(各種対応方法の詳細も覚書を確認してください)

ここ間違っている、ここもう少し詳しくなどコメントもらえると助かります。

対応方法

この後に出てくる対応方法は、書かれている対応を行えば絶対に安全というものではありません。
基本、無限のコスト(人と時間)をかけられる攻撃者の方が有利です。
どこまで対応する必要があるかは、守りたい情報やアセットの重要度と、実装(対応)コストを、勘案する必要があります。

暗号化

エンコーディング(base64など)は、暗号化ではありません。
暗号化は、System.Security.CryptographyなどでAESやRAS使用したもののことを指しています。

暗号化にも強度があります。現在のPCでは暗号強度が弱いものだと解析されてしまいます。
適切な暗号強度のアルゴリズムと暗号化キーをを設定する必要があります。
(ハッシュアルゴリズムにも強度があります。適切なアルゴリズムを選択する必要があります。)

その他

Unityのモバイルゲームと銘打っていますが。
「WindowsやmacOSのPC環境」、「AndroidやiOS環境ネイティブアプリやゲーム」、「PlayStation 4、Xbox One、Switchなどコンソール機」、「Webサービスやゲーム」でもクラッキングのターゲットになり対策が必要です。

クラッキングの目的

私見になりますが。 2
ゲームをクラッキングする目的としては、「人より有利に進めたい」、「技術的興味」、「営利目的」などが考えられます。

  • 人より有利に進めたいは、「他の人に(お金を使わないで)簡単勝ちたい」、「時間短縮」、「欲しいユニットやアイテムを簡単に手に入れたい」などが考えられます。有利とは別に、元画像、3Dモデル、音楽データが欲しいなども考えられます。
  • 技術的興味は、対処のゲームがどのような構造で作られているか、セキュリティーを破りたいなど自分の欲求を満たすため。また、技術力を見せるためにクラッキングの方法やツールを公開することもあります。3
  • 営利目的は、「人より有利に進めたい」人でクラッキング能力がない人向けに、簡単に使えるクラッキングツール、改造済みのゲームアプリ、アカウントを提供して利益をえる。また、サービスを攻撃して停止に追い込み要求をだしたり。ユーザーデータなど価値あるものを手に入れて販売したりすることが考えられます。

対策が必要な条件は、上記の目的を持つ人が現れる場合に行う必要があります。
対策は守りたいポイントを明確にして、必要処置を行いましょう。
セキュリティ対策を後から入れる場合は、最初から対策よりもコストが高くなります。4

全体像

Unityのモバイルゲーム向けクラッキングが行われるポイントを整理してみた.png

大きく分けて、クライアント、ネットワーク、サーバに対するクラッキングのポイントを記載していきます。

  • クライアントは、クライアント内にある情報に対する攻撃
  • ネットワークは、クライアントとサーバ間で行う通信に対する攻撃
  • サーバは、サーバ内にある情報に対する攻撃

クライアント

スマートフォン(Android、iOS)端末内で行われる、クラッキングの内容と対策になります。

静的解析

プログラムが実行されていない状態で解析を行うことです。

パッケージ

Androidはapkファイル。iOSはipaファイル。
root(Android)、jailbreak(iOS)状態の端末から環境で取得したり、専用サイトを使用してダウンロードできる。(Androidはroot化してなくても端末から取り出せるかも)

apk、ipa共にzipファイルのため解凍するだけで中身をみることができます。
パッケージ情報の一部ファイルはプレーンテキストではなく、バイナリファイルに変換されています。
変換ツールを使ってプレーンテキストに戻すことができます。(apktoolツールなど)

改変したものをインストールするためには、apk、ipa共にパッケケージを再署名する必要があります。

実行ファイル

Windowsでいうと.exe。macだと.app(正確には実行許可ビットが立っているファイル)。

逆コンンパイル(逆アセンブル)を行われた場合に、可読性の高い状態でコードが復元されてしまいます。

  • ソースコードに実際使われないなコードやメソッドを挿入する
  • ソースコードを難読化(関数名や変数名を推測しにく名前に変えるなど)し、逆コンンパイルをされても解析しにくいようにする

セーブデータや通信時の暗号化キー、開発用サーバのエントリーポイントなどをconst、static
readonlyなどで文字列定義すると。
実行ファイル内にそのまま文字列として含まれる。逆コンパイルや「strings」コマンドなどで文字列を発見されてしまいます。

  • 不要な情報は含めないようにする
  • 暗号化や難読化する
  • 常にサーバから取得する(ローカルには保存しないようにする)

アセット

Unityだと、シーンファイル、シーンから参照しているリソースファイル、Resourcesフォルダ内のファイル、StreamingAssetsフォルダ内のファイルなどが対象になります。

シーンファイル、Prefab、画像、3Dモデル、音声データ、フォントなどが同梱されます。対処方法は「静的解析→ストレージ→アセット」の項目を参照してください。
マスターデータが含まれる場合もあります。対処方法は「静的解析→ストレージ→マスターデータ」の項目を参照してください。

ストレージ

ストレージは、ROMと表現される内蔵ストレージ。AndroidはSDカードで拡張した領域も含みます。
root(Android)、jailbreak(iOS)端末や、デバッグが許可されているアプリケーションの場合ストレージのデータにアクセスして取得できます。

AndroidのSDカードに書き込んだデータは、PCに接続してマウントしたり、SDカードリーダで簡単に読み出すことができます。

アカウント

ユーザーを識別する必要がある場合には、どのユーザーか認識するためにUUIDや専用アカウントを準備すると思います。
独自で実装する場合して、PlayerPrefs、テキストファイル、バイナリファイルに保存する場合は注意する必要があります。

プレーンテキスト、PlayerPrefs、バイナリファイルに保存すると内容がテキストエディターやバイナリエディターで読むことができます。

  • 暗号化や難読化する
  • OSのセキュアに保存する機能で保護して保存する(AndroidはAccountManager、iOSはKeychainなど)
  • idとパスワードではなく、セッショントークンを保存しておく。一定時間でセッショントークンは更新されるようにしておきクラッカーに渡っても永続的に使用できないようにする

マスターデータ

マスターデータはキャラクターデータ(HPやSTRなど)、敵キャラクターデータ、ステージ情報など、ゲーム初期や動作を設定するための情報をさしています。

敵キャラクターのHPをすべて1に変更して、バトルを有利に進めるられると困ります。

Sqliteや専用のバイナリフォーマットなどを、ストレージに保存している場合は解析が可能です。

マスターデータを取り出し。解析をしてパラメータ変更が行えます。

  • 改変されても問題のないデータのみ格納する
  • 暗号化や難読化する
  • 常にサーバから取得する(ローカルには保存しないようにする)
  • 重要な情報は、複数の場所にデータを保存しておき、比較して改変チェックを行う
  • ハッシュ値も合わせて保存しておき改変チェックを行う

開発用のデータなど、リリース版のアプリに不要な情報は含めないようにしましょう。

ユーザーデータ

ユーザーデータは、ゲームの設定(ユーザー名、BGMのボリュームなど)、フレンド情報、ゲームの中断データなどがあります。

BGMのボリュームは書き換えられても問題ありません。ですが、ゲームの中断データを改変されクリアしたことになる、勝利したことになると問題になります。

PlayerPrefs、テキストファイル、バイナリファイルでストレージに保存した場合はファイルを取り出し。
ファイルを解析をしてパラメータ変更が行えます。

  • 改変されても問題のないデータのみ格納する
  • 暗号化や難読化する
  • 常にサーバから取得する(ローカルには保存しないようにする)
  • 重要な情報は、複数の場所にデータを保存しておき、比較して改変チェックを行う
  • ハッシュ値も合わせて保存しておき改変チェックを行う

アセット

パッケージに含まれているものや、クラウドストレージ(AmazonのS3など)からダウンロードしてくるデータをさします。
UnityだとAssetbundleファイルのこと。
Assetbundleではなく、専用のフォーマットで保持する場合もあるかもしれません。

シーンファイル、Prefabなどにテキストで入力してあるセーブデータ、通信時の暗号化キー、開発用サーバのエントリーポイントなどは文字列として保存されてしまいます

  • 不要な情報は含めないようにする
  • 暗号化や難読化する
  • 常にサーバから取得する(ローカルには保存しないようにする)

画像、3Dモデルな、音声データ、フォントなどを変換してPCで閲覧できます。

  • 暗号化や難読化する
  • 専用フォーマットにして、解析しにくようにする
  • 常にサーバから取得する(ローカルには保存しないようにする)

動的解析

プログラムが実行いる状態で解析を行うことです。

攻撃方法

デバッガー

実行中のプログラムを動作を確認するための方法。
通常は開発中のアプリケーションの動作を見るために使用します。

  • 実行中のプログラムにアタッチして、実行中のプログラム動作を確認する
  • プログラムの動作からチェックロジックなどを探し出す
  • 回避ロジックを、実行ファイルにパッチを当て改造アプリを作成する
  • アプリケーションを再署名する

メモリ改変

プログラムはメモリ内にロードされて実行されます。
プログラムがロードされたメモリを書き換えて目的の状態に変更する方法です。

  • メモリ調査用のアプリを動作させて、アプリケーションを動作させる
  • HPなど変化を確認したい箇所をプレイする
  • メモリ内の変化を確認して、変更すべき場所を探す
  • メモリを書き換えるアプリケーションを使用して、HPなど減らないようにパッチを当てる

常にサーバから取得する(ローカルには保存しないようにする)

サーバーからダウンロード行い、メモリにアセットが常駐している場合はメモリをダンプしてファイルに保存する。
一般的なファイルフォーマットの場合は保存したファイルから、データを一般的なツールを使い表示できます。

暗号化して常駐しさせていれば保存しただけでは表示できません。
ですが、複合ロジックが解析された場合には、アセットのデータと合わせて元のデータを復元される可能性があります。

インジェクション 5

対象のアプリケーションに、ハッキング用のアプリケーションを同梱して実行・攻撃する方法です。

  • アプリケーションのハックするためのバイナリを付与する
  • アプリケーションを再署名する
  • 実機でアプリケーションを動かして動作や変更したいポイントを調査する
  • パッチを作り必要に応じてアプリケーションの動作を変更する

対応方法

解析をするようなアクションが行われたことを検知してアプリケーションをクラッシュさせる。

注意点としては、検出ロジックで端末やOSのバージョンによって想定した挙動と異なる場合。
普通にプレイしている場合でもクラッシュさせてしまう可能性があります。
メーカー、OS、バージョン、端末の設定、常駐するアプリをイロイロなパターン組み合わせてチェックする必要があります。

  • 端末がroot(Android)、jailbreak(iOS)されていないかチックする
    • 特徴的なファイルを検知してアプリケーションを終了させる
  • エミュレータチェック
    • 特徴的なファイルを検知してアプリケーションを終了させる
  • アプリケーションが改変されていないか
    • 署名のチェックを行う
    • ファイルのハッシュチェックを行い、ファイルが置き換えられていないか確認する
    • チェックに引っかかった場合はアプリケーションを終了する
  • デバッグモードの設定がオン(許可)になっていないかをチェックする
    • デバッグモードがオン(許可)にはアプリケーションを終了する
  • デバッガーがアタッチされていないかチックする
    • アタッチされている場合はアプリケーションを終了する
    • シンボル情報を残さないようにする
  • メモリ書き換え
    • 複数箇所に書き込みを行い定期的に比較する
    • 書き換えられて胃が場合にはアプリケーションを終了する

すべてのチェックを同じタイミングで行うと、まとめて対策コードが潰される可能性があります。
コードを分散する、チェックタイミングを分散する、複数準備して別々にチェックするなど対応を行う必要があります。

ネットワーク

スマートフォン(Android、iOS)とサーバ間の通信で行われるクラッキングの内容と対策になります。

解析

WebAPI

https(SSL/TLS)を使用して呼び出している場合は、そのままではクラッキングされることはありません。

  • 最近はAndroid/iOS共に、アプリケーションからのhttpアクセスはは許可されていない。そのため、通信内容を簡単には見れません
  • バージョンや設定になどにより通信内容を見たり、改変でき、クラッキングされるケースはある

証明書の正当性チェックをしない実装になっていると、証明書を端末にインストールすることで通信内容の読み取りおよび改変されてしまいます。
(デバッグのために証明書チェックを切った状態でリリースしてしまったなど)

証明書の正当性チェックを行なっていても、実行ファイルの証明書チェックコードを無効化されたり。
プログラム実行中にパッチを当てて無効化される可能性があります。
通信内容にチェックサムを付けてリクエスト内容が改変されていないかをサーバ側で確認する必要があります。
チェックサム自身も解析される可能性があります。
対策方法に関しては、静的解析、動的解析の項目を確認してください。

WebAPIのリクエストエラー時に表示するテキストも解析される可能性があります。
リリース時には、エラーコードのみにして詳細なエラー内容を表示するための文字列を含まないようにしましょう。
(エラーコードとエラー内容の対応表をチーム内のみ参照できるようにする)

Tcp、Udp

オリジナルデータ構造をそのまま送信している場合には暗号化されません。
データ内容を読み改変できないように暗号化する。
パケットが改変されていないかチェックサムを付与してチェックする必要があります。

暗号化キーや証明書の管理、チェックサムロジックを解析されないように注意する必要があります。
対策方法に関しては、静的解析、動的解析の項目を確認してください。

ミドルウェア

ミドルウェア(Photonモノビットエンジンなど)では通信内容を暗号化機能機能を搭載しています。

暗号化キーや証明書の管理に注意する必要があります。
対策方法に関しては、静的解析、動的解析の項目を確認してください。

生成

リプレイ

端末とゲームサーバの中間にProxyサーバを置き、WebAPIやパケット(Tcp/Udp)送信したものをもう一度送る攻撃方法です。
Proxyで一部のパラメータを変更して送信することも可能です。
例えば、スコアの項目を増やして送るなどです。

証明書の正当性チェックを行い通信内容を改変できないようにましょう。

リクエスト生成

解析した情報を元にクライアントを使用せずにゲームの情報が操作できるようになります。(ゲームの仕様に即した範囲までの操作)
WebAPIはcurl。Tcp/UdpはScapyでリクエストを生成できます。

対策

  • 暗号化キーやロジック変更する
  • 一定タイミングで、暗号化キーを切り替える
  • チェックサムのロジック変更
  • リクエストの監視をして、一定処理を繰り返している、明らかに実行できないアカウントを抽出する
    • アカウントを削除する。もしくは行動制限をする
    • F2Pタイトルだとすぐに新しいアカウントが生成できてしまう。そのため、イタチごっこにはなってしまう

BOT

解析した情報を元に、WebAPIやパケット(Tcp/Udp)のリクエスト生成する。キャラクター操作など自動でゲームが進行するように自動的に操作を生成する手法です。6
(MMOなどでは、開発時に負荷チェックやデバッグために使ったりもする)

リクエスト解析を解析するだけではなく、追加のアプリや、OSの機能、エミュレータなどで簡易操作BOTを作成することもできます。

対策

  • 暗号化キーやロジック変更する
  • 一定タイミングで、暗号化キーを切り替える
  • チェックサムのロジック変更
  • リクエストの監視をして、一定処理を繰り返している、明らかに実行できないアカウントを抽出する
    • アカウントを削除する。もしくは行動制限をする
    • F2Pタイトルだとすぐに新しいアカウントが生成できてしまう。そのため、イタチごっこにはなってしまう
関連資料

サーバ

サーバへ行われるクラッキングの内容と対策になります。

サーバはクラウドサービス(orオンプレミス)、マネージドサービス、mBaasなど使用するサービスにより対応するべき範囲が変わります。

例えば、クラウドサービスではサーバ構成、OSからアプリケーションまで自分たちで面倒見なくてはいけません。(オンプレミスだとハードウェアやハウジング環境もプラスされる)

mBaaSではサーバ上で実行するスクリプトを考慮すれば問題ありません。
(正確には、mBaasサービスを運営しているチームがサーバやOSを管理してくれているだけです。
mBaaSの運営チームのスキルレベルにより問題が発生した場合に、自分たちで使用しているmBaaSサービスの解決できない問題になる可能性はあります)

専門ではないので、よく出ているワードと資料へのリンクになります。

  • DoS攻撃:サーバリソースを枯渇させてサーバを使用できない状態にする
  • インジェクション攻撃:SQLやOSのコマンドを外部から実行さすることができてしまう問題
  • ディレクトリ・トラバーサル攻撃:Webサーバをクローリングを行い、不正にアクセスしファイルの閲覧や改ざんをする攻撃
  • ゼロデイ攻撃:サーバ、OS、ミドルウェア、アプリケーションが持つ脆弱性が発見されてから、ベンダーによりセキュリティパッチ(修正プログラム)が適用されるまでの期間を狙って実行されるサイバー攻撃
  • ブルートフォースアタック:IDとパスワードでユーザー認証する際のパスワードを手当たり次第試して、パスワードを解析しようとする手法

関連資料

その他

ハードウェア

GPS、加速度センサー、ジャイロセンサーなど位置ゲーを作成する場合に使用する。
位置情報は、GPSだけではなく、無線LANのアクセスポイント、mobile(4Gなど)での位置情報計測も含まれる。
位置情報の補正や、歩数などに加速度センサー、ジャイロセンサーを使用している。

  • エミュレータやデバッグ機能でデータを設定されていないかを確認する
    • チェックに引っかかった場合は、アプリケーションを終了させる。もしくはデータを採用しない。
  • 取得したパラメータが、理論上ありえない移動数値だった場合
    • データを採用しないようにする
    • 合わせてログを自社で管理するサーバ取得して通知するようにする
  • 怪しいユーザーがいた場合に、移動量などが可視化するツールを作成して確認できるようにする

ソーシャルハッキング

ソーシャルハッキング(そーしゃるはっきんぐ)とは - コトバンク

ユーザーIDやパスワードを盗み出すのに、技術的な手段を利用せず、直接本人の口から聞き出す、タイプ内容を盗み見る、書類やメモを入手する、といった手段を利用する行為。盗み見た上司のパスワードを使って情報を盗む組織内犯罪や、掃除夫などを装ってオフィスに侵入する手口等がある。システム管理者の技術的な対応では防ぐことが困難であり、個人個人にセキュリティー意識を徹底させることが重要である。

ソフトウェアからだけではなく、人間自身がセキュリティーホールになる場合もあります。

おすすめ資料

合わせて読むと理解が進むと思います。


  1. と書きつつ、この文章も長いので読むの大変ですが 

  2. 各種資料の受け売りも含む 

  3. 公開しなければ、クラッカーというよりハッカー? 

  4. どんなことでも、途中から想定していない対応項目を追加する場合はコストが増えると思いますが 

  5. Unity用のものもあるのかは不明 

  6. 最近だとコントローラ(ゲームパット)の入力での操作とかもありそう 

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

テキストやボタンの端を丸くする Android

はじめに

テキストやボタンの端を丸くする方法を簡単にまとめました。

1.Layout resource file の作成

layout_width 200dp
layout_height 50dpのTextViewの端を丸くさせます。

drawableフォルダにDrawable resource fileを作成する


スクリーンショット 2020-04-26 21.18.54.png

2.背景色と丸み

作成した、Drawable resource file<shapeタグにし
<solid android:color="@android:color/holo_orange_light"/>で色を
<corners android:radius="25dp"/>で丸の大きさを決める。
今回はtextviewのhightを50dpにしたので25dpとした。

<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <solid android:color="@android:color/holo_orange_light"/>
    <corners android:radius="25dp"/>

</shape>

3.backgrounに反映させる

TextViewのbackgroundを作成したDrawable resource fileに指定する。

 <TextView
        android:id="@+id/textView"
        android:layout_width="200dp"
        android:layout_height="50dp"
        android:gravity="center"
        android:text="TextView"
        android:background="@drawable/rounded_textview"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

丸くする事が出来た!


ボタンも同じように丸く出来ます。

スクリーンショット 2020-04-26 21.50.45.png

まとめ

端を丸めるデザインが多いので備忘録として残しました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Unity + AdMob + CocoaPods + iOS】エラーなくビルドを通すための最適解【Androidにも応用できる】

こんにちは!
ねこじょーかー(@nekojoker1234)と申します。

みなさんは、UnityEditor 上だけでなく、実機で動作確認したことはありますか?

実機で動作確認をするには「ビルド」が必要になるのですが、これがまた本当にやっかいです。
何がやっかいなのかと言うと、とにかくエラーが出ることが多く、そしてそのエラー解決も一筋縄ではいきません。

私が遭遇したやっかいなエラーたちは以下の通り。

  • GoogleMobileAds/GoogleMobileAds.h' file not found
  • Undefined symbols for architecture arm64
  • Undefined symbols for architecture armv7
  • linker command failed with exit code 1

エラー内容で調べるといろいろと情報は出てくるのですが、Unity のバージョンが新しいせいか、どれも解決にはいたりませんでした。

もうダメかな...と諦めかけていたとき、ついに解決方法を見つけ、無事にエラーなくビルドすることができるようになりました。

私は解決に数日間かかりハゲそうになったので、他の人がハゲてしまわないよう、この記事に残しておきます。

ということで、さっそく見ていきましょう。

エラーなくビルドを通すための最適解

External Dependency Manager for Unity のインポート

まずは、External Dependency Manager for Unityをダウンロードしてください。

これが今回の肝となるプラグインで、簡単な記述をするだけで、iOS や Android でやっかいな依存関係のエラーを解決してくれるという優れものです。

Google が出しているプラグインなので、安心ですね。

この中にある、external-dependency-manager-latest.unitypackageをインポートしていきます。

スクリーンショット 2020-04-26 16.23.35.png

こんな画面が出てくるので、そのままインポートしましょう。

スクリーンショット 2020-04-26 16.29.38.png

Google Mobile Ads Unity Plugin をすでに入れている場合は、一部更新マークになります。

すると、インポート中にできたゴミファイルを削除していいか聞かれるので、Apply で削除しておきましょう。

スクリーンショット 2020-04-26 16.32.48.png

ここから少し時間が経つと、統計情報の取得をしてもいいか聞かれます。

スクリーンショット 2020-04-26 16.35.16.png

どちらでもいいですが、私は No を選択しました。

あと2画面出てくるのですが、両方とも右下のボタンを押せばOKです。

「Add Selected Registries」を選択

スクリーンショット 2020-04-26 16.38.06.png

「Apply」を選択

スクリーンショット 2020-04-26 16.39.42.png

これでインポートは完了です。

Dependencies.xml の準備

続いて、SampleDependencies.xml をダウンロードしてきます。

これをプロジェクトのフォルダに置くのですが、2つルールがあるので注意してください。

  • MyPlugin/Editorの直下に置く
  • Editor の上位階層のフォルダ名と、Dependencies の前につけた文字列を一致させる。(今回の例だとMyPluginDependencies.xml

たとえば、上位階層のフォルダが「DownhillRush」だとすると、以下の構造になっていればOKです。

スクリーンショット 2020-04-26 17.10.52.png

次に、XML ファイルの中身を修正していきます。

ファイルの一番下を見ると、以下の記載があります。

<iosPod name="Google-Mobile-Ads-SDK" path="../google-mobile-ads-sdk" version="~> 7.0" bitcodeEnabled="true"
        minTargetSdk="6.0">
  <!-- Set of source URIs to search for this Cocoapod spec.
       By default Cocoapods will attempt to fetch the pod specs from:
       * $HOME/.cocoapods/repos
       * https://github.com/CocoaPods/Specs
       -->
  <sources>
    <source>https://github.com/CocoaPods/Specs</source>
  </sources>
</iosPod>

今回は、Google-Mobile-Ads-SDKだけあればいいので、ここを少し修正します。

<iosPod name="Google-Mobile-Ads-SDK" version="~> 7.0" bitcodeEnabled="false" minTargetSdk="6.0">

bitcodeEnabledは色んなサイトで「false にしとけ」と書かれていたので、とりあえず false にしておきます。
pathはローカルの CocoaPod のパスらしいのですが、よくわからないので消しました。

また、ビルド時に「cocoapods.mycompany.com/Specs が見つからない」とエラーになるので、以下のsourcesタグはコメントアウトしておきましょう。

修正前

<!-- Global set of sources to search for Cocoapods.
     These sources will be searched for all Cocoapods specified by
     iosPod. -->
<sources>
  <source>https://cocoapods.mycompany.com/Specs</source>
</sources>

修正後

<!-- Global set of sources to search for Cocoapods.
     These sources will be searched for all Cocoapods specified by
     iosPod. -->
<!--<sources>
  <source>https://cocoapods.mycompany.com/Specs</source>
</sources>-->

これで XML の準備は完了です。

iOS Resolver の設定変更

Assets > External Dependency Manager > iOS Resolver > Settings を開きます。

スクリーンショット 2020-04-26 16.59.27.png

Cocoapods Integration を、Xcode Project - Add Cocoapods to the Xcode projectに変更します。

スクリーンショット 2020-04-26 17.02.29.png

xcworkspace のファイルを作らずに、Xcode のプロジェクトファイルの中に CocoaPods の設定を含めるようにする、という変更です。

これですべての準備が整いました。

ビルド

あとはビルドをすれば、エラーなくビルドができるはずです。

私はこの方法にたどり着くまでに、35回もビルドを失敗してしまいました...

スクリーンショット 2020-04-26 13.18.17.png

今回は iOS で試しましたが、Android でも専用の手順の通りやることで、ビルドが通るようになると思います。

みなさんがこの記事を参考に、一発でビルドが通れば嬉しいです。

おまけ

PlayFab に関するブログも書いているので、よければ合わせてご覧ください。
https://playfab-master.com/

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Android][Kotlin]背景をタップしてキーボードを非表示にする

画面側

    <!-- 背景がフォーカスされる用のTextView -->
    <TextView
        android:id="@+id/focusView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:focusable="true"
        android:focusableInTouchMode="true"
        app:layout_constraintBottom_toTopOf="parent"
        app:layout_constraintEnd_toStartOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <EditText
        android:id="@+id/editText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:ems="10"
        android:inputType="text"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

EditText以外にLayoutに背景をタップした時に背景がフォーカスされるためにTextViewを追加します。
このTextViewは、実際に画面に表示する訳ではないため幅と高さは0dpにしておきます。

さらに、focusablefocusableInTouchModetrueにしておきます。
これで、タッチモードによらずフォーカスが当たるようになります。

Activity側

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        editText.setOnFocusChangeListener { v, hasFocus ->
            if (!hasFocus) {
                val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
                imm.hideSoftInputFromWindow(v.windowToken, 0)
            }
        }
    }

    override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
        focusView.requestFocus()
        return super.dispatchTouchEvent(ev)
    }

editTextsetOnFocusChangeListenerでフォーカスが外れたときにキーボードを非表示にする処理を実行するようリスナーを設定します。
setOnFocusChangeListenerは、フォーカスを取得したり消失したりした時にリスナーが実行されるためフォーカスが外れたときだけキーボードを非表示にするようにしています。

dispatchTouchEventでは、focusViewにフォーカスを強制的に当てるようにrequestFocusを実行しています。
これがないと背景をタップしてもフォーカスが移動せずキーボードが表示されたままになってしまいます。
dispatchTouchEventは、タップイベントが起こった時に実行されます。onTouchEventだと、レイアウトによっては子でタッチイベントの伝搬が終了してしまい親でonTouchEventが実行されないことがあるため必ず実行されるdispatchTouchEventにしました。
dispatchTouchEventonTouchEventについて、詳しくは、Android のタッチイベントを理解する(その1) - Unmotivatedが参考になります。

起動した時の挙動

起動した時は、editTextにフォーカスは当たりません。
focusViewfocusablefocusableInTouchModetrueにしているため、起動時にはfocusViewにフォーカスが当たります。

editTextにフォーカスした状態でキーボードを非表示にするために、AndroidManifest.xmlwindowSoftInputModeを指定してもfocusViewにフォーカスが当たってしまい上手くいかないようです。
AndroidアプリのEditTextを含む画面でキーボードを非表示にする - Qiitaの「EditTextからフォーカスをはずす」が今回の対応にあたります。

参考

[Android]画面タップでキーボードを閉じる - ワークレ

入力イベントの概要  |  Android デベロッパー  |  Android Developers

表示| Androidデベロッパー| Android開発者

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

スマートアプリの脆弱性診断

アプリの脆弱性診断サービスとは

「アプリケーション脆弱性診断サービス」は、お客様が開発したスマートフォンアプリケーションのセキュリティ対策が適切であるかを診断し、問題点の有無をご報告するサービスです。

インターネットを介した不正アクセス被害が日々報じられる昨今、 その手法を理解し攻撃からシステムを守る技術の重要性はかつてなく高まっています。

脆弱性診断サービスの分類

自動ツールだけに頼らない手動診断と、リバースエンジニアリングによる高度な解析技術によりの手動診断があります。
1.Webアプリ脆弱性診断
2.スマホアプリ脆弱性診断IOS/Android
3.ペネトレーションテスト(侵入テスト)

スマホアプリ脆弱性診断の項目

OWASP Mobile Top 10を基準とします
1.png

報告書イメージ

スクリーンショット 0002-04-26 13.27.32.png

Msafe Technologyの脆弱性診断サービスはキャンペんで無料で実施しております。
ご希望のお客様はコーポレートサイト問い合 わせフォームよりお問い合わせください。
Msafe Technology株式会社

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Firebase ML 備忘録(クイックスタート)

はじめに

Firebase ML を試す機会があったので、
その時にやったこと・わかったことを備忘録に残します。

参考にしたサイト

公式

一番手軽に始めるなら、
クイックスタートサンプルをDL( clone は一つ上の階層から他のPJも含めてになります)して、
Firebaseにパッケージを登録するのが一番早かったです。
(逆に、Firebase使ってる既存のPJのパッケージ名にアプリを寄せちゃうかですね...)

自分でコードを書いて、作ってみる場合はコードラボが一番いいです。
CameraXも使いながら、テキスト解析・顔認識・バーコード解析をやってみましたが、
ある程度APIのインタフェースは揃っていたので、一つの使い方を理解すれば展開ができそうでした。

詰まったところ

テキスト認識から始めたのですが、手元にある端末(OS8のHuwai端末)では動きませんでした。
stackoverflow
(Google開発者サービスのデータ削除も何度もやったのだけど...)

同じコードで別端末では動いたので、端末の相性がある?のかもしれません...
顔認識とバーコード解析はできました..

まとめ

自分でCustomモデル作らないと学習の効果や深さを得られないかなとも思いましたが、
既存の物を理解・使用するだけでもFirebase ML の外観がわかりました。
画像解析使用時のペアになるCameraXがβ版であり、
Firebase ML 自体もβ版なので商用投入はもう少し待ってからの方が良さそうです。
(2020年4月現在)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

monkeyrunnerでAndroidの自動化テスト作成

Androidの操作を自動化してテストを自動化する

開発環境

Mac 10.14.6

やったこと

  • Mac でmonkeyrunnerを動かすためにopenjdk8のインストール
  • monkeyrunner で操作を記録
  • 記録した操作で実行

参考にしたサイト

https://qiita.com/ikota/items/ef6bdb4dad6ab9ba912a
https://developer.android.com/studio/test/monkeyrunner/MonkeyDevice?hl=ja

手順

monkeyrunnerの実行環境の構築

すでにAndroid StudioがDownloadされている環境ではmonkeyrunnerが以下にある。
/Users/xxx/Library/Android/sdk/tools/bin/monkeyrunner

ターミナルからmonkeyrunnerを実行すると、以下のエラーが出て実行できない。

./monkeyrunner 
-Djava.ext.dirs=/Users/xxx/Library/Android/sdk/tools/lib:/Users/xxx/Library/Android/sdk/tools/lib/x86_64 is not supported.  Use -classpath instead.
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.

monkeyrunner は"Java SE 10.0.2" では実行できないようなので OpenJDK 8をinstallする。

$ brew tap homebrew/cask-versions
==> Tapping homebrew/cask-versions
Cloning into '/usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask-versions'...
remote: Enumerating objects: 21, done.
remote: Counting objects: 100% (21/21), done.
remote: Compressing objects: 100% (17/17), done.
remote: Total 225744 (delta 8), reused 6 (delta 4), pack-reused 225723
Receiving objects: 100% (225744/225744), 58.27 MiB | 7.02 MiB/s, done.
Resolving deltas: 100% (155275/155275), done.
Tapped 155 casks (202 files, 64.5MB).

$ brew cask install adoptopenjdk8
==> Downloading https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u252-b09/OpenJDK8U-jdk_x64_mac_hotspot_8u252b09.pkg
==> Downloading from https://github-production-release-asset-2e65be.s3.amazonaws.com/140418865/c5d7a700-80b2-11ea-83f0-4ba454f82e1c?X-Amz-Algorithm=AWS4-HMAC-SHA256
######################################################################## 100.0%
==> Verifying SHA-256 checksum for Cask 'adoptopenjdk8'.
==> Installing Cask adoptopenjdk8
==> Running installer for adoptopenjdk8; your password may be necessary.
==> Package installers may write to any location; options such as --appdir are ignored.
Password:
installer: Package name is AdoptOpenJDK
installer: Installing at base path /
installer: The install was successful.
?  adoptopenjdk8 was successfully installed!

openjdk8 がインストールされたことを確認する。

$ /System/Library/Frameworks/JavaVM.framework/Versions/A/Commands/java_home -V
Matching Java Virtual Machines (2):
    10.0.2, x86_64: "Java SE 10.0.2"    /Library/Java/JavaVirtualMachines/jdk-10.0.2.jdk/Contents/Home
    1.8.0_252, x86_64:  "AdoptOpenJDK 8"    /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home

/Library/Java/JavaVirtualMachines/jdk-10.0.2.jdk/Contents/Home

defaultのjava versionをopenjdk8に切り替える。

~/.bashrc
export JAVA_HOME=$(/System/Library/Frameworks/JavaVM.framework/Versions/A/Commands/java_home -v "1.8.0_252")
PATH=${JAVA_HOME}/bin:${PATH}

Android 端末側で開発者オプションを有効にして、adb 接続できていることを確認する。

$ adb devices
List of devices attached
18f8de88    device

これで実行環境は整った。

monkeyrunner で操作を記録して、実行スクリプトに変換して実行

こちらのサイトに書かれている通りに実行する。
https://qiita.com/ikota/items/ef6bdb4dad6ab9ba912a

$ /Users/xxx/Library/Android/sdk/tools/bin/monkeyrunner ~/run_monkeyrecoder.py

携帯の画面と操作したログが右側に表示されるので、テストしたいシナリオを実行した後に、
Export Actions をして操作ログをaction_test.txtとして保存する。
image.png

先ほど保存したaction_test.txtを @ikota さんのconverterスクリプトを使って実行用のスクリプトに変換する。

$ python monkey_converter.py action_test.txt action_test.py

変換してできたaction_test.pyをmonkeyrunnerで実行すれば、自動で先ほど行った操作ができるようになる。

$ /Users/xxx/Library/Android/sdk/tools/bin/monkeyrunner ~/action_test.py

以上で、
Mac OS上でMonkey Runnerを使って、Android 端末の制御を自動化できた。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む