最近はAndroid Studioで開発するのが主流っぽい。
URL
- 全体像: Huaweiから学ぶ、AndroidのOS開発やライセンス
- Android AOSP( Android Open Source Project)
- Google Mobile Services
- 各メーカーが独自に追加した機能
AndroidStudioの状態
* Android Studio -> About Android Studio
* File -> Project Structure
Modulesなどで、Javaのバージョン指定ができる
* File -> Other Settings -> Default Project Structure.
Google Cloud Messaging (GCM) APIは2019年4月11日付けで廃止
- Android Studio
- HAXM
home-brewでもインストール可能。
最近は、studioインストール時にインストールされる。
システム環境設定 -> 一般 に許可を求めてくるので、解除する必要がある。
- HAXM
- gradle
Editor
- Alt + Shift + click: マルチカーソル
keyboardだけで操作がわからん、、?? - Alt + Enter import追加
Resource
DPI | scale | dp | px | example | dpi |
---|---|---|---|---|---|
ldpi | x0.75 | 4dp | 3px | 36x36 | <=120 |
mdpi | x1 | 4dp | 4px | 48x48 | <=160 |
hdpi | x1.5 | 4dp | 6px | 72x72 | <=240 |
xhdpi | x2 | 4dp | 8px | 96x96 | <=320 |
xxhdpi | x3 | 4dp | 12px | 144x144 | <=480 |
xxxhdpi | x4 | 4dp | 16px | 192x192 | <=640 |
- dpi
https://developer.android.com/training/multiscreen/screendensities - ldpiは必要なさそう
https://stackoverflow.com/questions/18213668/are-android-ldpi-assets-icons-still-needed
Log
- https://elinux.org/Android_Logging_System
- https://proandroiddev.com/managing-logging-in-a-multi-module-android-application-eb966fb7fedc
Emulator
wipe
Sign
keytool -printcert -jarfile app/release/app-release.apk
keytool -v -list -keystore keystore.jks
署名が古いと警告が出る
keytool -v -importkeystore -srckeystore keystore.jks -srcalias alias_name -destkeystore 出力用p12ファイル名 -deststoretype PKCS1
keytool -importkeystore -srckeystore old_keystore.jks -destkeystore new_keystore.jks -deststoretype pkcs12
netowrk
Update
Google Playストアアプリが検知する方法
Google I/O 2019にて正式版がリリース
HTMLをparseしてversionを取得する方法
仕組み
アプリの更新を管理する
ユーザーのデバイスのアプリを常に更新することでユーザーは最新の機能を利用できるようになり、アプリのセキュリティや安定性も向上します。
この記事では、IT 管理者が組織の管理対象デバイスにインストールされているアプリを最新のバージョンに保つ手順を説明します。
デフォルトの更新動作
デフォルトでは、次の条件を満たしている場合にアプリが自動的に更新されます。
* デバイスが Wi-Fi ネットワークに接続されている。
* デバイスが充電中である。
* デバイスがアイドル状態である(操作を行っていない)。
* 更新対象のアプリがフォアグラウンドで実行されていない。
一般に、Google Play では 1 日に 1 回、アプリのアップデートを確認しています。
そのため、アプリのアップデートが更新キューに追加されるまで最長で 24 時間ほどかかることがあります。
キューに追加されたアプリは、上記の条件を次回満たしたときに自動的に更新されます。
FullScreen
- 全画面モードを有効にする
- https://developer.android.com/training/system-ui/immersive?hl=ja
SYSTEM_UI_FLAG_IMMERSIVE_STICKY
SYSTEM_UI_FLAG_FULLSCREEN
SYSTEM_UI_FLAG_HIDE_NAVIGATION
proguardメモ
- http://yuki312.blogspot.com/2012/03/androidproguard_09.html
- https://qiita.com/samuraijap/items/100b2e679fbd6972e499
デフォルト設定を忘れずに
keymapping
Keymap → Main menu → Code → Completion → Basic
xcodeに近づける
Push通知
Dozeモードに関する注意
Android 6.0以降
バッテリーが長持ちする反面、バッググラウンドが制限される。
https://firebase.google.com/docs/android/setup?hl=ja
- Android プロジェクトに Firebase を追加する
サービスとGradleの依存情報を取得。 (※versionは古いので合わせる。) - 有用:「マッチングが成立しました!」通知を見てニタニタしたい。(FirebaseでAndroidアプリに通知を送るまで)
運用
- オープンテスト版、クローズド テスト版、内部テスト版をセットアップする
- FCM -> Device
デバイストークンが必要(テストなど) - API -> FCM -> Device
- Cloud Messagingのウェブ API キー
- プロジェクト認証情報のサーバーキー
curl -X POST https://fcm.googleapis.com/fcm/send -H 'Authorization: key=<APIキー>' -H 'Content-Type: application/json' -d '{
"notification" : {
"title": "title",
"body": "message",
"sound":"default",
"icon":"@android:drawable/sym_action_chat",
"color":"#FF8000"
} ,
"to" : "<トークン>",
"priority":"high"
}'
- Android で Firebase Cloud Messaging クライアント アプリを設定する
自動生成を停止するか検討。 - バックグラウンド アプリにテスト メッセージを送信する
- Android アプリでメッセージを受信する
- Firebase リリース チェックリスト
- AdMob
lint
- https://developer.android.com/studio/write/lint?hl=ja
- https://www.lifull.blog/entry/2015/01/07/104745
Site
- https://play.google.com/apps/publish/signup/
$25
Sign
Gradle https://developer.android.com/studio/build/build-variants?hl=ja
Version
- versioning
versionCode is 2100000000
- https://stackoverflow.com/questions/4616095/how-to-get-the-build-version-number-of-your-android-application
PackageManager, BuildConfigとか、 Build.VERSION.SDK_INT
Gradle
- https://developer.android.com/studio/build/gradle-tips.html
Intentのflg
FLAG_ACTIVITY_NEW_TASK 新しいタスクでActivityを起動
FLAG_ACTIVITY_SINGLE_TOP 現在のActivityと同じアクティビティは起動しない
FLAG_ACTIVITY_CLEAR_TOP 該当のActivity上にスタックされたタスクをクリアしてから起動
FLAG_ACTIVITY_NO_ANIMATION トランジションアニメーション無し
FLAG_ACTIVITY_NO_HISTORY 起動時にスタックに追加しない
FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY スタック内のActivityを使いまわす
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 履歴内のActivityを使いまわす
FLAG_ACTIVITY_PREVIOUS_IS_TOP 元のActivityをタスクのトップとして起動する
FLAG_ACTIVITY_REORDER_TO_FRONT スタック内の同一Activityを最前面へ移動させる
update
- https://qiita.com/kurun_pan/items/0e4d916d106f64942195
SSL
https://developer.android.com/training/articles/security-ssl?hl=ja
openssl s_client -connect test.com:443 | openssl x509 -noout -subject -issuer
基本doc
https://developer.android.com/studio/publish/app-signing?authuser=1#generate-key
keytool -v -list -keystore ./keystore/file.keystore
の情報を貼り付けておけばok
https://coderwall.com/p/r09hoq/android-generate-release-debug-keystores
keytool -genkeypair -dname "CN=xxx, OU=xxx, O=xxx, L=xxx, ST=xxx, C=JP" \
-alias aliaskey \
-keypass passwd \
-keystore ./keystore/file.keystore \
-validity 9125 \
-keyalg RSA \
-keysize 2048
opensslで上記を再現しようと思ったけど、CAがよくわからん。
keytoolでサーバーに送られてsignされていると思われる。(未確認)
opensslではsubjを使用し、セパレータはスラッシュ。
パスワード変更
keytool -storepasswd -keystore file.keystore
keytool -keypasswd -alias myalias -keystore file.keystore
AutoBackup
https://toconakis.tech/androidautobackup/
Debuger
https://github.com/facebook/stetho
Adb
adb version
adb devices
adb shell pm list package
adb install xxxx.apk
adb install -r xxxx.apk
adb uninstall [package name]
adb push ~/temp.png /sdcard/Download/
インストール済みのパッケージ情報
adb shell dumpsys package [packagename]
pm: package manager.
am: application manager.
activityを起動したりとか
# Activityの起動(ACTION_VIEW + URL)
am start -a android.intent.action.VIEW -d http://google.com
# Activityの起動(クラス名を指定)
am start -n com.hoge.app/.FugaActivity
# サービスの起動
am startservice ... # Intentの指定方法はActivityと同じ
# ブロードキャストの送信
am broadcast ... # Intentの指定方法はActivityと同じ
fileの転送だと、pull, push. logcatコマンドでログの表示
aapt
macosだと
/System/Volumes/Data/Users/[user name]/Library/Android/sdk/build-tools/[version]/
にあったりするので、PATHを通す.
aapt l -a app.apk | grep "A: package"
aapt l -a app.apk | grep "android:version"
aapt d badging app.apk | grep "application:"
名称
- ドロワー (cf.アプリ一覧)
- フォルダー
- クイック設定パネル *ドック
- ナビゲーションバー(戻るボタン、ホームボタン、マルチタスクボタン)
アプリ画面
- アプリバー、アクションバー
- ボトムナビゲーション
- Floating Action Button(FAB)
- タブ
- ナビゲーションドロワー、サイドメニュー
- スナックバー
- ダイアログ
- ボトムシート
ConstraintLayout vs Coordinator layout?
- CoordinatorLayoutは、 Behaviors を管理するアクティビティのトップレベルレイアウトとなることを目的としています
- ConstraintLayoutの主な目標は、複数の子を持つフラットレイアウトを作成する便利な方法を提供することです(より強力なRelativeLayout)。
開発メモ
赤線
File -> 'Invalidate Caches / Restart'
Image
res/drawable/
などのリソースを実行デバイスの解像度に合わせて、 拡大・縮小を行うようだ(未確認)。
dip(density-independent pixels)
の考え方にしがたい上記の処理を行うので、
その処理を省くには、drawable-hdpi
のフォルダを作成することで、
多分、該当dpiフォルダを探し、なければdrawableの画像を処理という流れだと思う?ビルド時にaaptツールが変更している模様(要調査)。
mipmap
はアプリケーション(Android4.2以降)内での拡大・縮小が発生した時に切り替えてくれるリソースとなる。
基本API経由で使用する。
bitstreamとして読み込む場合は、res/raw/
に画像をおく。
assetsフォルダに置いた場合は、idは生成されない。
rawは、Resources、assetsは、AssetManager. (App resources overviewより)
- Drawable resources
- Drawables overview
- Support different pixel densities
- Create WebP images
- App resources overview
Android の画像リソース(アイコンも)にはJPEG形式を使うこともできますが、JPEG は写真のような画像の圧縮には向いているものの、アプリで使用するアイコンやUI画像の圧縮には向いていません。アイコンやUI 画像の圧縮にはPNG、特にPNG8(8bitPNG) が向いています。ただし、PNG8を使う場合は、高画質で減色できるツールを使う必要があります。
Memo
- Long Tap(Detecting a long press with Android) sample
final GestureDetector gestureDetector = new GestureDetector(new GestureDetector.SimpleOnGestureListener() {
public void onLongPress(MotionEvent e) {
Log.e("", "Longpress detected");
}
});
public boolean onTouchEvent(MotionEvent event) {
return gestureDetector.onTouchEvent(event);
};
https://material.io/components/bottom-navigation#placement
UI Flag
http://y-anz-m.blogspot.com/2013/11/kitkat-android-44-ui.html
TableLayout
https://developer.android.com/guide/topics/ui/layout/grid
Notification
- 通知の概要
- Create and Manage Notification Channels どうも、IDとImportanceはuniqでkeyになるっぽいので、削除してすぐ作りなおししても、うまく反映されないっぽい。
Notification Dot Color
Applicationアイコンにより色が自動的に決定するとのこと。
今のところ変更できる余地はない。
setting
android:configChanges=“orientation|screenSize”
回転時のActivityの再生成を抑止。
https://developer.android.com/guide/topics/resources/runtime-changes.html#HandlingTheChange
layout
android:fitsSystemWindows="true"
AndroidX
support-v7-appcompat はdeprecated.
androidxに移行しているので注意。
Navigation
https://developer.android.com/guide/navigation/navigation-ui?hl=ja
Design
https://material.io/
https://material.io/develop/android/docs/getting-started
FullScreen Dialog
https://material.io/components/dialogs#actions
DataBinding
alt(opt) + enter
SSL関連
http://www.jssec.org/dl/android_securecoding_20180201/5_how_to_use_security_functions.html
めも
android:text="Hi Hello"
Data Binding
- XML -> select "parent element"
option + Enter
Convert to date binding layout
XMLにbindさせる場合は、Stringであること。
android:text="@{`` + mode.intValue}"
android:text="@{Integer.toString(mode.intValue)}"
Dialog
回転が絡むと、ライフサイクルが絡むので注意。
Snippet
// navigation bar
Resources resources = getContext().getResources();
int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
int navigationBar = 0;
if (resourceId > 0) {
logger.info(String.format("resourceId=%s", resourceId));
navigationBar = resources.getDimensionPixelSize(resourceId);
logger.info(String.format("navigationBar=%s", navigationBar));
rowHeightSpacer = navigationBar + 48;
}
logger.info(String.format("rowHeightSpacer=%s", rowHeightSpacer));
DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
int spaceHeight = (int) (48 * metrics.density);
logger.info(String.format("spaceHeight=%s", spaceHeight));
Drawable drawable = ResourcesCompat.getDrawable(res, R.drawable.circle_progress, null);
ProgressBar progressBar = new ProgressBar(getContext(), null, android.R.attr.progressBarStyleHorizontal);
progressBar.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.circle_progress_bg, null));
progressBar.setProgressDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.circle_progress_fg01, null));
progressBar.setLayoutParams(new TableRow.LayoutParams(cellSize, cellSize));
progressBar.setMax(100);
progressBar.setProgress(10 * 3);
progressBar.setTag(rec);
XML
android:checked
android:focusable
を取得する場合
TypedArray a = context.obtainStyledAttributes(
attrs,
new int [] { android.R.attr.focusable, android.R.attr.checked });
boolean focusable = a.getBoolean(0, true);
boolean checked = a.getBoolean(1, false);
※int配列はソート済みだとダメとの情報。
resource
android.resource://[package]/[resource_id]
android.resource://[package]/[res type]/[res name]
So the following would be managable.
String pkgName = getApplicationContext().getPackageName();
Uri path = Uri.parse("android.resource://"+pkgName+"/" + R.drawable.icon);
Uri otherPath = Uri.parse("android.resource://"+pkgName+"/drawable/icon");
Alerm
ここが有用
https://akira-watson.com/android/alarmmanager-timer.html
inflate
ハマったので、、
- attachToRootがtrueの場合は、addViewされる(記述は必要ない)。
- attachToRootがtrueの場合、親View、falseの場合はlayout Viewで挙動が異なる
- mergeタグのlayoutをinflateする場合は、attachToRootはtrue
Icon
https://github.com/konifar/Android-material-design-icon-generator-plugin
https://github.com/google/material-design-icons
https://material.io/resources/icons/?style=baseline 上記でsvg取得して、AndroidStudioで取り込む方法を採用
ID
JWT
https://github.com/auth0/JWTDecode.Android https://github.com/auth0/java-jwt
Animation
遷移時
* https://developer.android.com/guide/components/intents-common?hl=ja
* https://developers.cyberagent.co.jp/blog/archives/9291/
アニメーション入門 * https://qiita.com/suzukihr/items/7d5caa32eb0bdb22bb23
Releaseに向けて
GPC(Google Play Console)
公開の概要 -> 管理対象の公開のステータス
管理対象の公開をオフにすると自動公開
手動公開にする場合は、変更する。
手動公開にした場合
公開の概要 -> 確認して公開 ボタンが表示される
SharedPreferences
All shared prefs are stored in /data/data/[package name]/shared_prefs/[app name].xml, so i think there's no limit based on architecture.
Strage
Device File Explorer
* [View] > [Tool Windows] > [Device File Explorer]
* ツール ウィンドウ バーにある Device File Explorer アイコン
Android: /data/data配下にadb push
# ファイルを一時領域へコピー
$ adb push hoge /data/local/tmp
# アプリユーザに切り替え
$ adb shell
$ adb run-as <Application ID>
# ファイルコピー
$ cp /data/local/tmp/hoge /data/data/<ApplicationID>/hoge
## ↑でエラーが出た場合はcatリダイレクトする
$ cat /data/local/tmp/hohe > /data/data/<Application ID>/hoge
ファイルのコピー関連うまくいかなかったんだよな、、また変わったのかな?
adb shell pm grant <PACKAGE_NAME> <PERMISSION>
adb shell pm revoke <PACKAGE_NAME> <PERMISSION>
adb shell pm list packages
adb shell pm list permissions -g
movie
Logcatに動画アイコンボタンがあるので押す。(webm)
ffmpeg -i test.webm -pix_fmt yuv420p test.mp4
LogCat
制限があるので注意
* adb logcatでログを書き出すときに、長いmessageだと途中で切れてしまう問題
adb logcat -g
main: ring buffer is 2 MiB (191 KiB consumed), max entry is 5120 B, max payload is 4068 B
system: ring buffer is 2 MiB (2 KiB consumed), max entry is 5120 B, max payload is 4068 B
crash: ring buffer is 2 MiB (0 B consumed), max entry is 5120 B, max payload is 4068 B
kernel: ring buffer is 2 MiB (0 B consumed), max entry is 5120 B, max payload is 4068 B
これ以上の文字列を表示しようとすると、切り取られる。
Spell, Dictionary
AndroidStudioのPreferenceから Editor -> Inspections -> Typoを選択
in All Scopes
を任意で作成したscopeを指定し調整する。(例えば、xmlは除外するなど)
Scopeは別途作成
Sample Source https://github.com/android/views-widgets-samples
戻るアクション https://developer.android.com/guide/navigation/navigation-custom-back?hl=ja