- 投稿日:2019-05-21T23:46:44+09:00
AndroidにおいてFirebaseの匿名認証はアプリの再インストールで引き継がれるのか
はじめに
結論から書いちゃいますが、Androidでは引き継がれずuserIdが変わりますので気をつけましょう。
概要
StethoはSharedPreferences覗くために入れてます。
細かいバージョン情報等はbuild.gradleを参照。検証
ソースコード
build.gradle// Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { ext.kotlin_version = '1.3.31' repositories { google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.4.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'com.google.gms:google-services:4.2.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } allprojects { repositories { google() jcenter() } } task clean(type: Delete) { delete rootProject.buildDir }app/build.gradleapply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' android { compileSdkVersion 28 defaultConfig { applicationId "com.masaibar.firebaseanonymousauthsample" minSdkVersion 21 targetSdkVersion 28 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation 'androidx.appcompat:appcompat:1.0.2' implementation 'androidx.core:core-ktx:1.0.2' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'com.google.firebase:firebase-core:16.0.9' implementation 'com.google.firebase:firebase-auth:17.0.0' debugImplementation 'com.facebook.stetho:stetho:1.5.0' testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test:runner:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' } apply plugin: 'com.google.gms.google-services'MainActivity.ktclass MainActivity : AppCompatActivity() { private lateinit var auth: FirebaseAuth override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) Stetho.initializeWithDefaults(this) // SharedPreference覗くために追加 auth = FirebaseAuth.getInstance() Log.d("current", "currentUser = ${auth.currentUser?.uid.toString()}") signInAnonymously() } private fun signInAnonymously() { auth.signInAnonymously() .addOnCompleteListener(this) { task -> if (task.isSuccessful) { Log.d("success", "currentUser = ${auth.currentUser?.uid.toString()}") } else { Log.d("error", task.exception.toString()) } } } }検証結果
アプリのデータをクリアした後に再度インストールするとログで出力されるuserIdは別のものになっていました。
もう少し追ってみると、どうやらSharedPreferencesにuserIdを保存しているようです。
ガッツリSharedPreferencesに保存されておりました。
おわりに
Androidでは再インストールのたびに匿名認証のuserIdは変わるという前提を忘れてシステムを構築すると痛い目を見そうなので気をつけたいです。
ちなみにiOSは再インストール後も跨げるらしいです(NSUserDefaultに保存されている?未検証)。
- 投稿日:2019-05-21T22:01:57+09:00
Android開発者のためのOCR入門(tess-two編)
はじめに
AndroidアプリでOCRを実装する際、TessaractのAndroid用ラッパーライブラリtess-twoを利用するか、またはML Kit for Firebaseを利用する方法があります。
今回は、前者のtess-twoを使ってギャラリーから画像を選択してその画像にある文字を読み取るアプリを作ってみたいと思います。サンプルコードはここに置いてあります。
インストール
まずはtess-twoを入れます。また、画像をギャラリーから読み込む際にExifを読み取って画像の向きを正しい方向に直したいのでexifinterfaceも入れておきます。
app/build.gradle.kts// 略 dependencies { implementation("com.rmtheis:tess-two:9.0.0") implementation("androidx.exifinterface:exifinterface:1.0.0") }続いてappディレクトリ以下に/assets/tessdata/ディレクトリを作成して言語データを配置します。
今回はこんな感じにしました。app - assets - tessdata |-- jpn.traineddata `-- eng.traineddata言語データは下記からダウンロードしてください。tess-twoはtesseract3.0.5以下で作成された言語データが必要です。
https://github.com/tesseract-ocr/tessdata/tree/3.04.00実装
tess-twoの使い方自体は非常に簡単です。わずか5行程度です。
OCRUtil.ktval baseApi = TessBaseAPI() // initで言語データを読み込む baseApi.init(context.getFilesDir().toString(), "jpn") // ギャラリーから読み込んだ画像をFile or Bitmap or byte[] or Pix形式に変換して渡してあげる baseApi.setImage(bitmap) // これだけで読み取ったテキストを取得できる val recognizedText = baseApi.utF8Text baseApi.end()ですが注意点が2つあります。
1つ目はbaseApi.initはの中では、言語データをFileでopenしているためFileで読み込める場所にコピーしてあげる必要があります。
OCRUtil.ktprivate val TESS_DATA_DIR = "tessdata" + File.separator private val TESS_TRAINED_DATA = arrayListOf("eng.traineddata", "jpn.traineddata") private fun copyFiles(context: Context) { try { TESS_TRAINED_DATA.forEach { val filePath = context.filesDir.toString() + File.separator + TESS_DATA_DIR + it // assets以下をinputStreamでopenしてbaseApi.initで読み込める領域にコピー context.assets.open(TESS_DATA_DIR + it).use {inputStream -> FileOutputStream(filePath).use {outStream -> val buffer = ByteArray(1024) var read = inputStream.read(buffer) while (read != -1) { outStream.write(buffer, 0, read) read = inputStream.read(buffer) } outStream.flush() } } val file = File(filePath) if (!file.exists()) throw FileNotFoundException() } } catch (e: FileNotFoundException) { e.printStackTrace() } catch (e: IOException) { e.printStackTrace() } }2つ目はtess-twoで画像を読み込む場合、画像の向きが正しくないと当然読み込めません。ギャラリーから読み込む場合、画像が回転してしまっている場合があるのでExifを見て正しい方向に直す必要があります。
MainActivity.kt// 画像のuri uri?.let { contentResolver.openFileDescriptor(it, "r").use {parcelFileDescriptorNullable -> parcelFileDescriptorNullable?.let {parcelFileDescriptor -> val fileDescriptor = parcelFileDescriptor.fileDescriptor bitmapOrigin = BitmapFactory.decodeFileDescriptor(fileDescriptor) contentResolver.openInputStream(it).use { it?.let { // ExifInterfaceを初期化 val exifInterface = ExifInterface(it) val orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED) val degrees = when (orientation) { // 正しい方向の場合は回転させない 1 -> { 0f } // 逆向きなので180度回転させる 3-> { 180f } // 左向きの画像になってるので90度回転させる 6 -> { 90f } // 右向きの画像になってるので270度回転させる 8 -> { 270f } else -> { 0f } } val matrix = Matrix() val imageWidth = bitmapOrigin?.getWidth() ?: 0 val imageHeight = bitmapOrigin?.getHeight() ?: 0 matrix.setRotate(degrees, imageWidth.toFloat() / 2, imageHeight.toFloat() / 2) bitmap = Bitmap.createBitmap(bitmapOrigin!!, 0, 0, imageWidth, imageHeight, matrix, true) } } } } }ここまで実装したら早速動かしてみましょう。今回はこちらの画像から文字を読み取ってみます。
早速アプリを起動して画像を読み込んでみると…
無事、文字を読み取ることが出来るようになりました!が、、精度がいまいちです…
日本語言語データをカスタマイズ
先程の画像を見てみると数字が全然読み取れていないことに気がつくと思います。今回はこの数字の精度を改善してみたいと思います。
数字の誤変換の原因ですが、こちらのサイトを見てみると認識結果の変換マッピングが原因のようです。なのでjpn.unicharambigsを修正してみます。
今回、tesseract-ocrの環境をDockerで用意しました。こちらの環境を使ってカスタマイズします。
https://github.com/tarumzu/OCRSampleAndroid/tree/master/containersまずは下記の手順でDockerコンテナにログイン
cd containers docker-compose build docker-compose up docker-compose exec tesseract bashログインしたら、jpn.traineddataをダウンロード、次にcombine_tessdataコマンドのeオプションでjpn.traineddataからjpn.unicharambigsを取り出します。
wget https://github.com/tesseract-ocr/tessdata/raw/3.04.00/jpn.traineddata combine_tessdata -e jpn.traineddata jpn.unicharambigs
取り出したらjpn.unicharambigsをvimで開いて下記の行を削除します。これは左側のキャラクタを右側のものに変換するというルールなのですが正直必要ない変換だと思います。
1 l 1 ー 1 1 | 1 ー 1 1 I 1 ー 1 1 1 1 ー 1 1 | 1 ー 1 1 O 1 。 1 1 ° 1 。 1ここまでできたらjpn.traineddataを再作成します。
combine_tessdata -o jpn.traineddata jpn.unicharambigs
では、先程作成した言語データはcontainersに保存されます。この言語データを使って再度画像を読み込んでみましょう。
たったこれだけで数字の精度が劇的に改善できました!
終わりに
簡単にOCRが実装できましたが言語データのカスタマイズは必須ですね…
次はML Kit for FirebaseでOCRを実装してみて違いなどを記事にしてみたいと思います。参考
- 投稿日:2019-05-21T21:52:17+09:00
Androidのリリース用署名情報をbuild.gradleで管理する
リリース用の署名情報(alias、パスワード、keystoreなど)を app/build.gradle に組み込みたい場合がある。
やり方は色々あるが、今回は2つの方法を紹介
方法1. app/build.gradleに直書き
一番シンプルで簡単
git管理に含まれちゃうけどねapp/build.gradleandroid { ... signingConfigs { debug { } release { storeFile file('release.keystore') keyAlias '***' storePassword '***' keyPassword '***' } }コミット例
https://github.com/banbara23/Android-Kotlin-Lab/commit/a85e0fdb4d81039361fee970d115dd1998c4b46b個人プロジェクトなどはこれでいいんじゃないかな
方法2. 別のgradleファイルに書き出す
署名情報をgitに含めたくない場合を想定
会社のプログラムはこれでいいんじゃないかな
今更ながらAndroid の keystore と 署名(signingConfigs) の管理・運用について考えてみた
を参考にしたまず release.gradle というファイルを作成する。
release.gradlesigningConfigs { debug { } release { storeFile file('release.keystore') keyAlias '***' storePassword '***' keyPassword '***' } }そのファイルを build.gradle から読み込む。
app/build.gradleandroid { ... apply from: 'release.gradle', to: android最後に release.gradle をgitに含めないよう.gitignoreに追加して終わり
app/release.gradleコミット例
https://github.com/banbara23/Android-Kotlin-Lab/commit/9ab38238a402b2bd1f3104763229aa0cb63c32ecもし新しい人がプロジェクトにアサインして環境構築する場合、release.gradle をどこからか持ってくる必要があるけどね。
備考
たぶん個人プロジェクトも方法2で管理した方が良いね。
他にもっと良い方法があれば知りたいなー
- 投稿日:2019-05-21T18:05:53+09:00
Jetpack Composeについて調査 文法編
はじめに
Google I/O 2019で発表された
Jetpack Compose
について調査しました。本記事ではその中でも特徴的な宣言的UI
の構築を行うための文法についてまとめてみます。注意点
本記事は5/21時点でpre-alpha段階の
Jetpack Compose
について調査を行なっており、今後の変更で大きくインターフェースが変わる可能性があります。Jetpack Composeの文法
Hello World
を書く定番の
Hello World
は以下のように書けます。class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { CraneWrapper { MaterialTheme { val textColor = Color(0xFFFF0000.toInt()) Text( text = "Hello World!", style = +themeTextStyle { h2.copy(color = textColor) } ) } } } } }これは以下のように表示されます。
文字列を縦方向に二つ表示してみましょう。
otlin class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { CraneWrapper { MaterialTheme { val textColor = Color(0xFFFF0000.toInt()) Column { Text( text = "Hello", style = +themeTextStyle { h2.copy(color = textColor) } ) Text( text = "World!", style = +themeTextStyle { h2.copy(color = textColor) } ) } } } } } }これは以下のように表示されます。
宣言的にUIが構築されているので、結構読みやすいです。
Hello World
の解説上記
Hello World
に登場したJetpack Compose
固有のワードについて解説します。
setContent
以下のように
Activity
の拡張関数として実装されています。fun Activity.setContent(composable: @Composable() () -> Unit) = setContentView(FrameLayout(this).apply { compose(composable) })受け取った
composable
な関数をFrameLayout
に描画して自身にsetしています。
基本的にはこの関数を使うことでJetpack Compose
で書かれたUIを描画することになります。
CraneWrapper
Context
,FocusManager
,TextInputService
を作り、Jetpack Compose
の世界でこれらを使えるようにするためのwrapperです。上記Android上でのUI構築に必須なものを作る部分なので、setContent
直下にこれを記述し、これに関数を渡すようにUIを設計しないと例外が発生してしまいます。
MaterialTheme
Text
やButton
など、各種コンポーネントに適用できるマテリアルデザインなスタイルを提供します。
+themeTextStyle
上記
MaterialTheme
で提供されている文字に関するスタイルです。これに文字のスタイルを定義する関数を渡すことができます。
この辺りはKotlinDSL
の利点が活かされており、適切なスタイル定義をIDEやコンパイラの支援を受けつつ簡単に書くことができるようになっています。
上記コードでは、h2
スタイルの色だけを0xFFFF0000
(赤色)に変更するようにスタイルを定義しています。
Text
文字列を表現する関数です。Androidで言う
TextView
に相当します。
text
この名前で渡した引数が
Text
で表示される文字列になります。
style
この名前で渡した引数が
Text
で表示される文字列のスタイルになります。
Column
複数のコンポーネントを縦に並べて表示することができます。Androidのorientation=”vertical”な
LinearLayout
に相当します。コンポーネントを自作する
Jetpack Compose
ではコンポーネントの自作も簡単に行うことができます。試しに上記Hello Worldを以下のような仕様でコンポーネントにしてみます。
- Hello World!と表示する
- styleをパラメータとして適用できる
これは以下のように実装することができます。
@Composable fun HelloWorld(style: TextStyle? = null) { Text( text = "Hello World!", style = style ) }このようにして作られたコンポーネントは、以下のようにして使うことができます。
class MainActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { CraneWrapper { MaterialTheme { val textColor = Color(0xFFFF0000.toInt()) HelloWorld( style = +themeTextStyle { h2.copy(color = textColor) } ) } } } } }コンポーネントの自作は非常に簡単で、
@Composable
を付与した関数を作るだけです。ただし、いくつか気をつけなければならない点もあり、
- 副作用を起こさないようにする
- 関数の引数として渡されたパラメータ以外は使わないようにする(例えばグローバル変数にアクセスしたりしない)
と行った注意点も存在します。
ステートを持つUI
を作る上記
Hello World
はステートを持たないシンプルなUIでした。
今度は「ボタンをタップする度にカウントアップする」と言う機能を持ったUIを作ってみます。
タップされた回数を保持するのでステートを必要とします。class MainActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { CraneWrapper { MaterialTheme { CountableButton() } } } } } @Composable fun CountableButton() { val count = +state { 0 } Column { Button( onClick = { count.value++ }, text = "Tap Me!!" ) Text( text = "Tapped count ${count.value}", style = +themeTextStyle { h3 } ) } }これは以下のように動作します
タップされた回数をカウントしていきます。上の例ではInt
を使いましたが、@Model
を使うことで独自に定義した型を使うこともできます。独自の型を利用する形でCountableButton
コンポーネントを書き換えると以下のようになります。これは上記GIF画像と同じ動きをします。@Composable fun CountableButton() { val count = +state { CountModel() } Column { Button( onClick = { count.value.increment() }, text = "Tap Me!!" ) Text( text = "Tapped count ${count.value.num}", style = +themeTextStyle { h3 } ) } } @Model class CountModel { var num = 0 fun increment() { num++ } }
ステートを持つUI
の解説上記
ステートを持つUI
に登場したJetpack Compose
固有のワードについて解説します。
+state
この関数は
State
インスタンスを作るトップレベル関数です。
この関数にはState
インスタンスが保持するパラメータを初期化する関数を与えることができます。
上記初期化式で初期化されたパラメータを保持したState
インスタンスを返します。
State
stateを管理するクラスです。上記
+state
関数で作ることができます。
value
プロパティを経由することで、内部で保持しているパラメータを参照、更新することができます。
このようにしてパラメータを更新すると、UIが再描画され、更新後のパラメータが適用されます。
@Model
stateを表現するクラスに付与しなければならないアノテーションです。
+state
関数で作成したState
インスタンスで独自のクラスを保持させたい場合には、これを対象のクラスに付与しなければなりません。
これを付与し忘れた場合、コンパイルは通りますが、パラメータに変更があった際にUIが再描画されません。KTX
以下のようなコードは
Text(text = "Hello World!")このようにも書けます。
<Text text="Hello World!" />この
JSX
のタグにも似た書き方はKTX
と呼ばれているそうです。この書き方はKotlinのコンパイラを拡張する方法で実現されているそうです。しかし、KTX
は関数呼び出しで記述する方法を開発する以前の古い記法らしく、現在はKTX
からそちらに移行している最中だそうです。今後のことを考えるとこの書き方はしない方が良さそうです。おわりに
Jetpack Compose
について調べてみました。
Androidの既存の書き方(いわゆる宣言的ではない方法)だと色々と辛いところもありましたが、Jetpack Compose
が実用化されると、非常に簡単かつ苦しみを少なくしてUIを構築できそうです。
stable
になるまでまだまだ時間はかかりそうですが、非常に期待できそうです。参考
https://developer.android.com/jetpack/compose
https://android.googlesource.com/platform/frameworks/support/+/androidx-master-dev/compose/README.md
https://medium.com/q42-engineering/android-jetpack-compose-895b7fd04bf4
- 投稿日:2019-05-21T17:23:34+09:00
[Kotlin] AlertDialogをカスタマイズする
AlertBuilderでAlertDialogをカスタマイズします。(カスタムレイアウト作成した方がおすすめですが)
ソースコード
AlertDialogFragment.kt// 省略 override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { // ダイアログのタイトルのカスタマイズ val text = TextView(context) text.text = "Error" text.setPadding(0, 25, 0, 25) text.textSize = 20F text.textAlignment = View.TEXT_ALIGNMENT_CENTER text.setTextColor(resources.getColor(R.color.white, null)) text.background = resources.getDrawable(R.color.green, null) val builder = activity?.let { AlertDialog.Builder(it) } // setTitleではなくsetCustomTitleを使う builder!!.setCustomTitle(text) .setMessage(message) .setPositiveButton(okButtonName, onOkClickListener) val dialog = builder.show() // OKボタンを中央揃えに val button = dialog.getButton(DialogInterface.BUTTON_POSITIVE) button.gravity = Gravity.CENTER button.setTextColor(resources.getColor(R.color.colorWhite, null)) button.setPadding(0, -30, 0, -30) button.background = resources.getDrawable(R.drawable.green_button, null) button.textSize = 15F val layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 55) layoutParams.gravity = Gravity.CENTER layoutParams.marginStart = 250 layoutParams.marginEnd = 250 layoutParams.topMargin = 20 layoutParams.bottomMargin = 15 button.layoutParams = layoutParams this.isCancelable = false return dialog }二つ以上のボタンがある時
AlertDialogFragment.kt// 省略 builder!!.setCustomTitle(text) .setMessage(message) .setPositiveButton("OK",onOkClickListener) .setNegativeButton("CANCEL",onCancelClickListener) .setOnDismissListener(onDismissListener) val dialog = builder.show() val okButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE) okButton.gravity = Gravity.CENTER okButton.setTextColor(resources.getColor(R.color.white, null)) okButton.setPadding(70, -30, 70, -30) okButton.background = resources.getDrawable(R.drawable.green_button, null) okButton.textSize = 15F val layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, 55) layoutParams.gravity = Gravity.CENTER layoutParams.marginStart = 30 layoutParams.marginEnd = 160 layoutParams.topMargin = 20 layoutParams.bottomMargin = 10 okButton.layoutParams = layoutParams val cancelButton = dialog.getButton(DialogInterface.BUTTON_NEGATIVE) cancelButton.gravity = Gravity.CENTER cancelButton.setTextColor(resources.getColor(R.color.green, null)) cancelButton.setPadding(50, -30, 50, -30) cancelButton.textSize = 15F val layoutParams2 = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, 55) layoutParams2.gravity = Gravity.CENTER layoutParams2.marginStart = 60 layoutParams2.marginEnd = 30 layoutParams2.topMargin = 20 layoutParams2.bottomMargin = 10 cancelButton.layoutParams = layoutParams2 // 省略成果物
- 投稿日:2019-05-21T14:24:43+09:00
WSL 上で Vue.js を用いた Android (iOS) アプリを開発する
はじめに
仕事中、睡魔と戦いながら、Android アプリを作ろうと思いました。
ところが私は、C# は触った程度だし Java はコンソールアプリしかやったことがなく GUI はわかりません。そこで調べてみると、HTML で作れるそうじゃないですか。社会人二年目で Web 系しかしていない私にはありがたい話です。
もう少し欲を出して、業務で使用している Vue.js を使えないかなーと思ったら、ちょうどいいのがあるじゃないですか。
というわけで、Windows Subsystem for Linux (WSL) 上で Vue.js を用いて Android アプリを開発するための手順を紹介します。
つかうもの
- WSL : Windows 環境がカオスにならないようにするため
- Vue.js : 今回使いたかったもの
- nativescript : Javascript でアプリ開発できるようにするすごいやつ
- アンドロイド実機 : 開発時の実機との連携がすごい
手順
WSL の有効化から実機での起動まで端折らずにやるよ。
- WSL 環境の構築
- Ubuntu への各種インストール
1. WSL 環境の構築
まずは WSL を有効化し、Ubuntu をインストールします。
コントロールパネル > プログラムのアンインストール を選択
左側 windows の機能の有効化または無効化を選択
Windows Subsystem for Linux にチェックを入れ有効化
インストール完了次第再起動
(念の為)設定 > 更新とセキュリティ > 開発者向け > 開発者モードを有効にする
スタートから Microsoft Store を開く
「Ubuntu」で検索し、Ubuntu を選択
入手をクリックでインストール
スタートから Ubuntu を開く
インストール完了を待ち、ユーザー名とパスワードを入力(パスワードは表示されないので注意)
リポジトリを日本のサーバに変更(sudo 利用時、パスワード入力を求められます)
$ sudo sed -i -e 's%http://.*.ubuntu.com%http://ftp.jaist.ac.jp/pub/Linux%g' /etc/apt/sources.listパッケージのアップデート
$ sudo apt update $ sudo apt upgradeWindows との共有ディレクトリを作成
$ ln -s /mnt/c/Users/(username)/shareWithUbuntu ~/shareWithWindows # (username)はWindows側のユーザ名に置き換え以上で WSL 環境の構築は完了です。WSL 環境をリセットしたい場合は
スタート > Ubuntu 右クリック > アプリの設定 > リセット
から可能です。リセット後は Ubuntu を起動するとまたアカウント設定から始まります。環境破壊と再構築、簡単ですね。2. Ubuntu への各種インストール
NativeScript-Vue での開発に必要なものをインストールしていきます。
Node.js のインストール
$ sudo apt install -y nodejs npm # node、npmのインストール $ sudo npm install n -g # n package導入 $ sudo n stable # nを使用してnodeのstable版をインストール $ sudo apt purge -y nodejs npm # 最初に入れた古いnode、npmは削除 $ exec $SHELL -l # 再ログイン $ node -v # バージョン確認NativeScript CLI のインストール
$ sudo npm install -g nativescriptG++ (C++ のコンパイラ)のインストール
$ sudo apt install g++JDK8 の設定
$ sudo apt install openjdk-8-jdk # JDK8インストール $ sudo update-alternatives --config java # JAVAのバージョンが複数あればJDK8を選択環境変数 JAVA_HOME の追加
~/.bashrc を開く
$ vi ~/.bashrc
Iキーで編集モードに入り、一番下に以下の行を追加
$ export JAVA_HOME=$(update-alternatives --query javac | sed -n -e 's/Best: *\(.*\)\/bin\/javac/\1/p')ESCキーを押し、:wq と入力
Android SDK のダウンロード(Windows 側での操作)
ここ の下の方の「Command line tools only」から Linux のものをダウンロード
ダウンロードした zip ファイルを解凍
解凍した中にある tools ディレクトリを shareWithUbuntu ディレクトリに移動
/usr/lib/android/sdk/ ディレクトリを作成
$ sudo mkdir -p /usr/lib/android/sdk/shareWithWindows ディレクトリ内の tools ディレクトリを /usr/lib/android/sdk/ に移動
$ sudo mv ~/shareWithWindows/tools /usr/lib/android/sdk/環境変数 ANDROID_HOME の追加
~/.bashrc を開く
$ vi ~/.bashrc
Iキーで編集モードに入り、一番下に以下の行を追加
$ export ANDROID_HOME="/usr/lib/android/sdk/" $ export PATH="${PATH}:${ANDROID_HOME}tools/:${ANDROID_HOME}platform-tools/"ESCキーを押し、:wq と入力
再ログイン
$ exec $SHELL -l必要なパッケージのインストール
$ sudo $ANDROID_HOME/tools/bin/sdkmanager "tools" "emulator" "platform-tools" "platforms;android-28" "build-tools;28.0.3" "extras;android;m2repository" "extras;google;m2repository"再ログイン
$ exec $SHELL -l以下のコマンドを実行し、No issues were detected. が出力されれば成功
$ tns doctor # 統計情報を自動送信して良いか聞かれるが n で構わないNativeScript 関連のインストールはここまで。
3. アプリケーションの作成
アプリケーションを作成します。
Vue 関連パッケージのインストール
$ sudo npm install -g @vue/cli @vue/cli-initプロジェクトを作成するディレクトリを作成、移動
$ mkdir workspace && cd workspaceプロジェクトの作成
$ vue init nativescript-vue/vue-cli-template sample-app # 以下対話形式(vue-devtools以外はデフォルトでもOK) ? Project name sample-app # プロジェクト名 ? Project description A native application built with NativeScript-Vue # プロジェクトの説明 ? Application name NativeScript-Vue Application # アプリ名 ? Unique application identifier org.nativescript.application # アプリケーション任意のID ? Project version 1.0.0 # プロジェクトのバージョン ? Author # 開発者 ? License MIT # ライセンスの種類 ? Select the programming language javascript # 使用する言語 ? Select a preset (more coming soon) Simple # 用意するアプリのテンプレート ? Install vuex? (state management) Yes # Vuexを使用するか(デフォルトはNo) ? Install vue-devtools? No # Vuedevtoolsを使用するか(デフォルトはYes) ? Color scheme none # カラーテーマプロジェクトディレクトリに移動し、パッケージインストール
$ cd sample-app && npm installアプリを起動
$ tns preview --bundleプロジェクトの作成からアプリ実行までは簡単ですね。コンソールに表示される QR コードは後ほど利用するので消さないでください。
実機で表示
作成したアプリケーションを実機に表示します。ここでは、Android 側にアプリケーションの導入が必要となります。
- Google Play から NativeScript Playground をインストール
Google Play から NativeScript Preview をインストール
NativeScript Playground を開き、 Scan QR code をタップ
コンソールの QR コードを読み込む
完了
QR の読み込み後に少し時間がかかりますが、個人的には QR 読み込みだけで実機で試せるのは革命的です。
おわりに
NativeScript-Vue のおかげで睡魔に打ち勝つことができました。が、この記事を書いている間は何度も睡魔に負けています。何か実用的なものを NativeScript-Vue で作成してまた記事を上げたいですが、今度は仕事が忙しくなり睡魔に襲われる機会が減りそうなので、なかったことになるかもしれないです。
ここを見れば誰でも同じことができるように心がけていますが、訳わかんねー記述があればコメントください。まあ私も素人ですが。
参考サイト
Windows Subsystem for Linuxをインストールしてみよう!
Ubuntuに最新のNode.jsを難なくインストールする
NativeScript-Vue / Installation(英語)
NativeScript Advanced Setup: Linux(英語)
Windows 10のWindows Subsystem for Linux(WSL)を日常的に活用する
- 投稿日:2019-05-21T14:24:43+09:00
WSL 上で Vue.js を用いた Android アプリを開発する
はじめに
仕事中、睡魔と戦いながら、Android アプリを作ろうと思いました。
ところが私は、C# は触った程度だし Java はコンソールアプリしかやったことがなく GUI はわかりません。そこで調べてみると、HTML で作れるそうじゃないですか。社会人二年目で Web 系しかしていない私にはありがたい話です。
もう少し欲を出して、業務で使用している Vue.js を使えないかなーと思ったら、ちょうどいいのがあるじゃないですか。
というわけで、Windows Subsystem for Linux (WSL) 上で Vue.js を用いて Android アプリを開発するための手順を紹介します。
つかうもの
- WSL : Windows 環境がカオスにならないようにするため
- Vue.js : 今回使いたかったもの
- nativescript : Javascript でアプリ開発できるようにするすごいやつ
- アンドロイド実機 : 開発時の実機との連携がすごい
手順
WSL の有効化から実機での起動まで端折らずにやるよ。
- WSL 環境の構築
- Ubuntu への各種インストール
1. WSL 環境の構築
まずは WSL を有効化し、Ubuntu をインストールします。
コントロールパネル > プログラムのアンインストール を選択
左側 windows の機能の有効化または無効化を選択
Windows Subsystem for Linux にチェックを入れ有効化
インストール完了次第再起動
(念の為)設定 > 更新とセキュリティ > 開発者向け > 開発者モードを有効にする
スタートから Microsoft Store を開く
「Ubuntu」で検索し、Ubuntu を選択
入手をクリックでインストール
スタートから Ubuntu を開く
インストール完了を待ち、ユーザー名とパスワードを入力(パスワードは表示されないので注意)
リポジトリを日本のサーバに変更(sudo 利用時、パスワード入力を求められます)
$ sudo sed -i -e 's%http://.*.ubuntu.com%http://ftp.jaist.ac.jp/pub/Linux%g' /etc/apt/sources.listパッケージのアップデート
$ sudo apt update $ sudo apt upgradeWindows との共有ディレクトリを作成
$ ln -s /mnt/c/Users/(username)/shareWithUbuntu ~/shareWithWindows # (username)はWindows側のユーザ名に置き換え以上で WSL 環境の構築は完了です。WSL 環境をリセットしたい場合は
スタート > Ubuntu 右クリック > アプリの設定 > リセット
から可能です。リセット後は Ubuntu を起動するとまたアカウント設定から始まります。環境破壊と再構築、簡単ですね。2. Ubuntu への各種インストール
NativeScript-Vue での開発に必要なものをインストールしていきます。
Node.js のインストール
$ sudo apt install -y nodejs npm # node、npmのインストール $ sudo npm install n -g # n package導入 $ sudo n stable # nを使用してnodeのstable版をインストール $ sudo apt purge -y nodejs npm # 最初に入れた古いnode、npmは削除 $ exec $SHELL -l # 再ログイン $ node -v # バージョン確認NativeScript CLI のインストール
$ sudo npm install -g nativescriptG++ (C++ のコンパイラ)のインストール
$ sudo apt install g++JDK8 の設定
$ sudo apt install openjdk-8-jdk # JDK8インストール $ sudo update-alternatives --config java # JAVAのバージョンが複数あればJDK8を選択環境変数 JAVA_HOME の追加
~/.bashrc を開く
$ vi ~/.bashrc
Iキーで編集モードに入り、一番下に以下の行を追加
$ export JAVA_HOME=$(update-alternatives --query javac | sed -n -e 's/Best: *\(.*\)\/bin\/javac/\1/p')ESCキーを押し、:wq と入力
Android SDK のダウンロード(Windows 側での操作)
ここ の下の方の「Command line tools only」から Linux のものをダウンロード
ダウンロードした zip ファイルを解凍
解凍した中にある tools ディレクトリを shareWithUbuntu ディレクトリに移動
/usr/lib/android/sdk/ ディレクトリを作成
$ sudo mkdir -p /usr/lib/android/sdk/shareWithWindows ディレクトリ内の tools ディレクトリを /usr/lib/android/sdk/ に移動
$ sudo mv ~/shareWithWindows/tools /usr/lib/android/sdk/環境変数 ANDROID_HOME の追加
~/.bashrc を開く
$ vi ~/.bashrc
Iキーで編集モードに入り、一番下に以下の行を追加
$ export ANDROID_HOME="/usr/lib/android/sdk/" $ export PATH="${PATH}:${ANDROID_HOME}tools/:${ANDROID_HOME}platform-tools/"ESCキーを押し、:wq と入力
再ログイン
$ exec $SHELL -l必要なパッケージのインストール
$ sudo $ANDROID_HOME/tools/bin/sdkmanager "tools" "emulator" "platform-tools" "platforms;android-28" "build-tools;28.0.3" "extras;android;m2repository" "extras;google;m2repository"再ログイン
$ exec $SHELL -l以下のコマンドを実行し、No issues were detected. が出力されれば成功
$ tns doctor # 統計情報を自動送信して良いか聞かれるが n で構わないNativeScript 関連のインストールはここまで。
3. アプリケーションの作成
アプリケーションを作成します。
Vue 関連パッケージのインストール
$ sudo npm install -g @vue/cli @vue/cli-initプロジェクトを作成するディレクトリを作成、移動
$ mkdir workspace && cd workspaceプロジェクトの作成
$ vue init nativescript-vue/vue-cli-template sample-app # 以下対話形式(vue-devtools以外はデフォルトでもOK) ? Project name sample-app # プロジェクト名 ? Project description A native application built with NativeScript-Vue # プロジェクトの説明 ? Application name NativeScript-Vue Application # アプリ名 ? Unique application identifier org.nativescript.application # アプリケーション任意のID ? Project version 1.0.0 # プロジェクトのバージョン ? Author # 開発者 ? License MIT # ライセンスの種類 ? Select the programming language javascript # 使用する言語 ? Select a preset (more coming soon) Simple # 用意するアプリのテンプレート ? Install vuex? (state management) Yes # Vuexを使用するか(デフォルトはNo) ? Install vue-devtools? No # Vuedevtoolsを使用するか(デフォルトはYes) ? Color scheme none # カラーテーマプロジェクトディレクトリに移動し、パッケージインストール
$ cd sample-app && npm installアプリを起動
$ tns preview --bundleプロジェクトの作成からアプリ実行までは簡単ですね。コンソールに表示される QR コードは後ほど利用するので消さないでください。
実機で表示
作成したアプリケーションを実機に表示します。ここでは、Android 側にアプリケーションの導入が必要となります。
- Google Play から NativeScript Playground をインストール
Google Play から NativeScript Preview をインストール
NativeScript Playground を開き、 Scan QR code をタップ
コンソールの QR コードを読み込む
完了
QR の読み込み後に少し時間がかかりますが、個人的には QR 読み込みだけで実機で試せるのは革命的です。
おわりに
NativeScript-Vue のおかげで睡魔に打ち勝つことができました。が、この記事を書いている間は何度も睡魔に負けています。何か実用的なものを NativeScript-Vue で作成してまた記事を上げたいですが、今度は仕事が忙しくなり睡魔に襲われる機会が減りそうなので、なかったことになるかもしれないです。
ここを見れば誰でも同じことができるように心がけていますが、訳わかんねー記述があればコメントください。まあ私も素人ですが。
参考サイト
Windows Subsystem for Linuxをインストールしてみよう!
Ubuntuに最新のNode.jsを難なくインストールする
NativeScript-Vue / Installation(英語)
NativeScript Advanced Setup: Linux(英語)
Windows 10のWindows Subsystem for Linux(WSL)を日常的に活用する
- 投稿日:2019-05-21T14:24:43+09:00
【Vue.js】WSL 上で Vue.js を用いた Android アプリを開発する
はじめに
仕事中、睡魔と戦いながら、Android アプリを作ろうと思いました。
ところが私は、C# は触った程度だし Java はコンソールアプリしかやったことがなく GUI はわかりません。そこで調べてみると、HTML で作れるそうじゃないですか。社会人二年目で Web 系しかしていない私にはありがたい話です。
もう少し欲を出して、業務で使用している Vue.js を使えないかなーと思ったら、ちょうどいいのがあるじゃないですか。
というわけで、Windows Subsystem for Linux (WSL) 上で Vue.js を用いて Android アプリを開発するための手順を紹介します。
つかうもの
- WSL : Windows 環境がカオスにならないようにするため
- Vue.js : 今回使いたかったもの
- nativescript : Javascript でアプリ開発できるようにするすごいやつ
- アンドロイド実機 : 開発時の実機との連携がすごい
手順
WSL の有効化から実機での起動まで端折らずにやるよ。
- WSL 環境の構築
- Ubuntu への各種インストール
1. WSL 環境の構築
まずは WSL を有効化し、Ubuntu をインストールします。
コントロールパネル > プログラムのアンインストール を選択
左側 windows の機能の有効化または無効化を選択
Windows Subsystem for Linux にチェックを入れ有効化
インストール完了次第再起動
(念の為)設定 > 更新とセキュリティ > 開発者向け > 開発者モードを有効にする
スタートから Microsoft Store を開く
「Ubuntu」で検索し、Ubuntu を選択
入手をクリックでインストール
スタートから Ubuntu を開く
インストール完了を待ち、ユーザー名とパスワードを入力(パスワードは表示されないので注意)
リポジトリを日本のサーバに変更(sudo 利用時、パスワード入力を求められます)
$ sudo sed -i -e 's%http://.*.ubuntu.com%http://ftp.jaist.ac.jp/pub/Linux%g' /etc/apt/sources.listパッケージのアップデート
$ sudo apt update $ sudo apt upgradeWindows との共有ディレクトリを作成
$ ln -s /mnt/c/Users/(username)/shareWithUbuntu ~/shareWithWindows # (username)はWindows側のユーザ名に置き換え以上で WSL 環境の構築は完了です。WSL 環境をリセットしたい場合は
スタート > Ubuntu 右クリック > アプリの設定 > リセット
から可能です。リセット後は Ubuntu を起動するとまたアカウント設定から始まります。環境破壊と再構築、簡単ですね。2. Ubuntu への各種インストール
NativeScript-Vue での開発に必要なものをインストールしていきます。
Node.js のインストール
$ sudo apt install -y nodejs npm # node、npmのインストール $ sudo npm install n -g # n package導入 $ sudo n stable # nを使用してnodeのstable版をインストール $ sudo apt purge -y nodejs npm # 最初に入れた古いnode、npmは削除 $ exec $SHELL -l # 再ログイン $ node -v # バージョン確認NativeScript CLI のインストール
$ sudo npm install -g nativescriptG++ (C++ のコンパイラ)のインストール
$ sudo apt install g++JDK8 の設定
$ sudo apt install openjdk-8-jdk # JDK8インストール $ sudo update-alternatives --config java # JAVAのバージョンが複数あればJDK8を選択環境変数 JAVA_HOME の追加
~/.bashrc を開く
$ vi ~/.bashrc
Iキーで編集モードに入り、一番下に以下の行を追加
$ export JAVA_HOME=$(update-alternatives --query javac | sed -n -e 's/Best: *\(.*\)\/bin\/javac/\1/p')ESCキーを押し、:wq と入力
Android SDK のダウンロード(Windows 側での操作)
ここ の下の方の「Command line tools only」から Linux のものをダウンロード
ダウンロードした zip ファイルを解凍
解凍した中にある tools ディレクトリを shareWithUbuntu ディレクトリに移動
/usr/lib/android/sdk/ ディレクトリを作成
$ sudo mkdir -p /usr/lib/android/sdk/shareWithWindows ディレクトリ内の tools ディレクトリを /usr/lib/android/sdk/ に移動
$ sudo mv ~/shareWithWindows/tools /usr/lib/android/sdk/環境変数 ANDROID_HOME の追加
~/.bashrc を開く
$ vi ~/.bashrc
Iキーで編集モードに入り、一番下に以下の行を追加
$ export ANDROID_HOME="/usr/lib/android/sdk/" $ export PATH="${PATH}:${ANDROID_HOME}tools/:${ANDROID_HOME}platform-tools/"ESCキーを押し、:wq と入力
再ログイン
$ exec $SHELL -l必要なパッケージのインストール
$ sudo $ANDROID_HOME/tools/bin/sdkmanager "tools" "emulator" "platform-tools" "platforms;android-28" "build-tools;28.0.3" "extras;android;m2repository" "extras;google;m2repository"再ログイン
$ exec $SHELL -l以下のコマンドを実行し、No issues were detected. が出力されれば成功
$ tns doctor # 統計情報を自動送信して良いか聞かれるが n で構わないNativeScript 関連のインストールはここまで。
3. アプリケーションの作成
アプリケーションを作成します。
Vue 関連パッケージのインストール
$ sudo npm install -g @vue/cli @vue/cli-initプロジェクトを作成するディレクトリを作成、移動
$ mkdir workspace && cd workspaceプロジェクトの作成
$ vue init nativescript-vue/vue-cli-template sample-app # 以下対話形式(vue-devtools以外はデフォルトでもOK) ? Project name sample-app # プロジェクト名 ? Project description A native application built with NativeScript-Vue # プロジェクトの説明 ? Application name NativeScript-Vue Application # アプリ名 ? Unique application identifier org.nativescript.application # アプリケーション任意のID ? Project version 1.0.0 # プロジェクトのバージョン ? Author # 開発者 ? License MIT # ライセンスの種類 ? Select the programming language javascript # 使用する言語 ? Select a preset (more coming soon) Simple # 用意するアプリのテンプレート ? Install vuex? (state management) Yes # Vuexを使用するか(デフォルトはNo) ? Install vue-devtools? No # Vuedevtoolsを使用するか(デフォルトはYes) ? Color scheme none # カラーテーマプロジェクトディレクトリに移動し、パッケージインストール
$ cd sample-app && npm installアプリを起動
$ tns preview --bundleプロジェクトの作成からアプリ実行までは簡単ですね。コンソールに表示される QR コードは後ほど利用するので消さないでください。
実機で表示
作成したアプリケーションを実機に表示します。ここでは、Android 側にアプリケーションの導入が必要となります。
- Google Play から NativeScript Playground をインストール
Google Play から NativeScript Preview をインストール
NativeScript Playground を開き、 Scan QR code をタップ
コンソールの QR コードを読み込む
完了
QR の読み込み後に少し時間がかかりますが、個人的には QR 読み込みだけで実機で試せるのは革命的です。
おわりに
NativeScript-Vue のおかげで睡魔に打ち勝つことができました。が、この記事を書いている間は何度も睡魔に負けています。何か実用的なものを NativeScript-Vue で作成してまた記事を上げたいですが、今度は仕事が忙しくなり睡魔に襲われる機会が減りそうなので、なかったことになるかもしれないです。
ここを見れば誰でも同じことができるように心がけていますが、訳わかんねー記述があればコメントください。まあ私も素人ですが。
参考サイト
Windows Subsystem for Linuxをインストールしてみよう!
Ubuntuに最新のNode.jsを難なくインストールする
NativeScript-Vue / Installation(英語)
NativeScript Advanced Setup: Linux(英語)
Windows 10のWindows Subsystem for Linux(WSL)を日常的に活用する
- 投稿日:2019-05-21T12:59:18+09:00
TaskerでSesame miniを手ぶら解錠(RESTask編)
はじめに
SESAMEアプリの手ぶら解錠。とても便利なのですが
どうしても安定性が低くドアの前で待たされることもしばしば。
あれと思ってスマホを開くとようやく開いたり。特にうちでは2台使っているので2台とも手ぶらで開くというのは
5回に1回もないくらいです。投稿時点でもアプリの改善などをしてくれているようなので
それに期待しつつそれまでは自前で対応しようということで
AndroidのアプリであるTaskerを使って手ぶら解錠の仕組みを作ります。HTTP Shortcutsを使った方法はこちらの記事にまとめています。
TaskerでSesame miniを手ぶら解錠(HTTP Shortcuts編)準備するもの
手順1. ダッシュボードで情報収集
APIキーの取得
CANDY HOUSEのダッシュボードにログインして
下の方のAPI settingsからSEND CODEを押して
送られてきた認証コードを入力してConfirm。
CANDY HOUSEダッシュボード
https://my.candyhouse.coAPI KeysでADDを押すと数秒してAPIキーが表示されます。
これは後からは参照できなくなるので必ずコピーしておきましょう。デバイスIDの確認
Sesame Listから操作したいSesameを選択してデバイス画面に移動。
(カーソルがリンク表示になりませんがそのままクリックできます)
各デバイスの画面のURLにデバイスIDが含まれています。https://my.candyhouse.co/#/sesameList/0/********-****-****-****-************この****の部分の文字列をデバイスIDとして記録しておきます。
手順2.Taskerの設定
TaskerとRESTaskをインストールして設定をしていきます。
最終的にプロファイルを2つ、タスクを3つ作ります。手順2-1.タスクの作成と確認アクションの追加
タスクとは動作(アクション)を組み合わせたものです。
作成したいのは解錠するタスクですが、
まずは施錠確認のアクションを作成しましょう。タスクタブの右下の+ボタンでタスクを作成できます。
名前を入力してタスク編集画面に入り、
右下の+ボタンでアクションを追加します。Sesame APIにGETしたいのでTasker自体のアクションである
ネット内のHTTP:GETメソッドを使いたいところなのですが
このメソッドではREST APIが使えません。
そこでプラグインのRESTaskを使用します。アクションの追加でプラグインからRESTaskを選択し
設定の鉛筆アイコンを押すとRESTaskの画面に変わります。ここで設定するのはHostの部分だけです。
https://api.candyhouse.co/public/sesame/********-****-****-****-************ 注)****部分はデバイスID次にHeadersタブに移り以下のヘッダーを追加します。
- Nameは「Authorization」
- Valueには手順1で取得したAPIキー を入力します。
これで右上の▶を押すと以下のようなウィンドウが表示されます。
ざっくりと内容を解説すると、
- 「locked」が施錠状態で、閉まっていればtrue、開いていればfalse
- 「battery」は電池の残量
- 「responsive」はSESAME miniが現在操作可能であるか
を表しています。手動で鍵を開閉して、lockedの状態が反映されることを確認してみましょう。
確認できたら右上の保存ボタンを押して保存します。手順2-2.解錠アクションの追加
そのまま解錠アクションも作成します。
手順2ー1と同様にRESTaskの画面に入り、
- Request TypeをPOST
- Hostは手順2ー1と同じ
https://api.candyhouse.co/public/sesame/********-****-****-****-************ 注)****部分はDevice ID
- Enable custom bodyにチェックを入れて
- Custom bodyに以下を記入します。
{"command":"lock"}次にHeadersタブで以下の2つのヘッダーを追加します。
Header Value Authorization 手順1で取得したAPIキー Content-Type application/json これで右上の▶を押すとTaskIDが表示されて鍵が開きます。
動作が確認できたら保存を押してTaskerに戻ります。解錠を実行して解錠されたことを確認するために
確認アクションの上に解錠アクションを移動して
その間にタスク→待機/Waitで5秒のウェイトを入れます。手順2-3.解錠アクションの結果の取得
これでWeb APIを動かす準備は整ったのですが
Taskerからの実行では結果のウィンドウが表示されないので
このままでは施錠結果を確認することが出来ません。
そこで確認アクションの結果を取得するアクションを追加します。コード→Javascript(小)/Javascriptletを作成し
コードの部分に以下を入力します。var locked = JSON.parse(rtres).lockedRESTaskの実行結果は%rtresという変数に入るので
その中からlockedの内容を取得しています。ちなみに%rtresをそのまま通知などで表示させると
手順2ー1で見たウィンドウの内容が表示されます。これで%lockedに施錠状態(trueかfalse)が入ったので
それを表示したり、分岐したりして使います。これを解錠という名前のタスクとして保存しましょう。
ちなみに通知の内容はこんな感じにしています。手順3.Sesame 発見プロファイルを作成
プロファイルはトリガーとアクションを関連付けるものです。
今回はSesame miniをBluetoothで検知できたら解錠します。公式アプリでは接続できたらBluetooth経由で解錠しているので
接続自体が不安定だったり接続するまで時間がかかったりしますが、
Sesame miniのBluetoothを検知したらWeb APIで解錠するので
Bluetooth接続の不安定性に左右されません。右下の+ボタンでプロファイルを作成して名前(「発見」等)を入力し
状態カテゴリーから「ネット」→「近くのBluetooth」を選択。
住所欄で虫眼鏡の検索アイコンを押して
Sesame miniのMACアドレスを指定します。CANDYHOUSEのDASHBOARDのSesame Listで
Serialに表示されているのがMACアドレスです)Low-Energy(LE)機器と未接続の機器にチェックを入れて戻り、
最後にタスクとして解錠を指定します。これでSesame miniを検知すると解錠タスクが起動します。
これだけでも近づけば解錠するという機能は出来たのですが
家の中にいる時でも玄関に近づくたびに解錠されてしまいます。そこで一度解錠したらこのプロファイルは無効にするようにします。
解錠タスクの編集画面に移ってアクションの追加で
「Tasker」→「プロファイルの状態」から名前に「発見」を指定し
セットに「オフ」を指定します。これで一度解錠したらその後は近付いても解錠されません。
このままではずっと解錠されなくなってしまうので、
次は自宅の付近に近付いたらプロファイルを有効にします。手順4.発見オン/発見オフ タスクを作成
発見をオン/オフするタスクを作成します。
発見オンと名付けたタスクを作成し、
「Tasker」→「プロファイルの状態」から名前に「発見」を指定し
セットに今回は「オン」を指定します。
同様に発見オフというタスクも作成します。
動作確認のために通知を作成しておいた方がいいでしょう。手順5.自宅付近プロファイルを作成
プロファイルの作成から現在地を選択し、自宅の位置を指定します。
範囲は30mか50mがいいと思います。
このプロファイルにはタスクとして発見オンを指定します。指定した発見オンの部分を長押しすると出口タスクを追加できます。
このトリガーが無効になったときに発動するタスクを指定するもので、
ここでは発見オフを指定してバッテリー消費を抑えます。まとめ
以上で、自宅から30mか50m以内に入ったら発見プロファイルが有効になり
周囲のBluetoothを探し始めます。BluetoothでSesame miniが検知されたら解錠タスクが起動し
Web APIから解錠されます。解錠されたら発見プロファイルは無効化されるため
再度玄関に近付いても解錠されることはありません。自宅付近を通過した際には近付いた時に発見が有効になりますが
離れると発見が無効化されるためバッテリー消費を抑えます。おわりに
セキュリティには気をつけて運用してください。
Taskerのデフォルトの設定では画面消灯中の監視は
600秒になっており10分毎にしかチェックされません。
その場合は自宅の範囲を広げて時間稼ぎをするか、
チェックの間隔を短くして対処してください。チェックの間隔を短くするとバッテリー消費は増えます。
私は120秒にして使っています。
- 投稿日:2019-05-21T12:24:27+09:00
アプリ開発で使う mitmproxy 4.0 のコマンド一覧
mitmproxy 4.0チートシート
- アプリ開発でよく使うコマンドをまとめた
- 大きく操作が変わったversion 4での内容です
- 基本的な操作 q, tab, enter, j, k, ctr + d, shift + g, gg は除く
コマンド一覧みたい
?
flow list をフィルタリングしたい
f
並び替え(sort, order by)したい
o
画像のみをフィルタリングしたい
# fを押して f # : set view_filter= が表示されるので、下記を入力 ~a jpgPOST(Method)のみをフィルタリングしたい
f ~m POSTContent-typeでフィルタリング
f ~t jsonflow list をコピーしたい
- Altを押したまま選択
- macだとfnを押したまま選択
flow listを消したい
z
curlコマンドに変換(コピー)したい
# :を押してコマンドプロンプトにして : # 以下を入力でクリップボードにcurl形式でコピー # @focusで表示中の内容をコピー export.clip curl @focus常に一番下に新しい通信を表示したい(followingモード)
F (shift + f) # 解除は再度F
- 投稿日:2019-05-21T10:48:29+09:00
Android エミュレーターでネットワークに繋がらない時
1. SDKの場所を確認する
emulatorのDNSを変更させる
- ターミナルでSDKのパスに移動
cd /Users/xxx/Library/Android/sdk
- さらにemulatorフォルダに移動
cd emulator
- emulatorの一覧を確認
./emulator -list-avdsと打つと、私の場合はこれ↓が返ってきました
Nexus_5X_API_19 Nexus_6_API_22 Pixel_2_XL_API_23 Pixel_XL_API_19
- デバイスを一個ずつ起動させる(Nexus_5X_API_19の箇所は自由に変えてください)
./emulator -avd Nexus_5X_API_19 -dns-server 8.8.8.8この手順でネットワークにつながりました!
- 投稿日:2019-05-21T10:14:58+09:00
Android GoogleMapの使い方メモ
はじめに
最近プロジェクトでGoogleMapAPIを利用したので、細かな使い方を記事として残しておきます。
プロジェクト作成〜地図の表示
AndroidStudioのプロジェクトウィザードで簡単に作れます。
生成された、google_maps_api.xml を開き、
YOUR_KEY_HERE
を更新します。キーは https://console.developers.google.com から取得します。
UIの設定
移動
スワイプで地図を平行移動できます。
googleMap.uiSettings.isScrollGesturesEnabled = trueズーム
ピンチイン・アウトで縮尺を変更できます。
googleMap.uiSettings.isZoomGesturesEnabled = true回転
ピンチからの回転で地図が回転できます。
googleMap.uiSettings.isRotateGesturesEnabled = trueズームボタン
画面右下にズーム変更ボタンが表示されます。
googleMap.uiSettings.isZoomGesturesEnabled = trueツールバー
マーカーをタップした時に、
画面の右下に表示されるGoogleMapのユーザインターフェイスです。googleMap.uiSettings.isMapToolbarEnabled = trueズームボタンと同時に表示するとこのように表示されます。
ティルト
2本指でスワイプで視点を傾けることができます。
googleMap.uiSettings.isTiltGesturesEnabled = trueコンパス
画面左上の表示されます。
googleMap.uiSettings.isCompassEnabled = true現在地表示
ACCESS_COARSE_LOCATION
またはACCESS_FINE_LOCATION
の許可を取得しておく必要があります。googleMap.isMyLocationEnabled = true現在地ボタン
画面の右上に表示されます。
タップすると現在地にカメラと縮尺が調整されます。googleMap.isMyLocationButtonEnabled = trueカメラの移動
// アニメーションなし googleMap.moveCamera(CameraUpdateFactory.newLatLng(latLng)) // アニメーションあり googleMap.animateCamera(CameraUpdateFactory.newLatLng(sydney))カメラの縮尺変更
val zoomValue = 14.0f // 1.0f 〜 21.0f を指定 googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, zoomValue))おおよその詳細レベル
1: World 5: Landmass/continent 10: City 15: Streets 20: Buildingsズームレベルの詳細はこちらを参考に
https://developers.google.com/maps/documentation/android-sdk/views
https://qiita.com/SnowMonkey/items/795779913be692c12a0bマーカー表示
val sydney = LatLng(-34.0, 151.0) googleMap.addMarker( MarkerOptions() .position(sydney) // 地図上のマーカーの位置 .title("Marker in Sydney") // マーカーをタップ時に表示するテキスト文字列 .snippet("Australian cities") // タイトルの下に表示される追加のテキスト .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE)) // アイコン )また、マーカーをタップしなくても吹き出しを表示することも出来る。
val marker = googleMap.addMarker( MarkerOptions() .position(latLng) .title("test") .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED)) ) marker.showInfoWindow() // タップした時と同じ挙動円の描画
val latLng = LatLng(35.681236, 139.767125) // 東京駅 val radius = 1000 * 10.0 // 10km googleMap.addCircle( CircleOptions() .center(latLng) // 円の中心位置 .radius(radius) // 半径 (メートル単位) .strokeColor(Color.BLUE) // 線の色 .strokeWidth(2f) // 線の太さ .fillColor(0x400080ff) // 円の塗りつぶし色 )線の描画
googleMap.addPolyline( PolylineOptions() .add(LatLng(35.681236, 139.767125)) // 東京駅 .add(LatLng(34.7331, 135.5002)) // 新大阪駅 .color(Color.RED) // 線の色 .width(8f) // 線の太さ )2点間に距離を計算(SphericalUtil)
距離を簡単に計算するのに必要なユーティリティライブラリを追加します。
https://developers.google.com/maps/documentation/android-sdk/utility//app/build.gradledependencies { ... // add implementation 'com.google.maps.android:android-maps-utils:0.5' }検証として、
東京駅
〜新大阪駅
の緯度経度を使います。val latLngA = LatLng(35.681236, 139.767125) val latLngB = LatLng(34.7331, 135.5002) // 距離をメートル単位で返す val distance = SphericalUtil.computeDistanceBetween(latLngA, latLngB) println("AB: $distance m") println("AB: ${distance / 1000} km")出力
AB: 401709.92548952583 m AB: 401.70992548952586 km
以下は、PCのブラウザでGoogleMapで距離を測った結果です。
2点間に距離を計算(Location)
ユーティリティライブラリを入れなくても、
Location
クラスで2点間の距離を計算できます。
簡単に呼び出せるように以下のExtension
を定義しておきます。fun LatLng.distanceBetween(toLatLng: LatLng): Float { val results = FloatArray(1) try { Location.distanceBetween( this.latitude, this.longitude, toLatLng.latitude, toLatLng.longitude, results ) } catch (e: IllegalArgumentException) { return -1.0f } return results[0] }呼び出し元
val latLngA = LatLng(35.681236, 139.767125) val latLngB = LatLng(34.7331, 135.5002) // 距離をメートル単位で返す val distance = latLngA.distanceBetween(latLngB) println("AB: ${latLngA.distanceBetween(latLngB)} m") println("AB: ${latLngA.distanceBetween(latLngB) / 1000} km")
SphericalUtil
と比較した結果、こちらは少し誤差が出るようです。AB: 402483.6 m AB: 402.48358 km
まとめ
本記事で記述しているのはGoogleMapAPIの中でもごく一部です。
忘れた頃にいちいちググりにいくのが面倒なので、ひとまずまとめておきました。公式資料
https://developers.google.com/android/reference/com/google/android/gms/maps/GoogleMap
http://googlemaps.github.io/android-maps-utils/javadoc/com/google/maps/android/SphericalUtil.html
- 投稿日:2019-05-21T09:54:03+09:00
いまさらWorkManager〜基本編③(繰り返し処理を実行する)〜
はじめに
この記事で説明した通り、様々な機能を活用していきましょう。
今回は、繰り返し処理を設定する方法を学習していきます。動作環境
この記事の動作環境は以下のとおりです。
- Android Studio:3.3
- Kotln:1.3.11
- Open JDK:1.8
- compileSdkVersion:28
- targetSdkVersion:28
- minSdkVersion:19
目標
繰り返して処理を実行出来るようになる!
概要
繰り返し処理を実行したい場合は、PeriodicWorkRequestクラスを利用します。
連続して実行は出来ませんが、ある一定時間(インターバル)を置いて実行が可能です。
イメージとしてはこんな感じでしょうか。実際に一定のインターバルでノーティフィケーションを表示する処理をすると下図のような実行結果になります。
実装方法
基本的な実装方法はOnetimeWorkRequestと同じですが、最後のRequestオブジェクトを作成する時に、インターバルなどの設定を行います。
PeriodicWorkRequestオブジェクトを生成するには、Builderクラスを利用します。
そのコンストラクタで、インターバルを設定します。共通の条件
インターバルの最小時間は決まっています。 PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS 以上でなければなりません。
定義を確認してみると。。。public final class PeriodicWorkRequest extends WorkRequest { /** * The minimum interval duration for {@link PeriodicWorkRequest} (in milliseconds). */ public static final long MIN_PERIODIC_INTERVAL_MILLIS = 15 * 60 * 1000L; // 15 minutes. 〜〜〜省略〜〜〜〜 }となっていました。
なので、最低でも 15分 以上は開ける必要があります。PeriodicWorkRequest.Builder(Class<? extends ListenableWorker> workerClass, long repeatInterval, TimeUnit repeatIntervalTimeUnit)
コンストラクタの引数
引数 値と説明 第1引数 Workerクラスのクラス情報 第2引数 インターバルの時間 第3引数 時間の単位 説明
APIの説明を読むと以下のように記述されています。
引数で指定したインターバル期間に実行するPeriodicWorkRequeクラスのオブジェクトを生成します。
PeriodicWorkRequestはインターバルの期間中に1度だけ実行されることが保証されています。
バッテリーや端末の状況によっては、その影響を受ける可能性はあります。実行する処理は15以上間隔を開ける必要があります。それ以外の条件が満たされていれば、その期間中に実行可能状態になります。また、実行する処理の時間はフレックス期間を設定し、制限することも可能です。
ということは、インターバル期間中に実行が可能なれば実行できるみたいです。
きっちり15分間とかではなく、その15分間の中で実行されるイメージみたいです。
分かりづらいですが、絵にすると下図のような感じになります。また、フレックスについては、後述します。
実装例
val periodicWork = PeriodicWorkRequest.Builder( MyWorker::class.java, 15, TimeUnit.MINUTES ).build()public PeriodicWorkRequest.Builder (Class<? extends ListenableWorker> workerClass, Duration repeatInterval)
コンストラクタの引数
引数 値と説明 第1引数 Workerクラスのクラス情報 第2引数 インターバルの時間と単位 説明
基本的には、上記に記載した「PeriodicWorkRequest.Builder(Class<? extends ListenableWorker> workerClass, long repeatInterval, TimeUnit repeatIntervalTimeUnit)」と同じです。
違いとしては、インターバルの時間をDurationクラスのメソッドを使用して、時間と単位を一度に設定できることです。実装例
val periodicWork = PeriodicWorkRequest.Builder( MyWorker::class.java, Duration.ofMinutes(15) ).build()PeriodicWorkRequest.Builder(Class<? extends ListenableWorker> workerClass, long repeatInterval, TimeUnit repeatIntervalTimeUnit, long flexInterval, TimeUnit flexIntervalTimeUnit)
コンストラクタの引数
引数 値と説明 第1引数 Workerクラスのクラス情報 第2引数 インターバルの時間 第3引数 インターバルの時間の単位 第4引数 フレックスの時間 第5引数 フレックスの時間の単位 説明
インターバルの時間内にフレックス時間を設け、そのフレックス時間内に処理が実行されます。
フレックス時間は下記で計算された時間からインターバル終了までとします。フレックス開始時間 = インターバル時間 ー フレックス時間
また、インターバルの時間は最低でもPeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS(15分以上) 以上、フレックスの時間は、最低でもPeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS(15以上)に設定しなければなりません。
これだけだといまいちピンとこなかったので、図にしてみました。
要するに、インターバルの中にフレックスがありそのフレックスの時間の間で処理を実行します。
フレックス時間の終了はインターバルの終了時間と同じであるため、インターバルの最初の方で処理が実行されることはありません。実装例
val periodicWork = PeriodicWorkRequest.Builder( MyWorker::class.java, 20, TimeUnit.MINUTES, // インターバルの時間 15, TimeUnit.MINUTES // フレックスの時間 ).build()PeriodicWorkRequest.Builder(Class<? extends ListenableWorker> workerClass, Duration repeatInterval, Duration flexInterval)
コンストラクタの引数
引数 値と説明 第1引数 Workerクラスのクラス情報 第2引数 インターバルの時間と単位 第3引数 フレックスの時間と単位 説明
基本的な内容はPeriodicWorkRequest.Builder(Class<? extends ListenableWorker> workerClass, long repeatInterval, TimeUnit repeatIntervalTimeUnit, long flexInterval, TimeUnit flexIntervalTimeUnit)と同じです。
違いとしては、Durationクラスを利用して、時間と単位を一気に設定します。実装例
val periodicWork = PeriodicWorkRequest.Builder( MyWorker::class.java, Duration.ofMinutes(20), // インターバルの時間 Duration.ofMinutes(15) // フレックスの時間 ).build()動作確認をした際のコード
最後に、動作確認した際のコードをすべて掲載します。
AndroidManifest.xmlはプロジェクトのテンプレートから変更していないため、掲載はしません。build.gradleapply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' android { compileSdkVersion 28 defaultConfig { applicationId "jp.co.casareal.workmanagerperiodicwork" minSdkVersion 19 targetSdkVersion 28 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support.constraint:constraint-layout:1.1.3' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' def work_version = "1.0.0" implementation "android.arch.work:work-runtime-ktx:$work_version" }MyWork.ktpackage jp.co.casareal.workmanagerperiodicwork import android.app.NotificationChannel import android.app.NotificationManager import android.content.Context import android.os.Build import android.support.v4.app.NotificationCompat import androidx.work.Worker import androidx.work.WorkerParameters import java.text.SimpleDateFormat class MyWorker(cxt: Context, params: WorkerParameters) : Worker(cxt, params) { val notificationManager = applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager // カテゴリー名(通知設定画面に表示される情報) val name = "通知のタイトル的情報を設定" // システムに登録するChannelのID val id = "casareal_chanel" // 通知の詳細情報(通知設定画面に表示される情報) val notifyDescription = "この通知の詳細情報を設定します" private val simpleDateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss") companion object { var nid = 1; } init { // Channelの取得と生成 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { notificationManager.getNotificationChannel(id) == null val mChannel = NotificationChannel(id, name, NotificationManager.IMPORTANCE_HIGH) mChannel.apply { description = notifyDescription } notificationManager.createNotificationChannel(mChannel) } } override fun doWork(): Result { val notification = NotificationCompat.Builder(applicationContext, id).apply { setContentText("${nid}回目のメッセージ:${simpleDateFormat.format(System.currentTimeMillis())}") setSmallIcon(R.drawable.ic_launcher_background) } notificationManager.notify(MyWorker.nid, notification.build()) MyWorker.nid++ return Result.success() } }MainActivity.ktpackage jp.co.casareal.workmanagerperiodicwork import android.os.Build import android.os.Bundle import android.support.v7.app.AppCompatActivity import androidx.work.PeriodicWorkRequest import androidx.work.WorkManager import kotlinx.android.synthetic.main.activity_main.* import java.time.Duration class MainActivity : AppCompatActivity() { private val manager = WorkManager.getInstance() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) buttonStart.setOnClickListener { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val periodicWork = PeriodicWorkRequest.Builder( MyWorker::class.java, Duration.ofMinutes(15) ).build() val operation = manager.enqueue(periodicWork) } } } }activity_main.xml<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <Button android:id="@+id/buttonStart" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent"/> </android.support.constraint.ConstraintLayout>まとめ
繰り返し実行する場合は、インターバルの時間を設定することが大事なようです。
そこで、インターバルの時間を開始してから実行を遅らせるためにフレックスの時間を利用することによって適切なタイミングでの実行が可能になっていることがわかりました。
- 投稿日:2019-05-21T09:13:32+09:00
Genymotionのemulatorがネットワークに繋がらない
はじめに
最近、expoを用いてクロスプラットフォームにアプリ開発を行っています。
その中でandroidで動作確認を行うのにGenymotionを使っているのですが、emulatorが全然ネットワークにつながってくれなかったのでその解決方法について書きます。Genymotionとは
ここでは詳しく説明しませんが、Android StudioのAVDよりも高速に動くemulatorです。Virtual Box上で動きます。
個人利用であれば無料でで使えます。
詳細はこちら問題
全然ネットワークにつながってくれない。
GenymotionもしくはVirtual Boxのネットワークの設定が間違っているのでしょうが、どこをどういじればいいかわからず、とりあえずググッて出てきた解決策を試してみました。
実際にこれらを試してみましたが、だめでした。
https://stackoverflow.com/questions/33075796/genymotion-emulator-no-internet-connection
https://qiita.com/shymst/items/1bb60ca0c8a020ce6bc2解決策
Virtual Boxの設定でNATネットワークを作成するとネットワークに繋がりました。
- Virtual Boxの設定 >> ネットワーク
- NATネットワークの追加(設定はデフォルトのまま)
- emulator起動
- wifiつながった
参考: https://stackoverflow.com/a/36151812
さいごに
たったこれだけのことでしたが、仮想環境でのネットワークについての理解がまったくないのでめちゃくちゃ時間がかかりました。
これを期に仮想環境、ネットワーク周りの勉強をしようと思います。
- 投稿日:2019-05-21T08:54:51+09:00
AndroidのFragmentでOverlayViewを表示する
Solution
res/layout/partial_overlay.xml<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/overlay_screen_bg"> <!-- クリックイベントをセットするためのView --> <View android:id="@+id/view_bg" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" /> ... </androidx.constraintlayout.widget.ConstraintLayout>HogeFragment.ktclass HogeFragment : Fragment() { override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) showOverlayView() } private fun showOverlayView() { // activityのrootを取得 val rootLayout = requireActivity().findViewById(android.R.id.content) as FrameLayout // overlayViewを表示 val overlayView = View.inflate(requireActivity(), R.layout.partial_overlay, rootLayout) // view_bgをタップしたら非表示にする overlayView.view_bg.setOnClickListener { rootLayout.removeViewAt(rootLayout.childCount - 1) } } }参考
https://stackoverflow.com/questions/14194967/android-addview-adding-a-new-view-on-top-of-activity
- 投稿日:2019-05-21T08:54:11+09:00
Picassoで画像キャッシュを無効にする
案件でPicassoのキャッシュを無効にする事になり、ちょっと調べた情報をまとめる。
Picassoのデフォルトの動作
Picassoのデフォルトの動作は以下
- メモリキャッシュはアプリケーションRAMの15%
- ディスクキャッシュはストレージサイズの2%で最大50MB
- 注:これはAPI 14+で、またはOkHttpのようなすべてのAPIレベルでディスクキャッシュを提供するスタンドアロンライブラリを使用している場合にのみ利用可能
- ディスクおよびネットワークアクセス用の3つのダウンロードスレッド。Picassoは常に最初にメモリキャッシュから画像をロードしようとする。
メモリキャッシュになければ、ディスクキャッシュをチェックする。
ディスクキャッシュもなければネットワーク処理をリクエストする。つまり、
メモリ -> ディスク -> ネットワーク
の順にチェックする。また、Picassoで表示する画像はメモリ/ディスクキャッシュの両方に保管される。
キャッシュ無効
メモリキャッシュ、ディスクキャッシュを両方とも無効にする必要がある。
java
Picasso.get()
.load(url)
.memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_STORE)
.networkPolicy(NetworkPolicy.NO_CACHE)
.into(imageView);
参考リンク
- Picasso — Influencing Image Caching https://futurestud.io/tutorials/picasso-influencing-image-caching
- Picassoでキャッシュの簡単設定 - Qiita https://qiita.com/hoonokonoko/items/fc4a16bf187faf39979a
- 投稿日:2019-05-21T08:08:24+09:00
WebViewとネイティブのメリットデメリット
App内で動作する簡易ブラウザ(WebView)と通信からUIまでアプリ内で完結するネイティブアプリのメリットデメリットをまとめてみました。
■WebViewのメリット・デメリット
メリット
コストが安い
Web上にコンテンツがあり、それを流用したい場合、新規で開発することなく同じコンテンツを表示できます。アプリストアへの申請・審査の不要
ネイティブアプリの申請や審査が不要になります。
※ただし、部分的なWebView表示の場合ネイティブと変わらないので審査は必要です。アプリアップデートの不要
アプリの保守をする必要がないため、アプリ自体のアップデートがありません。
※仕様が変更された時は、アプリの動作を変更する可能性があるため、一概ではないです。デメリット
課金ができない
Apple Store審査ガイドラインの規約違反になり、リジェクトされる恐れがあります。
※Webブラウザでの課金は可能(リンクをブラウザへ飛ばす必要あり)
引用:Apple Store審査ガイドライン:3.1.1 App内課金レスポンシブ対応
画面解像度に応じたUI設計の対応が必要。
Webの表示をそのまま、アプリに適応させると表示崩れが起こる可能性がある。脆弱性
自社以外の外部アクセス
URL直打ちで、自社ではないサイトにアクセスできる場合、悪用される恐れがある。
外部アクセスできるサイトに制限を設ける必要がある。端末内のファイルストリームにアクセスできる
「file://」で始まるURI(※URLではない)でアクセスすることで、端末内部のファイルにアクセスすることができる。
アクセスログからユーザー情報が漏洩されてしまう。iOSは、Cookieを保存しない
アプリが終了するとCookieが消えるので、永続化する必要がある
XSSの恐れ
攻撃スクリプトを入力できてしまう。
サニタイジング(無害化)する必要がある。通信エラー場合の表示
通信エラー場合のWebView画面を表示する前に、レスポンスチェックを行い、ネイティブの別画面を表示させる。
WebViewは通信した結果の表示なので、真っ白になったり、URLエラーになったりしてUI的に作りが悪い。環境によっては表示が遅い
Web通信が伴うため、通信環境によっては表示が遅い場合があります。■ネイティブ画面のメリット・デメリット
メリット
Webではできない画面設計・操作設計ができる
アプリ内のUIを使用するため、自由に画面設計を行うことが可能導線設計が可能
アプリに誘導できるセキュリティ
URL直打ちではないため、外部のサイトへアクセスさせることはないです。デメリット
コストが高い
iOS / Androidの開発者が必要
開発言語が異なるため、それぞれの開発者が必要アプリストアへの申請・審査
ネイティブアプリの申請や審査が必要です。アプリアップデートが必要
保守でアプリ修正があった場合は、アップデートが必要課金
App内課金を(30%)手数料(30%)が発生する引用
https://appbu.jp/webapps-nativeapps
https://ja.developer.box.com/docs/android-security-guidelines
https://appkitbox.com/knowledge/android/20130819-84
https://teratail.com/questions/100872
https://mexess.blog/2018/08/03/post-304/
https://qiita.com/noboru_i/items/240ffcb2036f3b5cbc3b
https://qiita.com/noboru_i/items/bc39d95638e9e55437fa#cookie%E3%81%AE%E8%A8%AD%E5%AE%9A
https://qiita.com/i_nak/items/be0fac91bdc68aa165db
https://backapp.co.jp/blog/11594/
https://support.ebis.ne.jp/search_service/15033/