- 投稿日:2021-01-20T19:33:44+09:00
【Android】センサーを使う方法
プログラミング勉強日記
2021年1月20日
一昨日の記事でAndroidのセンサーAPIについてまとめた。今日はAndroidのセンサーの使い方を簡単にまとめる。Androidセンサーを使う方法
Androidセンサーを使う処理を説明する。
1. SensorManagerを取得
SensorManagerを取得するためには、getSystemServiceメソッドを使う。引数には、android.contentパッケージのContextクラスの定数SENSOR_SERVICEを指定する。
SensorManagerの取得// SensorManagerインスタンス private SensorManager sensorManager; @Override public void onCreate(Bundle savedInstanceState) { // SensorManagerのインスタンスを取得する sensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE); }2. イベントリスナーの実装
イベントリスナーは、何かしらのイベントが発生したときに呼ばれるクラスである。センサーイベントには、SensorEventListenerインタフェースをActivityに実装して具体的な処理をする。
SensorEventListenerインタフェースにはonAccuracycahngedとonSensorCahngedの2つのメソッドが定義されている。イベントリスナーの実装public class SensorActivity extends Activity implements SensorEventListener { @Override // センサーの精度が変更されると呼ばれる public void onAccuracyChanged(Sensor sensor, int accuracy) { } @Override // センサーの値が変化すると呼ばれる public void onSensorChanged(SensorEvent event) { } }イベントリスナーの登録と登録解除の方法
リスナーの登録にはSensorManagerクラスのregisterListenerメソッドを使う。引数には、センサーイベントを取得するリスナー、取得するセンサーの種類、取得する頻度を設定する。
registerListener(SensorEventListener listener, Sensor sensor, int rate)イベントリスナーの登録解除には、SensorManagerクラスのunregisterListenerメソッドを使う。
イベントリスナーの登録を解除protected void onPause() { super.onPause(); if (sensorManager != null) { sensorManager.unregisterListener(this); } }参考文献
- 投稿日:2021-01-20T19:19:04+09:00
HMSスマホでLINE CLOVA Assistantを有効にする手順と機能紹介
HMSスマホの音声アシスタント
音声アシスタントとは音声だけで端末を操作する機能です。
一般的に、Android端末ではGoogleアシスタントがプリインストールされ、使われています。ところが、ファーウェイの最新端末にGoogleのアプリがプリインストールされていないし、GMSも入っていないので、Googleアシスタントが利用できません。
ファーウェイは去年セリア(Celia)という音声アシスタント機能をリリースしました。しかし、残念ながら、日本語がまだ対応されておらず、日本もまだサポート地域に入っていません。
幸い、HMS端末で使える音声アシスタントはほかにあります。それはLINE CLOVA Assistantです。しかも、以下のHMS端末ではLINE CLOVA Assistantが標準搭載になっています。
HMS端末でLINE CLOVA Assistantを有効にする手順
[設定] -> [アプリ] -> [デフォルトアプリ] -> [アシスタント機能と音声入力] -> [アシストアプリ] に入って、LINE CLOVA Assistantを選ぶだけです。
こちらはその手順の動画です:https://twitter.com/i/status/1351829028173320192
(LINE CLOVA Assistantを使うのに、LINE)
HMS端末のLINE CLOVA Assistantで何ができるか?
以下のできることの例です。
機能 コマンドの例 電話をかける 〇〇に電話かけて 通話履歴を表示する 通話履歴を表示して スマホの設定を変更する Bluetoothをオンにして アプリを起動する App Galleryを起動して 天気を調べる 今日の天気を教えて 事柄を調べる 〇〇について教えて ニュースを知る ニュースを教えて 翻訳する ○○語に翻訳して 日時などを確認する いま何時 運行情報を調べる 山手線の運行情報を教えて イベント情報を調べる イベント情報教えて こちらはHMS端末でLINE CLOVA Assistantを使う動画です。
アプリ起動:https://twitter.com/i/status/1351829397662121986
百科事典:https://twitter.com/i/status/1351829528914522115
時間:https://twitter.com/i/status/1351829624880132100
- 投稿日:2021-01-20T15:57:38+09:00
スコープ関数のrun()関数を使わずに、関数式を使う方法
金田著「はじめてのandroidプログラミング 第5版」を使って、勉強しています。
「第9章カウントダウンタイマーを作ろう」で使っているテクニックを解析してみます。
スコープ関数のrun関数を関数式に直してみます。
はじめはrun関数の意味が分からなかったので、まずはrun関数を使わず、インスタンスを作り、そのメソッド()を操作する古いやり方に書き換えようとしました。しかしSoundPoolクラスのコンストラクタが非推奨になっていたので、本書のとおりSoundPool.Builder()でインスタンスを作ることにしました。調べて行く過程でrun関数を使わずに、関数式で書けることが分かったので紹介します。以下、本書を持っている前提で説明します。本書を使って勉強中の方、一緒に勉強しましょう。
0.前提
p253まで写経が済んでいるとします。
1.原型
p253まで写経が済んでいる状態のコードを示します。説明に不要な部分は、著作権に配慮して省略しています。
本書のやり方では、SoundPool.Builder()のrun()関数の中に、AudioAttributesのインスタンスを作り出すAudioAttributes.Builderが含まれています。MainActicity.ktclass MainActivity : AppCompatActivity() { // 省略 override fun onResume() { super.onResume() soundPool = SoundPool.Builder().run { val audioAttributes = AudioAttributes.Builder().run { this.setUsage(AudioAttributes.USAGE_ALARM) this.build() } this.setMaxStreams(1) this.setAudioAttributes(audioAttributes) this.build() } // 省略 } // 省略 }2.AudioAttributes.Builderを、SoundPool.Builder()のrun関数の外に出す
先ずは、SoundPool.Builder()のrun関数の中に含まれているAudioAttributes.Builderを、SoundPool.Builder()のrun関数の外に出します。なおrun関数の動作については、本書p127に書かれています。
MainActicity.ktclass MainActivity : AppCompatActivity() { // 省略 override fun onResume() { super.onResume() val audioAttributes = AudioAttributes.Builder().run { // (2)(1)をここへ移動する。(追記) this.setUsage(AudioAttributes.USAGE_ALARM) // this.は省略可 this.build() } soundPool = SoundPool.Builder().run { // val audioAttributes = AudioAttributes.Builder().run { // (1)この部分を外に出す(削除) // this.setUsage(AudioAttributes.USAGE_ALARM) // this.build() // } this.setMaxStreams(1) this.setAudioAttributes(audioAttributes) this.build() } // 省略 } }ここで、 AudioAttributesやSoundPoolのインスタンスを作るのに、コンストラクタを用いることが非推奨であるから使えないので、このままAudioAttributes.Builder()、SoundPool.Builder()を使ってインスタンスを作ることとした。
3.関数型に変換する
上記のコードを関数型に書き換えます。関数型に変換するにあたり、nyan のアプリ開発を参考にした。
MainActivity.kt// 省略 override fun onResume() { super.onResume() // 変換方法<参考> https://akira-watson.com/android/kotlin/soundpool-play.html> val audioAttributes = AudioAttributes.Builder() // run()関数とthisを外し、関数をピリオド(.)連結する。 .setUsage(AudioAttributes.USAGE_ALARM) .build() // val audioAttributes = AudioAttributes.Builder().run { // this.setUsage(AudioAttributes.USAGE_ALARM) // this.build() // } // 変換方法<参考> https://akira-watson.com/android/kotlin/soundpool-play.html> soundPool = SoundPool.Builder() // run()関数とthisを外し、関数をピリオド(.)連結する。 .setMaxStreams(1) .setAudioAttributes(audioAttributes) .build() // soundPool = SoundPool.Builder().run { // this.setMaxStreams(1) // this.setAudioAttributes(audioAttributes) // this.build() // } // 省略 } // 省略第2項のrun()関数を使うやり方と第3項の関数式を使うやり方と、どちらが見やすいでしょうか?私は、電車ごっこのような、順繰りとタスクが進む関数式の方が、分かりやすく見やすいと思います。run関数を使うか、関数式を使うかの選択は、趣味の問題でしょうか?疑問が残ります。
3.蛇足
見た目、汚らしいですがrun()関数の中で、関数を関数式で連結することも出来るみたいです。
MainActivity.ktsoundPool = SoundPool.Builder().run { setMaxStreams(1) .setAudioAttributes(audioAttributes) // ここから先を関数式で連結 .build() }MainActivity.ktsoundPool = SoundPool.Builder().run { setMaxStreams(1) setAudioAttributes(audioAttributes) .build() // これだけを関数式で連結 }
- 投稿日:2021-01-20T15:57:38+09:00
スコープ関数のrun()関数を使わずに、ピリオドでメソッドを連結させる
金田著「はじめてのandroidプログラミング 第5版」を使って、勉強しています。
「第9章カウントダウンタイマーを作ろう」で使っているkotlinの文法のテクニックを解析してみます。
スコープ関数のrun関数を関数式に直してみます。
はじめはrun関数の意味が分からなかったので、まずはrun関数を使わず、インスタンスを作り、そのメソッド()を一行1行、操作する古いやり方に書き換えようとしました。しかしSoundPoolクラスのコンストラクタが非推奨になっていたので、本書のとおりSoundPool.Builder()でインスタンスを作ることにしました。調べて行く過程でrun関数を使わずに、ピリオドでメソッドを連結できることが分かったので紹介します。以下、本書を持っている前提で説明します。本書を使って勉強中の方、一緒に勉強しましょう。
0.前提
p253まで写経が済んでいるとします。
1.原型
p253まで写経が済んでいる状態のコードを示します。説明に不要な部分は、著作権に配慮して省略しています。
本書のやり方では、SoundPool.Builder()のrun()関数の中に、AudioAttributesのインスタンスを作り出すAudioAttributes.Builderが含まれています。MainActicity.ktclass MainActivity : AppCompatActivity() { // 省略 override fun onResume() { super.onResume() soundPool = SoundPool.Builder().run { val audioAttributes = AudioAttributes.Builder().run { this.setUsage(AudioAttributes.USAGE_ALARM) this.build() } this.setMaxStreams(1) this.setAudioAttributes(audioAttributes) this.build() } // 省略 } // 省略 }2.AudioAttributes.Builderを、SoundPool.Builder()のrun関数の外に出す
先ずは、SoundPool.Builder()のrun関数の中に含まれているAudioAttributes.Builderを、SoundPool.Builder()のrun関数の外に出します。なおrun関数の動作については、本書p127に書かれています。
MainActicity.ktclass MainActivity : AppCompatActivity() { // 省略 override fun onResume() { super.onResume() val audioAttributes = AudioAttributes.Builder().run { // (2)(1)をここへ移動する。(追記) this.setUsage(AudioAttributes.USAGE_ALARM) // this.は省略可 this.build() } soundPool = SoundPool.Builder().run { // val audioAttributes = AudioAttributes.Builder().run { // (1)この部分を外に出す(削除) // this.setUsage(AudioAttributes.USAGE_ALARM) // this.build() // } this.setMaxStreams(1) this.setAudioAttributes(audioAttributes) this.build() } // 省略 } }ここで、 AudioAttributesクラスやSoundPoolクラスのインスタンスを作るのに、コンストラクタを用いることが非推奨であるから、AudioAttributes()やSoundPool()といった風にコンストラクタを使えないので、このままAudioAttributes.Builder()、SoundPool.Builder()を使ってインスタンスを作ることとした。
3.ピリオドで連結する方法に変換する
上記のコードをピリオドでメソッドを連結した形式に書き換えます。ピリオドで連結する形式に変換するにあたり、nyan のアプリ開発を参考にした。
MainActivity.kt// 省略 override fun onResume() { super.onResume() // 変換方法<参考> https://akira-watson.com/android/kotlin/soundpool-play.html> val audioAttributes = AudioAttributes.Builder() // run()関数とthisを外し、関数をピリオド(.)連結する。 .setUsage(AudioAttributes.USAGE_ALARM) .build() // val audioAttributes = AudioAttributes.Builder().run { // this.setUsage(AudioAttributes.USAGE_ALARM) // this.build() // } // 変換方法<参考> https://akira-watson.com/android/kotlin/soundpool-play.html> soundPool = SoundPool.Builder() // run()関数とthisを外し、関数をピリオド(.)連結する。 .setMaxStreams(1) .setAudioAttributes(audioAttributes) .build() // soundPool = SoundPool.Builder().run { // this.setMaxStreams(1) // this.setAudioAttributes(audioAttributes) // this.build() // } // 省略 } // 省略ピリオドで連結する形が使えるのは、AudioAttributes.BuilderクラスやSoundPool.Builderクラスのメソッドの戻り値が、AudioAttributes.Builder型やSoundPool.Builder型であるからである。例えばAudioAttributes.BuilderクラスのメソッドsetUsage()は、戻り値の型がAudioAttributes.Builderである。setUsage()のリファレンスを参照して頂きたい。
さて、第2項のrun()関数を使うやり方と第3項のピリオドで連結するやり方とでは、どちらが見やすいでしょうか?私は、電車ごっこのような、順繰りとタスクが進むピリオドで連結する方が、分かりやすく見やすいと思います。run関数を使うか、関数式を使うかの選択は、趣味の問題でしょうか?疑問が残ります。
4.ピリオド連結を分解し、メソッドを一行一行処理する(2021/01/21追記)
当初やり方が分からなかったが、落ち着いて考えたら方法を思いついたので記述する。
ピリオドで連結していたメソッドを分解し、一行一行に変数を設けるようにコードを書き換える。MainActivity.kt// val audioAttributes = AudioAttributes.Builder() // .setUsage(AudioAttributes.USAGE_ALARM) // .build() val buildedAudioAttributes = AudioAttributes.Builder() val setUsagedAudioAttributes = buildedAudioAttributes.setUsage(AudioAttributes.USAGE_ALARM) val audioAttributes = setUsagedAudioAttributes.build() // soundPool = SoundPool.Builder() // .setMaxStreams(1) // .setAudioAttributes(audioAttributes) // .build() val buildedSoundPool = SoundPool.Builder() val setMaxStreamsedSoundPool = buildedSoundPool.setMaxStreams(1) val setAudioAttributedBuildedSoundPool = setMaxStreamsedSoundPool.setAudioAttributes(audioAttributes) soundPool = setAudioAttributedBuildedSoundPool.build() // 省略5.蛇足
見た目、汚らしいですがrun()関数の中で、メソッドを連結することも出来るみたいです。第2項、第3項と比較してください。
【例1】
MainActivity.ktsoundPool = SoundPool.Builder().run { setMaxStreams(1) .setAudioAttributes(audioAttributes) // ここから先を関数式で連結 .build() }
【例2】MainActivity.ktsoundPool = SoundPool.Builder().run { setMaxStreams(1) setAudioAttributes(audioAttributes) .build() // これだけを関数式で連結 }
- 投稿日:2021-01-20T15:14:11+09:00
Android端末におけるMSALを使用したSSO認証
急に「これやりたいから調べてくれない?」と言われた自分用メモ
結論
https://docs.microsoft.com/ja-jp/azure/active-directory/develop/quickstart-v2-android
https://github.com/Azure-Samples/ms-identity-android-java
公式のクイックスタートとサンプルリポジトリのREADMEとソースを読むと良い。ドキュメントたくさんあるし自分がこれを書く必要なくない?アプリの初起動
PublicClientApplication.createSingleAccountPublicClientApplication()
を叩いてISingleAccountPublicClientApplication
インスタンスを取得する。
このインスタンスを使用して、サインインやサインアウト、アカウントの状態確認等ができる。
auth_config_single_account.json
はMSALで使用する構成ファイル
Azureにアプリ登録した際のIDとか、リダイレクトURIとかの設定が記載されている。PublicClientApplication.createSingleAccountPublicClientApplication( getContext(), R.raw.auth_config_single_account, // res/raw/auth_config_single_account.jsonのリソースID new IPublicClientApplication.ISingleAccountApplicationCreatedListener() { @Override public void onCreated(ISingleAccountPublicClientApplication application) { mSingleAccountApp = application; // 現在のアカウント状態を読み込む } @Override public void onError(MsalException exception) { displayError(exception); } });アプリの構成が正しく読み込めたら、
mSingleAccountApp.getCurrentAccountAsync
を呼び出して、現在のアカウントの状態を読み込む。
処理が終われば引数に設定したリスナーのonAccountLoaded
が呼び出されて、引数にアカウント情報が入ってくる。
一度もサインインしていない場合は引数にnullが設定されるので、サインインする。mSingleAccountApp.getCurrentAccountAsync(new ISingleAccountPublicClientApplication.CurrentAccountCallback() { @Override public void onAccountLoaded(@Nullable IAccount activeAccount) { if(activeAccount == null){ // サインインの処理 } else { // 必要であればトークンの更新 } } @Override public void onAccountChanged(@Nullable IAccount priorAccount, @Nullable IAccount currentAccount) { // ログインアカウントを変更する場合に呼び出される } @Override public void onError(@NonNull MsalException exception) { displayError(exception); } });サインイン
サインインは
mSingleAccountApp.signIn(activity, hint, scope, callback);
を呼び出せばOK
activity
は現在のアクティビティ
hint
は事前入力用の文字列(nullable)
scope
は要求する権限
callback
はサインインの結果を受け取るリスナー呼び出すとMSAL側のログインアクティビティが立ち上がってユーザーに認証を求めてくる。
サインインできればコールバックのonSuccess
メソッドが呼び出される。要望としてこっそりサインインさせたいんだけどって言われたけど
引数にアクティビティは必須だし、ログイン用のアクティビティが立ち上がるので
こっそりログインさせるのは無理そう2回目以降の起動(トークンの取得・更新)
アプリ構成とログインしているアカウントの情報がコールバックの引数に入ってくるはずなので、そこから確認できる。
トークンを取得したい場合はmSingleAccountApp.acquireToken
メソッドか
mSingleAccountApp.acquireTokenSilentAsync
メソッドを呼び出すことで取得できる。
有効なアクセストークンがなくても、自動的にリフレッシュトークンを使用して更新してくれる。基本は
mSingleAccountApp.acquireTokenSilentAsync
を使用して、
エラーが発生する等のユーザが操作する必要がある場合にmSingleAccountApp.acquireToken
を使う感じだと思います。トークンってどこに保存されているの
https://docs.microsoft.com/ja-jp/azure/active-directory/develop/msal-android-single-sign-on
IntuneもしくはMicrosoft Authenticatorが入っていて、会社等でデバイスを管理していれば、このアプリがトークンを保存している。
もしもIntuneとAuthenticatorが入っていない場合は、Androidで設定しているブラウザもしくはWebViewを使用する。
開くブラウザが異なると何度もサインインを求められるので注意。その他ハマったポイント
リダイレクトURIについて
MSAL構成ファイルのリダイレクトURIはパーセントエンコーディングする必要があり、
AndroidManifest.xml
に記載するpath
は、頭に/
をつけてデコードした文字列を設定する必要がある。
例えば、以下のようなMSAL構成ファイルだった場合はauth_config_single_account.json{ "client_id" : "0984a7b6-bc13-4141-8b0d-8f767e136bb7", "authorization_user_agent" : "DEFAULT", "redirect_uri" : "msauth://com.azuresamples.msalandroidapp/1wIqXSqBj7w%2Bh11ZifsnqwgyKrY%3D", "account_mode" : "SINGLE", "broker_redirect_uri_registered": true, "authorities" : [ { "type": "AAD", "authority_url": "https://login.microsoftonline.com/common" } ] }以下のような
AndroidManifest.xml
になる。
(%2B
が+
に、%3D
が=
に変わっている。)AndroidManifest.xml<activity android:name="com.microsoft.identity.client.BrowserTabActivity"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:host="com.azuresamples.msalandroidapp" android:path="/1wIqXSqBj7w+h11ZifsnqwgyKrY=" android:scheme="msauth" /> </intent-filter> </activity>疲れたので終わり
- 投稿日:2021-01-20T10:47:59+09:00
直近のUnity開発で困ったことの逆引きメモ
メモ書きですが、どなたかのお役に立てれば幸いです。
NavMesh
NavMeshAgentのキャラクターの動きを改善する
こちらを使わせていただくとイイカンジに動きます。感謝!!
NavMeshAgentでよい感じにキャラクターを歩かせる - tanaka's Programming MemoNavMeshをランタイムで動的に生成(Bake)する
NavMesh Componentsを入れるとNavMesh Surfaceが使える。
これをNavMeshを生成させたいオブジェクトに入れ、任意のタイミングで定期的にNavMeshをBakeさせればよい。
しかし、定期的にBakeすると、その都度Agent(キャラクター)の座標が変わってしまうことがあるので注意。Unity:動的NavMeshの確認 - simplestarの技術ブログ
NavMeshAgentで浮いてしまう問題
[Navigation]ウィンドウの[Bake]→[Advanced]→[Height Mesh]のチェックをオンにする
Dynamically Fixing NavMeshAgent Base Offset? - Unity Answers
また、モデルの配置時は最低でもNavMeshが生成された地面等が必要。
地面がないと空中に浮いたまま移動してしまう。UI
UIを貫通してRaycastしてしまうのを防止する
下記はARRaycastmanager向けのものだが、汎用的に使えそう。
なおPhysics.Raycastは常にUIを貫通するので注意。