- 投稿日:2020-10-11T20:53:46+09:00
#6 Kotlin Koans Introduction/Data classes 解説
1 はじめに
Kotlin公式リファレンスのKotlin Koans/Data classesの解説記事です。
Kotlin Koansを通してKotlinを学習される人の参考になれば幸いです。
ただし、リファレンスを自力で読む力を養いたい方は、
すぐにこの記事に目を通さないで下さい!一度各自で挑戦してから、お目通し頂ければと思います
2-1 クラス定義・コンストラクタ
Kotlinでは
class
というキーワードをつけることでクラスを定義します。クラス名の右横に
()
で囲んでコンストラクタを実装することができます。コンストラクタは、クラスをインスタンス化するのと同時に呼ばれる関数のことです。
コンストラクタには2つの働きがあります。
・ プロパティを定義すること。
・ クラスのインスタンス化とパラメータの初期値の設定を同時に行うこと。
クラス定義・コンストラクタの実装を実際のコードで確認してみましょう。
//クラス定義。Invoiceがクラス名。 class Invoice { /*...*/ } //空のクラスの定義。クラス名の後の{]は省略できる。 class Empty //コンストラクタの実装。PersonクラスにfirstNameというプロパティを定義し、 //Personクラスがインスタンス化されるときに、firstNameに値が代入される。 //constructorというキーワードは省略できる。 class Person constructor(firstName: String) { /*...*/ }2-2 データクラス
クラスを定義する際、classのまえにdata修飾子を加えることで、クラスをデータクラスとして定義することができます。
データクラスは、
equal()関数、hashCode()関数、toString()関数、componentN()関数、copy()関数を自動的に実装してくれます。
2-3 セッター・ゲッター
Javaを学習された方には馴染みが深いかと思いますが、Kotlinにもゲッター・セッターが存在します。
ゲッター・セッターとはどちらも関数の1種です(Javaではメソッドと言います)。
Javaではクラス外からプロパティ(Javaではフィールドと言います)に値をセットするときにセッターを、クラス外からプロパティを利用したいときにゲッターを利用します。
ただ、Kotlinではこれら2つの関数を定義しなくても、暗黙的に定義されています。
なので特に何も定義しなくても、クラス外から目的のクラスのプロパティに値をセットしたり、利用したりできるのです。
実際にKotlinでクラス外でプロパティを利用しているコードを見てみましょう。
fun usePersonInfo(){ //Personクラスのインスタンスを生成。 val p = Person() //Personクラスのプロパティnameとageに値を代入。 p.name = "名前" p.age = 20 //プロパティnameとageの値を変数nとaに代入。 val n = p.name val a = p.age } //Personクラスを定義しプロパティnameとageを作成。初期値として、空文字と0を代入。 class Person{ var name : String = "" var age : Int = 0 }3 Introduction/Data classesの解説
Kotlin Koans Introduction/Data classesの解説です。
随時本サイトの内容を引用させていただきます。右側の本文を見てみましょう。
Rewrite the following Java code to Kotlin:
public class Person { private final String name; private final int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } }Then add a modifier data to the resulting class. This annotation means the compiler will generate a bunch of useful methods in this class: equals/hashCode, toString and some others. The getPeople function should start to compile.
Read about classes, properties and data classes.
JavaのコードをKotlinで書き換えなさい。
そのとき、data修飾子を追加しなさい。これにより、コンパイラはdata修飾子のついたクラスに便利な関数を生成する(equal()関数やhashCode()関数、toString()関数など)。getPeople関数はコンパイルし始めるべきである。
Javaのコードを見てみましょう。
Personクラス内には、String型のプロパティnameとInt型のプロパティageが存在しています。
Person()関数によってクラス外からプロパティに値がセットできます(この関数がJavaのセッターです。)。
getName()関数とgetAge()関数によってクラス外からプロパティが利用できます(この関数がJavaのゲッターです。)。
これをKotlinで書き換えます。
class Personこのコードに加筆して、以下の3点を加えます。
- プロパティnameとage
- ゲッター
- セッター
ただし、Kotlinではゲッター・セッターは定義不要なので、
1.のプロパティnameとageの定義のみ行えばOKです。プロパティをクラス内で定義するには、コンストラクタを利用するor利用しないの2通りあります。
ただ、getPeople()関数の中身を見てみると、
Person("Alice", 29), Person("Bob", 31)Personクラスのインスタンスを生成すると同時に、引数を設定しています。
この引数はコンストラクタに渡されPersonクラスのプロパティの初期値になります。
なので今回はプロパティの定義にコンストラクタを利用しないといけません。
また、data修飾子を追加するように問題文に指定があるので、
data class Person(val name : String,val age : Int)のようにすれば良いです(valはvarでもOKです。)。
(参考)
Personクラスの定義をdata修飾子無しでするとどうなるのでしょう?
Runボタンを押して見ると、
Fail: testListOfPeople: expected:<[Person[(name=Alice, age=29), Person(name=Bob, age=31)]]> but was:<[Person[@726f3b58, Person@442d9b6e]]>というエラーメッセージが出ます。
これは、
Person(name=Alice,age=29)とPerson(name=Bob,age=31)
を期待していたのに、
Person@726f3b58とPerson@442d9b6e
なんだけど、、、。といったニュアンスのメッセージです。実は、dataクラスは
toString()
関数を
インスタンスのプロパティの情報を人間のわかるように表示するように実装します。以下で具体例を見てみましょう。
通常のクラスを用いた場合 fun showExample(){ val e = Example("例1","例2") println(e.toString()) } class Example(val ex1 : String,val ex2 : String)これを実行すると、
Person@gen37232
と表示されます(@以下は任意の英数字の羅列です)。
Exampleクラスをdataクラスに書き換えて見ましょう。dataクラスを用いた場合 fun showExample(){ val e = Example("例1","例2") println(e.toString()) } data class Example(val ex1 : String,val ex2 : String)これを実行すると、
Person(ex1=例1,ex2=例2)
と表示されます。これだとPersonインスタンスのプロパティの情報が理解できますね。
4 最後に
次回はKotlin Koans Introducion/Nullable typesの解説をします
- 投稿日:2020-10-11T20:53:46+09:00
#6Kotlin Koans Introduction/Data classes 解説
1.はじめに
Kotlin公式リファレンスのKotlin Koans/Data classesの解説記事です。
Kotlin Koansを通してKotlinを学習される人の参考になれば幸いです。
ただし、リファレンスを自力で読む力を養いたい方は、
すぐにこの記事に目を通さないで下さい!一度各自で挑戦してから、お目通し頂ければと思います
2-1 クラス定義・コンストラクタ
Kotlinでは
class
というキーワードをつけることでクラスを定義します。クラス名の右横に
()
で囲んでコンストラクタを実装することができます。コンストラクタは、クラスをインスタンス化するのと同時に呼ばれる関数のことです。
コンストラクタには2つの働きがあります。
・ プロパティを定義すること。
・ クラスのインスタンス化とパラメータの初期値の設定を同時に行うこと。
クラス定義・コンストラクタの実装を実際のコードで確認してみましょう。
//クラス定義。Invoiceがクラス名。 class Invoice { /*...*/ } //空のクラスの定義。クラス名の後の{]は省略できる。 class Empty //コンストラクタの実装。PersonクラスにfirstNameというプロパティを定義し、 //Personクラスがインスタンス化されるときに、firstNameに値が代入される。 //constructorというキーワードは省略できる。 class Person constructor(firstName: String) { /*...*/ }2-2 データクラス
クラスを定義する際、classのまえにdata修飾子を加えることで、クラスをデータクラスとして定義することができます。
データクラスは、
equal()関数、hashCode()関数、toString()関数、componentN()関数、copy()関数を自動的に実装してくれます。
2-3 セッター・ゲッター
Javaを学習された方には馴染みが深いかと思いますが、Kotlinにもゲッター・セッターが存在します。
ゲッター・セッターとはどちらも関数の1種です(Javaではメソッドと言います)。
Javaではクラス外からプロパティ(Javaではフィールドと言います)に値をセットするときにセッターを、クラス外からプロパティを利用したいときにゲッターを利用します。
ただ、Kotlinではこれら2つの関数を定義しなくても、暗黙的に定義されています。
なので特に何も定義しなくても、クラス外から目的のクラスのプロパティに値をセットしたり、利用したりできるのです。
実際にKotlinでクラス外でプロパティを利用しているコードを見てみましょう。
fun usePersonInfo(){ //Personクラスのインスタンスを生成。 val p = Person() //Personクラスのプロパティnameとageに値を代入。 p.name = "名前" p.age = 20 //プロパティnameとageの値を変数nとaに代入。 val n = p.name val a = p.age } //Personクラスを定義しプロパティnameとageを作成。初期値として、空文字と0を代入。 class Person{ var name : String = "" var age : Int = 0 }3 Introduction/Data classesの解説
Kotlin Koans Introduction/Data classesの解説です。
随時本サイトの内容を引用させていただきます。右側の本文を見てみましょう。
Rewrite the following Java code to Kotlin:
public class Person { private final String name; private final int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } }Then add a modifier data to the resulting class. This annotation means the compiler will generate a bunch of useful methods in this class: equals/hashCode, toString and some others. The getPeople function should start to compile.
Read about classes, properties and data classes.
JavaのコードをKotlinで書き換えなさい。
そのとき、data修飾子を追加しなさい。これにより、コンパイラはdata修飾子のついたクラスに便利な関数を生成する(equal()関数やhashCode()関数、toString()関数など)。getPeople関数はコンパイルし始めるべきである。
Javaのコードを見てみましょう。
Personクラス内には、String型のプロパティnameとInt型のプロパティageが存在しています。
Person()関数によってクラス外からプロパティに値がセットできます(この関数がJavaのセッターです。)。
getName()関数とgetAge()関数によってクラス外からプロパティが利用できます(この関数がJavaのゲッターです。)。
これをKotlinで書き換えます。
class Personこのコードに加筆して、以下の3点を加えます。
- プロパティnameとage
- ゲッター
- セッター
ただし、Kotlinではゲッター・セッターは定義不要なので、
1.のプロパティnameとageの定義のみ行えばOKです。プロパティをクラス内で定義するには、コンストラクタを利用するor利用しないの2通りあります。
ただ、getPeople()関数の中身を見てみると、
Person("Alice", 29), Person("Bob", 31)Personクラスのインスタンスを生成すると同時に、引数を設定しています。
この引数はコンストラクタに渡されPersonクラスのプロパティの初期値になります。
なので今回はプロパティの定義にコンストラクタを利用しないといけません。
また、data修飾子を追加するように問題文に指定があるので、
data class Person(val name : String,val age : Int)のようにすれば良いです(valはvarでもOKです。)。
(参考)
Personクラスの定義をdata修飾子無しでするとどうなるのでしょう?
Runボタンを押して見ると、
Fail: testListOfPeople: expected:<[Person[(name=Alice, age=29), Person(name=Bob, age=31)]]> but was:<[Person[@726f3b58, Person@442d9b6e]]>というエラーメッセージが出ます。
これは、
Person(name=Alice,age=29)とPerson(name=Bob,age=31)
を期待していたのに、
Person@726f3b58とPerson@442d9b6e
なんだけど、、、。といったニュアンスのメッセージです。実は、dataクラスは
toString()
関数を
インスタンスのプロパティの情報を人間のわかるように表示するように実装します。以下で具体例を見てみましょう。
通常のクラスを用いた場合 fun showExample(){ val e = Example("例1","例2") println(e.toString()) } class Example(val ex1 : String,val ex2 : String)これを実行すると、
Person@gen37232
と表示されます(@以下は任意の英数字の羅列です)。
Exampleクラスをdataクラスに書き換えて見ましょう。dataクラスを用いた場合 fun showExample(){ val e = Example("例1","例2") println(e.toString()) } data class Example(val ex1 : String,val ex2 : String)これを実行すると、
Person(ex1=例1,ex2=例2)
と表示されます。これだとPersonインスタンスのプロパティの情報が理解できますね。
4 最後に
次回はKotlin Koans Introducion/Nullable typesの解説をします
- 投稿日:2020-10-11T19:18:30+09:00
Navigation Architecture Componentで現在アクティブなFragmentか判定する方法
Navigation Architecture Componentでイベントの中で画面遷移処理行う場合に、
ダイアログの裏側のFragmentが反応してしまい、backStackがおかしくなることが頻発したため、
自身がアクティブなFragmentか判定するために、extensionを書いたのでメモしておきます。サンプルコード
Fragment.ktpackage com.example.extension import androidx.fragment.app.Fragment import androidx.navigation.NavDestination import androidx.navigation.fragment.DialogFragmentNavigator import androidx.navigation.fragment.FragmentNavigator import androidx.navigation.fragment.findNavController /** * isCurrentDestination */ fun Fragment.isCurrentDestination(): Boolean { val currentDestination: NavDestination = findNavController().currentDestination ?: return false when (currentDestination) { is DialogFragmentNavigator.Destination -> { if (currentDestination.className == this.javaClass.name) { return true } } is FragmentNavigator.Destination -> { if (currentDestination.className == this.javaClass.name) { return true } } } return false }使用例
/** * 戻るボタンクリック処理 */ fun onClickBackButton() { if (!isCurrentDestination()) { return } findNavController().popBackStack() }
- 投稿日:2020-10-11T19:02:15+09:00
Android で各ストレージの総容量、空き容量を取得する方法
Android 10(Q)から導入されたScoped Storageの影響で、以前のストレージの容量関連の取得ができなくなっていたため、Android 10以降でも利用できる方法を模索したのでメモしておきます。
※ ディレクトリ毎のパーミッションを取ればできますが、
容量関連の情報を取るためだけに、ユーザにパーミッション許可を求めたくなかったため、
StatFsを用いた方法にしてあります。なお、勢いで書いたので、実際には動かしてないです。。。
※サンプルコードの他に外部ストレージアクセスのパーミッション取得が必要な可能性あり。サンプルコード
MainActivity.ktpackage com.example.storage.ui import android.annotation.SuppressLint import android.os.Build import android.os.Bundle import android.os.StatFs import android.os.storage.StorageManager import android.os.storage.StorageVolume import android.util.Log import androidx.appcompat.app.AppCompatActivity import java.util.* /** * Main Activity */ class MainActivity : AppCompatActivity() { /** * ============================================== * インスタンス変数 * ============================================== */ /** タグ */ private val tag: String = "MainActivity" /** ストレージマネージャー */ private val storageManager: StorageManager? get() = getSystemService(StorageManager::class.java) /** * ============================================== * ライフサイクルイベント * ============================================== */ /** * onCreate */ @SuppressLint("DiscouragedPrivateApi") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) Log.i(tag, "onCreate") for (storageVolume: StorageVolume in storageManager!!.storageVolumes) { // ストレージボリュームのリストを取得し、1件づつ処理 // ストレージボリュームから絶対パスを取得 val path: String = when { Build.VERSION.SDK_INT>= Build.VERSION_CODES.R -> { // Android 11以降 storageVolume.directory?.absolutePath } else -> { // Android 10以前 // NOTE: Android10以前ではgetPathがprivateなため無理やり実行して取得 val getPath = StorageVolume::class.java.getDeclaredMethod("getPath") getPath.invoke(storageVolume) as String? } } ?: continue // 絶対パスが取得できない場合は、スキップ val statFs = StatFs(path) // 総容量 val totalSpase: Long = statFs.blockCountLong * statFs.blockSizeLong / 1024L / 1024L // 空き容量 val freeSpase: Long = statFs.availableBlocksLong * statFs.blockSizeLong / 1024L / 1024L // 使用容量 val usedSpase: Long = totalSpase - freeSpase Log.d(tag, "Path: $path") Log.d(tag, " Used space: ${String.format(Locale.US, "%,12d", usedSpase)}MB") Log.d(tag, " Free space: ${String.format(Locale.US, "%,12d", freeSpase)}MB") Log.d(tag, "Total space: ${String.format(Locale.US, "%,12d", totalSpase)}MB") Log.d(tag, "Total space: ${String.format(Locale.US, "%,12d", totalSpase)}MB") } } }実行結果
LogPath: /storage/emulated/0 Used space: 495MB Free space: 5,455MB Total space: 5,951MB Path: /storage/1200-3709 Used space: 0MB Free space: 509MB Total space: 509MB
- 投稿日:2020-10-11T15:11:27+09:00
#5 Kotlin Koans Introduction/Strings 解説
1 はじめに
Kotlin公式リファレンスのKotlin Koans/Stringsの解説記事です。
Kotlin Koansを通してKotlinを学習される人の参考になれば幸いです。
ただし、リファレンスを自力で読む力を養いたい方は、
すぐにこの記事に目を通さないで下さい!一度各自で挑戦してから、お目通し頂ければと思います
2 正規表現・エスケープシーケンス
正規表現(regex patterns)とは、文字列に関する文法事項とイメージして頂ければOKです。
特殊な記号を用いて文字列パターンを指定します。
エスケープシーケンスとは、画面上に文字を出力する際に、文字そのものを出力するのではなく、文字色の変更やカーソルの移動、文字の消去など、文字出力の制御を行う特殊な文字列のことです。
/
記号と他の記号のセットで用います。(エスケープシーケンス(エスケープ文字)とは? ~見えない文字を表現する~|データ分析用語を解説を引用させていただきました。)
具体例は#3で解説します。
3 Introduction/Stringsの解説
Kotlin Koans Introduction/Stringsの解説です。
随時本サイトの内容を引用させていただきます。右側の本文を見てみましょう。
Read about different string literals and string templates in Kotlin.
Raw strings are useful for writing regex patterns, you don't need to escape a backslash by a backslash. Below there is a pattern that matches a date in format 13.06.1992 (two digits, a dot, two digits, a dot, four digits):
fun getPattern() = """\d{2}\.\d{2}\.\d{4}"""Using month variable rewrite this pattern in such a way that it matches the date in format 13 JUN 1992 (two digits, a whitespace, a month abbreviation, a whitespace, four digits).
different string literals and string templatesを読みなさい。
raw stringsは正規表現を記述するのに便利である。バックスラッシュでバックスラッシュをエスケープする必要がない。
以下は13.06.1992
(2個の数字、1個のドット、2個の数字、1個のドット、4個の数字)のフォーマットの日付にマッチする文字列パターンである。変数monthを用いてこのパターンを
13 JUN 1992
(2個の数字、スペース、月の略記、スペース、4個の数字)に書き直しなさい。とあります。(13,06,1992,JUNはあくまでパターンの例ですので、気にする必要はありません。)
つまり、
val month = "(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)" fun getPattern(): String = TODO()変数month(月の略記が格納されている)を用いて、TODO()部分で
13 JUN 1992
のフォーマットを実現すれば良いわけです。ここで、正規表現・エスケープシーケンスを利用します。
使用する、正規表現・エスケープシーケンスは以下のとおりです。
\d
:1~9のいずれかの数字を表現します。{}
:直前の文字を{}内の数字の回数分表示します。${}
:{}内の文字列を、別の文字列に埋め込む見ます(これをString Templateと言います。)これらを用いて、TODO()を
"""\d{2} ${month} \d{4}"""と書き換えればOKです。
(参考)
13.06.1992
を表現している正規表現・エスケープシーケンスを見てみましょう。"""\d{2}\.\d{2}\.\d{4}"""
\.
は正規表現での.
の「任意の1文字を指定する」といった意味を打ち消し、.
そのものを表示します。
4 最後に
次回はKotlin Koans Introducion/Data classesの解説をします
あと、みなさんraw stringsってどう日本語で呼んでいるんでしょうか、、、?
よろしければご意見ください
- 投稿日:2020-10-11T13:42:47+09:00
Androidアプリ開発の準備
概要
20代後半の現SEです。
SIerに所属していますが、業務内容が技術とは離れているため、スキルアップのために自己学習を行っています。
今までも、PHPやPython等を勉強してきまいしたが、効率的なスキルアップにはインプットだけでなく、アウトプットも大事ということで、Qiitaに投稿しようと思いました。何故Androidアプリかというと、以下の理由です。
①自分が持っているスマホがAndroidのため
②所持しているOSがWindowsのため(iPhoneアプリはMacが必要)
③現時点でポピュラーなJavaを習得できる
④広告収入をつければ儲けの仕組みを併用で勉強できる(儲けは考慮しない)本当は今までやっているWeb系でもよかったのですが、どうせなら新しいことを学びたいと思いAndroidアプリを選びました。
Androidアプリについて
言語
- Java
- Kotlin
- C言語
- Ruby
Androidアプリの開発ではJavaとKotlinが有名なようですが、Javaを選択しました。
IDE
JavaではEclipseが使われていますが、Android専用の「Android Studio」というIDEがあるため、こちらを使用します。
OS
Windows 10
Android Studioのダウンロード
Android Studioは下記のサイトからダウンロードできます。
Android Studio
「DOUNLOAD ANDROID STUDIO」をクリックAndroid Stuidoのインストール
ダウンロードしたEXEファイルを開きます
→android-studio-ide-193.6626763-windows.exe表示されるウィンドウに沿って、進めていきます
インストールフォルダの選択です。
人によって指定したいフォルダを選択すればよいと思います。
私はデフォルトで進めました。
スタートメニューのどのフォルダに表示するか、ですね。
これもデフォルトでよいと思います。Android Studioの初回起動
Android Studioを起動すると、デザイン等の選択が選べます。
慣れてくれば色々改造してもいいと思いますが、Standardでいきます。
ソースコードの表示ですね。
黒でもよいとは思いますが、何となく白にしました。
多分後からでも変えられると思います。
現在のインストールされている内容の確認ですね。
Finishを選択します。次回からはプロジェクトの立ち上げをして、HelloWorldとか電卓とかの簡単なアプリを作っていこうと思います。
- 投稿日:2020-10-11T11:52:03+09:00
AndroidアプリをGooglePlayConsoleで好きなタイミングで公開する
Androidアプリの公開タイミングについて
審査後すぐ公開ではなく、自分の好きなタイミングで公開する手順を試したので
書き記しておく公式のヘルプ
https://support.google.com/googleplay/android-developer/answer/9859654?hl=ja前情報
- 新しいUI(2020/11/2〜)を使用
手順
- GooglePlayConsoleにログイン > アプリ指定
- 左メニュー > 公開の概要
- 管理対象の公開のステータスを「オン」にする
- 左メニュー > リリース > 製品版 > 新しいリリースを作成
- 新しいバージョンのAPKファイルをアップロード > リリースのレビュー > 製品版としての公開を開始
- 審査中となる
- 「公開の概要」画面でも「審査中の変更」として表示される
- ストアページの内容変更も同様に「審査中の変更」になる
- 審査が終了し、「公開の概要」画面で「変更の公開準備完了」として表示される。 この時点では、アプリもページの変更もまだ公開されていない
- 自分の公開したいタイミングで「公開して確認」ボタン押下
- ボタンを押してすぐに公開されました
感想
時間指定ではなく、ボタンを押すと公開。
また、管理対象の公開機能で保留されない変更もあるので注意が必要
- 投稿日:2020-10-11T10:22:45+09:00
自宅以外の場所にいる子供の位置情報を全自動で通知して安心したい
はじめに
小学校の中~高学年ともなると、塾や習い事、友達の家に遊びに行ったりなど、一人で外出することが多くなるかと思います。
親としては子供が一人で外出している最中に、どこにいるのか、変なことに巻き込まれていないかなどを常に心配なものです。
子供が今どこにいるかが分かれば、少しは心配も減る・安心できるかと思い、子供に持たせたスマホ位置情報を全自動で通知する仕組みを作りました。スマホは Andorod、自動化処理は Macrodroid を使用します。
Macrodroid とは、自分で設定した処理を実行できる Android アプリです。すべて GUI で設定ができるため、プログラマーでなくても直感的にスクリプトが作成できます。
要件定義
- 子供の手を介さずに全自動で行う
- 自宅 WIFI の SSID 圏外になったら、位置情報の通知処理を開始する
- 通知は10分ごとにメールで行う
- 自宅 WIFI の SSID 圏内になったら、位置情報の通知処理を停止する
- 帰宅したことを通知する
環境
Android10 (SHARP AQUOS Phone SH-M07)
Macrodroid 5.6.3Macrodroid 設定
マクロは「位置情報自動通知」と「帰宅」の2つ作ります。
いずれも、自宅 WiFi の SSID の検知状況をトリガーとしています。マクロ その1(位置情報自動通知)
トリガー設定
トリガー完成形
トリガー設定手順
- 「トリガー」枠の + を選択
- 「接続」→「WIFIのSSIDの変化」を選択
- 「指定SSID圏外になったとき」を選択
- 自宅 WIFI の SSID を選択します。SSID が複数ある場合は、対象にしたいものすべて選択します(OR条件なので、いずれか一つが見つかれば動作対象となります)。
- 位置情報の権限を求められたら、「常に許可」を選択
以上で、トリガーの設定は完了です
アクション
アクション完成形
アクション設定手順
- 「アクション」枠の+を選択
- 「条件分岐/繰り返し」を選択
- 「条件で繰り返す(While)」を選択
- 「1回は必ず実行し、条件を満たす限り繰り返す」を選択
- 「条件」枠の + を選択
- 「接続」→「WiFiの状態」→「WiFi切断」→ 自宅 WiFi の SSID を選択
- 「アクション」枠の+を選択
- 「位置」 →「位置情報を強制的に更新」を選択
- 「アクション」枠の+を選択
- 「MacroDroid固有」 →「次のアクション実行前に待機」→「1分」と設定(「アラーム機能を使う」をチェックしたほうが正確に動作します)
- 「アクション」枠の+を選択
- 「メッセージ」→「メールを送る」→「Gmailアカウント」を選択。メールアドレス、件名は任意で。本文は以下をコピペ。貼り付けたら画面上部のチェックマークを選択して保存
(自動) 現在位置を送信します。 次回の送信時刻は10分後です。 地図 http://www.google.com/maps?q=[last_loc_latlong]¢er=[last_loc_latlong] 日時 [year]/[month_digit]/[dayofmonth] [hour]:[minute]:[second] 緯度経度 [last_loc_latlong] 誤差 [last_loc_accuracy] Mobile Network Code [mnc] Cell ID [cell_id]
- 「アクション」枠の+を選択
- 「MacroDroid固有」 →「次のアクション実行前に待機」→「9分」と設定
- 「アクション」枠の ↓↑ を選択
- 各アクションの右側に表示される = をドラッグするとアクションの位置が入れ替えられます。完成形の形に並べ替えてください。
保存
画面上部の「マクロ名を入力」に任意のマクロ名を入力し、画面右下の =+ ボタンを選択。
(私は「自宅WIFIを検出しなくなったら10分毎に現在位置を自動送信する」という名称にしています。長い)
以上で、マクロ その1 の設定は完了です。マクロ その2(帰宅通知)
・アプリホーム画面下部の「マクロ」→ 画面右下の + ボタンを選択します
トリガー設定
トリガー完成形
トリガー設定手順
- 「トリガー」枠の + を選択
- 「接続」→「WiFi の SSID の変化」を選択
- 「指定 SSID 圏内に入ったとき」を選択
- 自宅 WIFI の SSID を選択
アクション
アクション完成形
アクション設定手順
- 「アクション」枠の+を選択
- 「メッセージ」→「メールを送る」→「Gmailアカウント」を選択。メールアドレス、件名は任意で。本文は以下をコピペ。貼り付けたら画面上部のチェックマークを選択して保存
子供の携帯が家に着きました。 地図 http://www.google.com/maps?q=[last_loc_latlong]¢er=[last_loc_latlong] 日時 [year]/[month_digit]/[dateofmonth] [hour]:[minute]:[second] 緯度経度 [last_loc_latlong] 誤差 [last_loc_accuracy] Mobile Network Code [mnc] Cell ID [cell_id]保存
画面上部の「マクロ名を入力」に任意のマクロ名を入力し(私は「帰宅」という名称にしています。)、画面右下の =+ ボタンを選択。
以上で、マクロ その2 および、すべての設定が完了です。
最終的には、以下のような画面になります。
テスト
スマホを持って自宅 WiFi の電波が届かなくなる距離まで離れてみましょう(スマホの WiFi を ON/OFF してもいいと思いますが、実態に即したテストを行うことが大事です)。
メールアクションで設定した宛先に通知されるはずです。
メール本文の URL をタップすると、スマホの位置が地図アプリで確認できます。補足
- 10分ごとの更新としていますが、待機時間を短くすることで通知頻度を挙げられます。ただし、バッテリーの消費が早くなります。
- 「位置情報を強制的に更新」アクションは、おまじないみたいなものです。盛大にズレることもあるので気休め程度にお考えください。
- 子供のプライバシーも大切です。子供には「君のスマホには、外出時の位置を知らせる仕組みが設定していて、必要なときに確認できるようにしているよ」と必ず伝えておきましょう。子供が拒否したら、自動通知の仕組みを解除することも検討してください。
- 投稿日:2020-10-11T10:22:45+09:00
自宅以外の場所にいる子供の位置情報を全自動で通知できたら、少しは安心できるかもしれない
はじめに
小学校の中~高学年ともなると、塾や習い事、友達の家に遊びに行ったりなど、一人で外出することが多くなるかと思います。
親としては子供が一人で外出している最中に、どこにいるのか、変なことに巻き込まれていないかなどを常に心配なものです。
子供が今どこにいるかが分かれば、少しは心配も減る・安心できるかと思い、子供に持たせたスマホ位置情報を全自動で通知する仕組みを作りました。スマホは Andorod、自動化処理は Macrodroid を使用します。
Macrodroid とは、自分で設定した処理を実行できる Android アプリです。すべて GUI で設定ができるため、プログラマーでなくても直感的にスクリプトが作成できます。
要件定義
- 子供の手を介さずに全自動で行う
- 自宅 WIFI の SSID 圏外になったら、位置情報の通知処理を開始する
- 通知は10分ごとにメールで行う
- 自宅 WIFI の SSID 圏内になったら、位置情報の通知処理を停止する
- 帰宅したことを通知する
環境
Android10 (SHARP AQUOS Phone SH-M07)
Macrodroid 5.6.3Macrodroid 設定
マクロは「位置情報自動通知」と「帰宅」の2つ作ります。
いずれも、自宅 WiFi の SSID の検知状況をトリガーとしています。マクロ その1(位置情報自動通知)
トリガー設定
トリガー完成形
トリガー設定手順
- 「トリガー」枠の + を選択
- 「接続」→「WIFIのSSIDの変化」を選択
- 「指定SSID圏外になったとき」を選択
- 自宅 WIFI の SSID を選択します。SSID が複数ある場合は、対象にしたいものすべて選択します(OR条件なので、いずれか一つが見つかれば動作対象となります)。
- 位置情報の権限を求められたら、「常に許可」を選択
以上で、トリガーの設定は完了です
アクション
アクション完成形
アクション設定手順
- 「アクション」枠の+を選択
- 「条件分岐/繰り返し」を選択
- 「条件で繰り返す(While)」を選択
- 「1回は必ず実行し、条件を満たす限り繰り返す」を選択
- 「条件」枠の + を選択
- 「接続」→「WiFiの状態」→「WiFi切断」→ 自宅 WiFi の SSID を選択
- 「アクション」枠の+を選択
- 「位置」 →「位置情報を強制的に更新」を選択
- 「アクション」枠の+を選択
- 「MacroDroid固有」 →「次のアクション実行前に待機」→「1分」と設定(「アラーム機能を使う」をチェックしたほうが正確に動作します)
- 「アクション」枠の+を選択
- 「メッセージ」→「メールを送る」→「Gmailアカウント」を選択。メールアドレス、件名は任意で。本文は以下をコピペ。貼り付けたら画面上部のチェックマークを選択して保存
(自動) 現在位置を送信します。 次回の送信時刻は10分後です。 地図 http://www.google.com/maps?q=[last_loc_latlong]¢er=[last_loc_latlong] 日時 [year]/[month_digit]/[dayofmonth] [hour]:[minute]:[second] 緯度経度 [last_loc_latlong] 誤差 [last_loc_accuracy] Mobile Network Code [mnc] Cell ID [cell_id]
- 「アクション」枠の+を選択
- 「MacroDroid固有」 →「次のアクション実行前に待機」→「9分」と設定
- 「アクション」枠の ↓↑ を選択
- 各アクションの右側に表示される = をドラッグするとアクションの位置が入れ替えられます。完成形の形に並べ替えてください。
保存
画面上部の「マクロ名を入力」に任意のマクロ名を入力し、画面右下の =+ ボタンを選択。
(私は「自宅WIFIを検出しなくなったら10分毎に現在位置を自動送信する」という名称にしています。長い)
以上で、マクロ その1 の設定は完了です。マクロ その2(帰宅通知)
・アプリホーム画面下部の「マクロ」→ 画面右下の + ボタンを選択します
トリガー設定
トリガー完成形
トリガー設定手順
- 「トリガー」枠の + を選択
- 「接続」→「WiFi の SSID の変化」を選択
- 「指定 SSID 圏内に入ったとき」を選択
- 自宅 WIFI の SSID を選択
アクション
アクション完成形
アクション設定手順
- 「アクション」枠の+を選択
- 「メッセージ」→「メールを送る」→「Gmailアカウント」を選択。メールアドレス、件名は任意で。本文は以下をコピペ。貼り付けたら画面上部のチェックマークを選択して保存
子供の携帯が家に着きました。 地図 http://www.google.com/maps?q=[last_loc_latlong]¢er=[last_loc_latlong] 日時 [year]/[month_digit]/[dateofmonth] [hour]:[minute]:[second] 緯度経度 [last_loc_latlong] 誤差 [last_loc_accuracy] Mobile Network Code [mnc] Cell ID [cell_id]保存
画面上部の「マクロ名を入力」に任意のマクロ名を入力し(私は「帰宅」という名称にしています。)、画面右下の =+ ボタンを選択。
以上で、マクロ その2 および、すべての設定が完了です。
最終的には、以下のような画面になります。
テスト
スマホを持って自宅 WiFi の電波が届かなくなる距離まで離れてみましょう(スマホの WiFi を ON/OFF してもいいと思いますが、実態に即したテストを行うことが大事です)。
メールアクションで設定した宛先に通知されるはずです。
メール本文の URL をタップすると、スマホの位置が地図アプリで確認できます。補足
- 10分ごとの更新としていますが、待機時間を短くすることで通知頻度を挙げられます。ただし、バッテリーの消費が早くなります。
- 「位置情報を強制的に更新」アクションは、おまじないみたいなものです。盛大にズレることもあるので気休め程度にお考えください。
- 子供のプライバシーも大切です。子供には「君のスマホには、外出時の位置を知らせる仕組みが設定していて、必要なときに確認できるようにしているよ」と必ず伝えておきましょう。子供が拒否したら、自動通知の仕組みを解除することも検討してください。人の行動を監視するという非常に誤解されやすい仕組みでもあるため、事前の説明と同意は必須です。
- 投稿日:2020-10-11T00:31:00+09:00
TimePickerDialogで未来時刻が選択出来ないようにする
TimePickerDialogで未来時刻が選択出来ないようにしようと思った。
しかし...
実装方法を探しに探したが、全く見つからぬ٩( ᐛ )و
そして私は MaterialDateTimePicker というライブラリに出会った。
実装してみる
- build.gradleのdependenciesに以下を追加
implementation 'com.wdullaer:materialdatetimepicker:4.2.3'
- MaterialDateTimePickerを表示してみる(ボタンをクリックしたらダイアログが表示されるようにしています)
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) findViewById<Button>(R.id.show_timepicker_button).setOnClickListener { clickButton() } } private fun clickButton() { // TimePickerDialogのOKをクリックした時に呼ばれる。 // キャンセルや画面をクリックしてDialogを終了した時には呼ばれない val callback = TimePickerDialog.OnTimeSetListener { view, hourOfDay, minute, second -> // 選択した時間を取得して、何らかの処理を行う } val cal = Calendar.getInstance() TimePickerDialog.newInstance( callback, cal.get(Calendar.HOUR), cal.get(Calendar.MINUTE), false ).show(supportFragmentManager, TAG) } companion object { private const val TAG = "MainActivity" } }表示された( ´∀`)
未来時刻が選択出来ないようにする
val cal = Calendar.getInstance() val hour = cal.get(Calendar.HOUR_OF_DAY) val minute = cal.get(Calendar.MINUTE) TimePickerDialog.newInstance(callback, hour, minute, false).apply { // 現在の時刻を上限に設定する val timepoint = Timepoint(hour, minute) setMaxTime(timepoint) }.show(supportFragmentManager, TAG)未来時刻が選択出来ないようになりました
その他の設定
- MaterialDateTimePickerのデザインを変更
TimePickerDialog.newInstance(callback, hour, minute, false).apply { // TimePickerDialogのカラーを設定 accentColor = ContextCompat.getColor(this@MainActivity, R.color.colorAccent) // OKボタンの文言を設定 setOkText("よしっ!") // OKボタンのカラーを設定 setOkColor(ContextCompat.getColor(this@MainActivity, R.color.colorAccent)) // キャンセルボタンの文言を設定 setCancelText("あかん") // キャンセルボタンのカラーを設定 setCancelColor(ContextCompat.getColor(this@MainActivity, android.R.color.darker_gray)) }.show(supportFragmentManager, TAG)
- TimePickerDialog.newInstanceのis24HourModeをtrueにすると24時間表示になる