Concurrency Utilities for Java EE(JSR-236)のシンプルなサンプル試してみる
Java EEで非同期処理を行う方法を調べていました。 やりたいことは、iOSやAndroidのPushメッセージのリクエストを受け付けて、リクエストの内容はデータベースに保存。非同期で、データベースの情報を元に、APNsやGCMにメッセージを送るという処理です。
選択肢としてはこんな感じかなと思います。
方式 | 検討したこと |
---|---|
Concurrency Utilities for Java EE | Concurrencyという名前が付いているだけあって、単なる非同期処理というよりは、並列処理に関するコントロールがいろいろできそうです。 |
Message Driven Bean | キューにメッセージがエンキューされたタイミングで、イベント・ドリブンで処理が動きます。JMSにメッセージがキューイングされるので、メッセージの永続化が可能。メッセージの永続化が可能なら、この方式かなと思います。今回は、Pushメッセージの内容はDBに永続化されていて、処理依頼のメッセージ自体のの永続性は不要だったので、JMSの環境構築の手間も考えて選択肢から外しました。 |
EJB Timer Service | 単純な非同期処理以外にも、cron的なスケジュールベースの処理起動ができるみたいです。今回の要件では、多重度なくて、並行処理はどっちでもいいので、こちらの方式でもいいかも。 |
このエントリではConcurrency Utilities for Java EEを使ってみたいと思います。 Executors.newSingleThreadExecutorを使ってみます。これは、アプリケーション・サーバーなどのコンテナからスレッドを借りてこれますが、スレッドの多重度は1つになります。 生成されたスレッドは、コンテナのコンテキストを持っています。
Executors.newSingleThreadExecutorを使ったサンプルコード
Webサービスでリクエストを受け付ける部分
GETメソッドで処理を受け付けて、後述する非同期処理を起動します。 リクエストごとにRequestIdを採番しています。
package sample; import javax.ws.rs.GET; import javax.ws.rs.Path; @Path("/task") public class TaskService { static int index = 0; @GET @Path("/") public void start() { System.out.println("TaskService.start is called. RequestId is " + index); TaskManager timer = TaskManager.getInstance(); timer.exec(index++); } }
非同期処理を行う部分
Executors.newSingleThreadExecutorを使って、処理を非同期で行います。 シングルトンで実装しています。
非同期処理部分で2秒間待合せ処理をしています。 パラメタで受け取ったリクエストIDと、スレッドを識別するためのスレッドIDをログに出力しています。
package sample; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class TaskManager { static private TaskManager instace = null; private ExecutorService executor = null; private TaskManager() { executor = Executors.newSingleThreadExecutor(); } synchronized static public TaskManager getInstance() { if (instace == null) { instace = new TaskManager(); } return instace; } public void exec(int requestId) { Runnable runnable = new Runnable() { public void run() { System.out.println("RequestId " + requestId + ":ThreadId " + Thread.currentThread().getId() + " is running."); try { Thread.sleep(2000); } catch (InterruptedException e) {} System.out.println("RequestId " + requestId + ":ThreadId " + Thread.currentThread().getId() + " is finished."); } }; executor.execute(runnable); } }
実行時ログ
作ったWebサービスを呼び出して、ログを確認します。 Executors.newSingleThreadExecutorを使っていることで、リクエストが重なった時も1つのスレッドで順次処理されていることがわかります。
# 最初のリクエスト 01:00:46,566 INFO [stdout] (default task-2) TaskService.start is called. RequestId is 0 01:00:46,568 INFO [stdout] (pool-5-thread-1) RequestId 0:ThreadId 138 is running. 01:00:48,570 INFO [stdout] (pool-5-thread-1) RequestId 0:ThreadId 138 is finished. # リクエストを受け付けて、処理が不通に動きました。スレッドIDは138。 01:00:50,164 INFO [stdout] (default task-3) TaskService.start is called. RequestId is 1 01:00:50,164 INFO [stdout] (pool-5-thread-1) RequestId 1:ThreadId 138 is running. 01:00:52,169 INFO [stdout] (pool-5-thread-1) RequestId 1:ThreadId 138 is finished. # ここからリクエストを連続で投げました 01:00:53,444 INFO [stdout] (default task-4) TaskService.start is called. RequestId is 2 01:00:53,444 INFO [stdout] (pool-5-thread-1) RequestId 2:ThreadId 138 is running. 01:00:53,756 INFO [stdout] (default task-5) TaskService.start is called. RequestId is 3 01:00:54,028 INFO [stdout] (default task-6) TaskService.start is called. RequestId is 4 01:00:54,317 INFO [stdout] (default task-7) TaskService.start is called. RequestId is 5 # リクエストは受付られましたが、処理はキューイングされています 01:00:55,447 INFO [stdout] (pool-5-thread-1) RequestId 2:ThreadId 138 is finished. 01:00:55,447 INFO [stdout] (pool-5-thread-1) RequestId 3:ThreadId 138 is running. 01:00:57,448 INFO [stdout] (pool-5-thread-1) RequestId 3:ThreadId 138 is finished. 01:00:57,449 INFO [stdout] (pool-5-thread-1) RequestId 4:ThreadId 138 is running. 01:00:59,451 INFO [stdout] (pool-5-thread-1) RequestId 4:ThreadId 138 is finished. 01:00:59,451 INFO [stdout] (pool-5-thread-1) RequestId 5:ThreadId 138 is running. 01:01:01,452 INFO [stdout] (pool-5-thread-1) RequestId 5:ThreadId 138 is finished. # 同じスレッドIDで順次、処理が実行されていきました
サンプルコード
サンプルコードの全部はGithubで公開しています。
参考ドキュメント
こちらを参考にさせてもらいました。
Cordovaのサンプルをブラウザと、Androidで実行するまで
このエントリーでは、こちらのCorova公式サイトのGetting Startedで紹介されている手順をやってみます。 cordova.apache.org
Cordovaの環境の準備はこちらのエントリで書いています。 begirama.hatenablog.com
それでは行きましょう。
プロジェクトの作成
cordova create
コマンドで、プロジェクトの新規作成が行えます。
$ cordova -v 5.4.1 $ cordova create MyApp Creating a new cordova project.
以下の操作はすべて新しく作られたMyAppディレクトの中で作業を行います。
browserプラットフォームの追加
cordova platform add
コマンドで、プラットフォームを追加します。
ここではGetting Startedの手順通り、browserを追加しています。
$ cordova platform add browser Adding browser project... Running command: /Users/rsogo/.cordova/lib/npm_cache/cordova-browser/4.0.0/package/bin/create /Users/rsogo/work/cordova_sample/MyApp/platforms/browser io.cordova.hellocordova HelloCordova Creating Browser project. Path: platforms/browser Discovered plugin "cordova-plugin-whitelist" in config.xml. Installing to the project Fetching plugin "cordova-plugin-whitelist@1" via npm Installing "cordova-plugin-whitelist" for browser
実行
cordova run
コマンドで、先ほど追加したbrowserプラットフォームを実行します。
ここで、追加していないプラットフォームを指定すると、怒られます。
cordova run browser Running command: /Users/rsogo/work/cordova_sample/MyApp/platforms/browser/cordova/run Static file server running on port 8000 (i.e. http://localhost:8000) CTRL + C to shut down Static file server running @ http://localhost:8000/index.html CTRL + C to shut down
runすると、ブラウザが立ち上がって、Cordovaのマスコット(?)が表示されます。
ここまでがGetting Startedの内容ですが、Cordovaのマルチプラットフォーム感を味わうためにプラットフォームを追加してみましょう。
androidプラットフォームの追加
browserの時と同じようにandroidもplatform add
コマンドで既存のプロジェクトに追加します。
$ cordova platform add android Adding android project... Running command: /Users/rsogo/.cordova/lib/npm_cache/cordova-android/4.1.1/package/bin/create /Users/rsogo/work/cordova_sample/MyApp/platforms/android io.cordova.hellocordova HelloCordova --cli Creating Cordova project for the Android platform: Path: platforms/android Package: io.cordova.hellocordova Name: HelloCordova Activity: MainActivity Android target: android-22 Copying template files... Android project created with cordova-android@4.1.1 Installing "cordova-plugin-whitelist" for android This plugin is only applicable for versions of cordova-android greater than 4.0. If you have a previous platform version, you do *not* need this plugin since the whitelist will be built in.
どんなものが生成されたのか見てみましょう。 MyAppの直下にplatformsというディレクトリがありますね。
$ ls config.xml hooks platforms plugins www platforms/ plugins/
更にplatformsの下には先程追加したbrowserとandroidのディレクトリがあります。
$ ls platforms/ android/ browser/ platforms.json
さらにandroidの中に入って行くと、Androidのよく見るプロジェクト構成になっています。
$ ls platforms/android/ AndroidManifest.xml assets libs res CordovaLib build.gradle platform_www settings.gradle android.json cordova project.properties src
実行
こちらも同じくcordova run
コマンドのオプションにプラットフォーム名を指定して、実行できます。
$ cordova run android Running command: /Users/rsogo/work/cordova_sample/MyApp/platforms/android/cordova/run ANDROID_HOME=/Applications/adt-bundle-mac-x86_64-20140702/sdk JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home WARNING : No target specified, deploying to device 'CB5A26M91X'. Running: /Users/rsogo/work/cordova_sample/MyApp/platforms/android/gradlew cdvBuildDebug -b /Users/rsogo/work/cordova_sample/MyApp/platforms/android/build.gradle -PcdvBuildArch=arm -Dorg.gradle.daemon=true Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
こんな感じ。
いけましたね。
Install Node.js v5 and NPM for Mac
Cordovaの環境構築のためにパッケージマネージャーのNPMを入れます。
インストーラーのダウンロード
こちらからpkgファイルをダウンロードします。Node.js 特にnode.jsでなんか作る予定はないので、最新のv5を使っていきます。
node.jsインストーラーの起動
node.jsの動作確認
動作確認してみましょう。まずはバージョンのチェック。
$ node -v v5.10.1
さらにこちらの記事で作成されているサンプルを動かしてみます。
紹介されていたサンプルコード
var http = require('http'); http.createServer(function (request, response) { response.writeHead(200, {'Content-Type': 'text/plain'}); response.end('Hello World\n'); }).listen(8124); console.log('Server running at http://127.0.0.1:8124/');
http://localhost:8124/
にアクセスしてみます。OKですね。
npmの動作確認
続いて、一緒にインストールされてnpmの確認。 バージョンチェック。
$ npm -v 3.8.3
cordovaをインストールしてみます。
$ sudo npm install -g cordova fetchMetadata → network ▄ ╢██████████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░╟
以上で、cordovaのインストールが完了しました。
sudoしないと、権限エラーで怒られました。
npm ERR! Error: EACCES: permission denied, access '/usr/local/lib/node_modules' npm ERR! at Error (native) npm ERR! { [Error: EACCES: permission denied, access '/usr/local/lib/node_modules'] npm ERR! errno: -13, npm ERR! code: 'EACCES', npm ERR! syscall: 'access', npm ERR! path: '/usr/local/lib/node_modules' } npm ERR! npm ERR! Please try running this command again as root/Administrator.
npmで古いバージョンのインストール
今日時点で、最新のCordovaのバージョンは6.1.1でした。既存の資産がバージョン5でないと動かない箇所があるみたいなので、古いバージョンを指定してインストールします。
$ cordova -v 6.1.1 $ sudo npm install -g cordova@5.4.1 (略) $ cordova -v 5.4.1
OKでした。
Android:Fragmentの画面遷移時にアニメーション
Androidで、Fragmentの画面遷移の時にアニメーションを付けるやりかたを書きます。 FragmentTransaction.setCustomAnimationsを使いました。 FragmentTransaction | Android Developers
進む時のみにアニメーションを付ける場合
setCustomAnimations(int enter, int exit)
- enter: 次に表示されるFragmentのアニメーション
- exit: 今表示されているFragmentのアニメーション
Backボタンなど、戻る時にもアニメーションを付ける場合
setCustomAnimations(int enter, int exit, int popEnter, int popExit)
popEnter、popExitに戻る時のアニメーションを指定します。
- popEnter: 戻る時に次に表示されるFragmentのアニメーション
- popExit: 戻る時に今表示されているFragmentのアニメーション
引数で指定するのは、アニメーションを指定したリソースIDです。 左からスライド・インさせるアニメーションであればこんな感じ。
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:duration="300" android:fromXDelta="-100%" android:toXDelta="0" /> <alpha android:duration="300" android:fromAlpha="0.0" android:toAlpha="1.0" /> </set>
Activityの画面遷移全体に付けるのなら、Themeに指定するのが一番楽です。 詳しくはこちらが参考になりました。 【Android】画面遷移時のアニメーション設定 - Furudateのブログ
参考にさせてもらったサイト
LollipopでFragmentをスライドインするアニメーションの適用 - Qiita
java.lang.RuntimeException: Unknown animator name: translate
が発生した時の対応を書いてありました。同じエラーが発生したのですが、自分の場合は、FragmentTransactionはSupportライブラリを使うことで、回避しました。
EclipseからAndroid Studioへ移行しました
先週末、あるAndroidのプロジェクトをEclipseベースから、Android Studioに移行しました。
新規のプロジェクトや、小さめのプロジェクトはAndroid Studio化は完了していたのですが、一番大きいプロジェクトは社外の開発者の方の慣れもあって、踏み切れていなかったのですが、急遽やる必要があって、慌ててやった感じです。
Android Studioに移行するにあたって、一番大きいのはGradleベースでビルド、リリースをできるようにすることでした。
Gradleでのライブラリの取り込みにでは次の3つを使い分けました。
- リポジトリに登録されているライブラリの参照
- jarファイルで公開されているライブラリの参照 リポジトリに登録されていない、社内のライブラリなど
- ライブラリプロジェクトの参照 ライブラリのソースを編集するようなケース
dependencies { compile fileTree(dir: ‘libs’, include: [‘*.jar’]) compile ‘com.android.support:support-v4:22.+’ // 1の例 compile ‘com.google.code.gson:gson:2.2.4’ compile files(‘libs/StaggLib.jar’) // 2の例 compile project(‘:subproject’) // 3の例 }
1,2は特に問題がないと思いますが、3について、やり方を忘れるので、メモ。
「File -> New -> Import Project」を選択
settings.gradleに参照が追加されるGUIでの操作では対象のプロジェクトは、元プロジェクトにコピーして、インポートされるので注意が必要。必要に応じて、コピーされたファイル群を削除して、File('')のパスをオリジナルのプロジェクトを参照するように修正する。
後は、Jarファイルを直接参照していたいのを、リポジトリから取得するように変更して、コンパイルが通るまで、ライブラリの重複なんかを取り除いていく。
その他、移行中に発生したエラーはこんな感じ。
':app:dexDebug'. https://t.co/8iOBndcqdy.ide.common.process.ProcessException
— ryohei sogo (@rsogo) 2016年2月28日
のエラーは、これで解消した。https://t.co/2VtF1sO4PM
移行とは、直接関係ないけど、ハマったのがAndroid Studioがハングするという問題。
Macで開発していましたが、Applications以下のAndroid Studioを削除したり、別のフォルダに新規にインストールしましたが、解決せず。 結局、こちらの情報を元に、Applications以外の場所もキレイにして、再インストールで解決しました。Applicationsの下だけ消せば、綺麗にアンインストールできるというのが、Macの良いところだと思うんだけど、これだとWindowsと一緒だよー!
@rsogo これでアンインストールすると、Android Studioがハングアップするのは治った。https://t.co/8FaXQOeekE
— ryohei sogo (@rsogo) 2016年2月28日
その他参考にさせていただいた記事。
基本をおさえる!Androidアプリで指定するバージョンについて(compileSdk,buildToolsVersion,....) - Qiita
Android Studioでproguard付きでビルドした時の`Duplicate zip entry`エラーの調査と対応 - Qiita
Android Studio で Build Variants - Qiita
移行そのものではないけど、Gradle化に合わせて、環境差異や、リリース版/テスト版の違いをBuild Typeなんかで切り分けるのも入れた。
WebLogic 12.1.2のCUIインストール
WebLogicをCUIのみで入れる必要があって、いろいろ調べました。
12.1.1はコンソールモードっていうのがあって、CUIだけでインストールできるのですが、12.1.2からはなくなりました。サーバー側のソフトウェアのインストーラーにX Window systemがいるのって、本当にナンセンスだと思います。
クラウド化が進んでいくと、サーバーはどこにあるかわからない状態になって、リモート接続してセットアップしないといけなくて、セキュリティバリバリだと、いろいろポートは開いてないし、Xで接続するだけでも面倒。
しかもWebLogicのインストールは、半年に1回くらいしかやらないから、毎回手順忘れるっていう。
コンソールモードの廃止について
http://www.slideshare.net/OracleMiddleJP/wlstudy-201412unknown-features http://docs.oracle.com/cd/E28613_01/web.1211/b65940/console_mode.htm
OSXでssh経由でXに接続する
ポートフォーワーディングして、ssh経由でXに接続するやりかた。 http://www.cyberciti.biz/faq/apple-osx-mountain-lion-mavericks-install-xquartz-server/
前準備
インストール先のディレクトリの作成
今回は、次の2つを事前に作成しました。
[root@demo02 opt]# chown weblogic:weblogic /opt/oracle/weblogic/ [root@demo02 opt]# chown weblogic:weblogic /opt/oracle/oraInventory/
orainst.locの作成
[weblogic@demo02 ~]$ cat /opt/oracle/oraInventory/oraInst.loc inventory_loc=/opt/oracle/oraInventory/ inst_group=weblogic
WebLogicのインストール
レスポンスファイルの作成
[weblogic@demo02 ~]$ cat media/sinstall.txt
[ENGINE] #DO NOT CHANGE THIS. Response File Version=1.0.0.0.0 [GENERIC] #The oracle home location. This can be an existing Oracle Home or a new Oracle Home ORACLE_HOME=/opt/oracle/weblogic/ #Set this variable value to the Installation Type selected. e.g. Fusion Middleware Infrastructure, Fusion Middleware Infrastructure With Examples. INSTALL_TYPE=WebLogic Server #Provide the My Oracle Support Username. If you wish to ignore Oracle Configuration Manager configuration provide empty string for user name. MYORACLESUPPORT_USERNAME= #Provide the My Oracle Support Password MYORACLESUPPORT_PASSWORD= #Set this to true if you wish to decline the security updates. Setting this to true and providing empty string for My Oracle Support username will ignore the Oracle Configuration Manager configuration DECLINE_SECURITY_UPDATES=true #Set this to true if My Oracle Support Password is specified SECURITY_UPDATES_VIA_MYORACLESUPPORT=false #Provide the Proxy Host PROXY_HOST= #Provide the Proxy Port PROXY_PORT= #Provide the Proxy Username PROXY_USER= #Provide the Proxy Password PROXY_PWD=<SECURE VALUE> #Type String (URL format) Indicates the OCM Repeater URL which should be of the format [scheme[Http/Https]]://[repeater host]:[repeater port] COLLECTOR_SUPPORTHUB_URL=
インストーラーの実行
[weblogic@demo02 media]$ java -jar wls_121200.jar -silent -responseFile /home/weblogic/media/sinstall.txt -invPtrLoc /opt/oracle/oraInventory/oraInst.loc ファイルを抽出しています....... Oracle Universal Installerを起動中です CPU速度が300MHzを超えていることを確認してください. 実際2500.114MHz 問題なし スワップ領域の確認中: 512MBを超えている必要があります. 実際4079612MB 問題なし このプラットフォームに64-bit JVMが必要かどうかを確認中. 実際 64 問題なし(64-bitは不要) 一時領域の確認中: 300MBを超えている必要があります. 実際39149MB 問題なし /tmp/OraInstall2016-02-19_03-54-05PMからOracle Universal Installerの起動を準備中 ログ: /opt/oracle/oraInventory//logs/install2016-02-19_03-54-05PM.log Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. レスポンス・ファイルの読取り中.. 予期した結果: enterprise-4,enterprise-5,enterprise-6,redhat-6,redhat-4,redhat-5,SuSE-10,SuSE-11の1つ 実際の結果: (不明なOSバージョン) チェックが完了しました。このチェックの全体的な結果: 失敗しました <<<< 問題: このOracleソフトウェアは現行のオペレーティング・システム上では認証されていません。 推奨: ソフトウェアを適切なプラットフォームにインストールしていることを確認してください。 警告: チェック: CertifiedVersionsに失敗しました。 予期した結果: 1.7 実際の結果: 1.7.0_71 チェックが完了しました。このチェックの全体的な結果: 問題なし CheckJDKVersionチェック: 成功しました。 データの検証中...... ファイルのコピー中... -----------20%----------40%----------60%----------80%--------100% WebLogic Server 12.1.2.0.0のinstallationが正常に完了しました。
ドメインの作成
ドメインの作成はWLSTを使ってやることができます。
こちらを参考にさせていただきました。 「一歩先に進むためのWLST活用技法 + お悩み相談室」 https://blogs.oracle.com/wlc/entry/wlstudy_20130723_2
WLSTを起動
http://montai-garage.sakura.ne.jp/getthreaddump/
[weblogic@demo02 bin]$ ./wlst.sh WebLogic Scripting Tool(WLST)を初期化しています... WebLogic Server Administration Scripting Shellへようこそ 使用可能なコマンドに関するヘルプを表示するには、help()と入力してください wls:/offline> myHome="/opt/oracle/weblogic" wls:/offline> wlHome=myHome + "/wlserver" wls:/offline> readTemplate(wlHome + "/common/templates/wls/wls.jar") wls:/offline/base_domain>setOption('ServerStartMode', 'prod') wls:/offline/base_domain>cd('/Servers/AdminServer') wls:/offline/base_domain/Server/AdminServer>set('ListenAddress', '0.0.0.0') wls:/offline/base_domain/Server/AdminServer>set('ListenPort', 7001) wls:/offline/base_domain/Server/AdminServer>cd('/Security/base_domain/User/weblogic') wls:/offline/base_domain/Security/base_domain/User/weblogic>cmo.setPassword('パスワード設定してね') wls:/offline/base_domain/Security/base_domain/User/weblogic>writeDomain(myHome + '/user_projects/domains/mydomain') wls:/offline/mydomain/Security/mydomain/User/weblogic>closeTemplate() wls:/offline>exit() WebLogic Scripting Toolを終了しています。
writeDomainで、すっごい時間掛かった。
インストール後の作業
起動WebLogicユーザーの設定
http://www.oracle.com/webfolder/technetwork/jp/obe/fmw/wls/12c/15-BootProp--4471/bootproperties.htm
ユーザーのプロパティの指定。 起動時にパスワードをいれなくていいように。
2016年2月時点でのAndroidの各種情報
2016年2月時点でのAndroidの各種情報をまとめます。
Androidのバージョンシェア
Dashboards | Android Developers
KitKat(4.4)と Lollipop(5.x)で7割を占めています。 Jelly Bean(4.1, 4.2, 4.3)を加えると9割を超えます。 まだMarshmallow(6.0)は少ないけど、新規であればサポートするとして、KitKat以上は必須。日本だとJelly Beanの割合ももう少し高いと想定すると、なかなかサポートしないという訳には行かないかな。
開発ツール
Android Studioを使って開発します。Eclipseベースから、Android Studioに変わって、ツールはすごく進化したと思います。
Android Studio と SDK Tools のダウンロード | Android Developers
今、安定版はv1.5。2.0のベータ版が出ています。2.0ではInstant Runと呼ばれるコードの変更を、実行中に反映できるという機能や、エミュレータの高速化が個人的に目玉。 Android Studio 2.0 Preview | Android Developers Blog
デザイン
新規でAndroidに最適化したアプリをデザインするためには、マテリアルデザインを知っておくべきでしょう。 Introduction - Material design - Google design guidelines
次のStructure、Components、Patterns(特にナビゲーション!)は、設計者、デザイナーとも知っておくべきでしょう。知らないと、Androidでは一般的ではない(標準で機能が用意されていない)ことをやることになるのでUX的にも問題だし、開発のコストも上がります。
Structure - Layout - Google design guidelines
Bottom sheets - Components - Google design guidelines
Navigation - Patterns - Google design guidelines
複数の画面サイズ、複数
Devices and Displays | Android Developers
Supporting Multiple Screens | Android Developers
スマフォとタブレットは別のレイアウトを用意しておく、複数の解像度の画像を用意しておく、ピクセルじゃなくてdpを使おうぜ、みたいな話。
複数画面のデザイン | Android Developers
上の2つの記事のもうちょい詳しい資料。
Permission
Best Practices for App Permissions | Android Developers
Android 6.0 MarshmallowからPermissionの仕組みが変わっています。
端末ID
Best Practices for Unique Identifiers | Android Developers
Instance IDの利用が推奨されています。Instance IDとは何かとか、取得の方法はWhat is Instance ID? | Instance ID | Google Developersを参照。
Instance IDを使いたくない場合は、UUIDを自分で作ってねって書いてる。
便利なチェックリスト
発注側、受注側で合意しておくといいかも。
Core App Quality | Android Developers
Tablet App Quality | Android Developers
その他のNews
日本で唯一のグローバル端末ベンダーといってもいいSonyに、スマートフォン事業からの撤退という噂もあります。 Sony sees 25-fold profit jump by 2018; could exit TVs, phones | Reuters