「adb shell getprop」で端末情報を見る

ダッシュボード  |  Android Developers

つぶやきを監視しております。いつもありがとうございます。


やってみる。


~ $ adb shell getprop | grep api
[ro.product.first_api_level]: [25]

「SDK」関連を見てみます。


~ $ adb shell getprop | grep sdk
[ro.bootimage.build.version.sdk]: [28]
[ro.build.version.min_supported_target_sdk]: [23]
[ro.build.version.preview_sdk]: [1]
[ro.build.version.preview_sdk_fingerprint]: [9049062ccadb8a692212952393179260]
[ro.build.version.sdk]: [28]
[ro.qc.sdk.audio.fluencetype]: [fluencepro]
[ro.system.build.version.sdk]: [28]
[ro.vendor.build.version.sdk]: [28]

てか、整数のAPIバージョン数が分からないので、コードネームとの対照を調べる。


23 M                      6             Marshmallow
24 N                      7             Nougat
25 N_MR1                  7.1           Nougat
26 O                      8.0           Oreo
27 O_MR1                  8.1           Oreo
28 P                      9.0           Pie

core/java/android/os/Build.java - platform/frameworks/base - Git at Google

または、アプリ内部から吐かす。


Build.VERSION_CODES::class.declaredMembers.forEach { p ->
  p.isAccessible = true
  Log.d("VERSIONS", "${p.call()} -> ${p.name}")
}


D/VERSIONS: 1 -> BASE
D/VERSIONS: 2 -> BASE_1_1
D/VERSIONS: 3 -> CUPCAKE
D/VERSIONS: 10000 -> CUR_DEVELOPMENT
D/VERSIONS: 4 -> DONUT
D/VERSIONS: 5 -> ECLAIR
D/VERSIONS: 6 -> ECLAIR_0_1
D/VERSIONS: 7 -> ECLAIR_MR1
D/VERSIONS: 8 -> FROYO
D/VERSIONS: 9 -> GINGERBREAD
D/VERSIONS: 10 -> GINGERBREAD_MR1
D/VERSIONS: 11 -> HONEYCOMB
D/VERSIONS: 12 -> HONEYCOMB_MR1
D/VERSIONS: 13 -> HONEYCOMB_MR2
D/VERSIONS: 14 -> ICE_CREAM_SANDWICH
D/VERSIONS: 15 -> ICE_CREAM_SANDWICH_MR1
D/VERSIONS: 16 -> JELLY_BEAN
D/VERSIONS: 17 -> JELLY_BEAN_MR1
D/VERSIONS: 18 -> JELLY_BEAN_MR2
D/VERSIONS: 19 -> KITKAT
D/VERSIONS: 20 -> KITKAT_WATCH
D/VERSIONS: 21 -> LOLLIPOP
D/VERSIONS: 22 -> LOLLIPOP_MR1
D/VERSIONS: 23 -> M
D/VERSIONS: 24 -> N
D/VERSIONS: 25 -> N_MR1
D/VERSIONS: 26 -> O
D/VERSIONS: 27 -> O_MR1
D/VERSIONS: 28 -> P
D/VERSIONS: 10000 -> Q

この端末は API 25 の Nougat(MR1) でデビューしています。

今現在 「28-9.0-Pie」ように見えていますが、実際は、「Q-Preview」です。

Android OS バージョンのコードネームを取得する



Android OS バージョンの割合は? 2019-4-30現在

Android OS version market share over time | AppBrain

Mobile & Tablet Android Version Market Share Worldwide | StatCounter Global Stats

Oreo(8.0-0.1) の伸びが止まったまま、Pie(9.0)のみが割合を増やし続けている様子。

なぜ、公式は情報公開しないのだろう。

追記: 2019-05-27

👉【公式 2018-05-07】Android Pie バージョンがやっと 10%超えている件


Kotlin で書きたい「正しいシングルトン(Singleton)」

汎用性のある使えるシングルトン、

どのように書いてますか?


class Singleton private constructor() {

  // getInstance() ???

}

ここから、どんな getInstance() を?

いくつか。


fun getInstance(): Singleton {
  synchronized(this) {
    if(INSTANCE == null){
      INSTANCE = Singleton()
    }
    return INSTANCE!!
  }
}


companion object {
  private var INSTANCE: Singleton ? = null
  fun getInstance(): Singleton {
    if(INSTANCE == null){
      INSTANCE = Singleton()
    }
    return INSTANCE!!
  }
}


companion object {
  val INSTANCE = Singleton()
  fun  getInstance(): Singleton {
    return INSTANCE
  }
}


@Volatile private var INSTANCE: Singleton ? = null
fun getInstance(): Singleton {
  if(INSTANCE == null){
    synchronized(this) {
      INSTANCE = Singleton()
    }
  }
  return INSTANCE!!
}


companion object {
  @Volatile private var INSTANCE: Singleton ? = null
  fun getInstance(): Singleton {
    return INSTANCE?: synchronized(this){
      Singleton().also {
        INSTANCE = it
      }
    }
  }
}

Singleton Pattern — What you might be doing wrong! – Hacker Noon

正解?

Googleの人はこう書いてます。


class CheeseRepository(
  private val api: CheeseApi,
  private val db: CheeseDatabase,
  private val executor: Executor
) {

  companion object {
    private const val PAGE_SIZE = 30

    private var instance: CheeseRepository? = null

    fun getInstance(context: Context) = instance ?: synchronized(this) {
      instance ?: CheeseRepository(
          CheeseApi(),
          Room.databaseBuilder(context, CheeseDatabase::class.java, "cheese").build(),
          Executors.newFixedThreadPool(4)
      ).also { instance = it }
    }
  }

CheesePage/CheeseRepository.kt at master · yaraki/CheesePage

あと、Dagger の @Singleton もこのスタイルに変換されますので安心です。覚えておきたい記述です。

まとめ

なんだか気持ちが悪くても、
なかなか正解が見つけられないこと多くね? 最近。


Paging DataSourceFactory toLiveData() toObservable() が見つからない。

Javaのこのコードが、


public class ConcertViewModel extends ViewModel {
  private ConcertDao concertDao;
  public final Observable<PagedList<Concert>> concertList;

  public ConcertViewModel(ConcertDao concertDao) {
    this.concertDao = concertDao;
    concertList = new RxPagedListBuilder<>(
          concertDao.concertsByDate(), 50)
                  .buildObservable();
  }
}

Kotlinでこう書けるはずなのに!


class ConcertViewModel(concertDao: ConcertDao) : ViewModel() {
  val concertList: Observable<PagedList<Concert>> =
        concertDao.concertsByDate().toObservable(pageSize = 50)
}

Paging library overview  |  Android Developers

見つからない toObservable()。

- Added DataSourceFactory.toLiveData() as a Kotlin alternative for LivePagedListBuilder
- Added DataSourceFactory.toObservable() and toFlowable() as Kotlin alternatives for RxPagedListBuilder

Paging  |  Android Developers

どうやら -ktx のようです。


implementation "androidx.paging:paging-runtime-ktx:2.1.0"
implementation "androidx.paging:paging-rxjava2-ktx:2.1.0"

Maven Repository: androidx.paging

最近は、同じ処理でも複数の書き方があることが多くなって最初混乱したりします。


【MVVM】 ViewModel の_プロパティ記述

Android Java ではあまり見かけなかったその記述。

Kotlin では、たくさん見かけてはいましたが、
個人的な明示記述小技かと思っていました。


private val _items = MutableLiveData<List<Task>>().apply { value = emptyList() }
val items: LiveData<List<Task>>
    get() = _items


private val _dataLoading = MutableLiveData<Boolean>()
val dataLoading: LiveData<Boolean>
    get() = _dataLoading

android-architecture/TasksViewModel.kt at todo-mvvm-live-kotlin · googlesamples/android-architecture


private val _repositories = MutableLiveData<List<Repo>>()
val repositories : LiveData<List<Repo>>
    get() = _repositories

android - Kotlin: Read Only access of Immutable Type to an Internal Variable of a Mutable Type - Stack Overflow


private val _models = ConflatedBroadcastChannel<Model>()
override val models: ReceiveChannel<Model> get() = _models.openSubscription()

private val _events = Channel<Event>(RENDEZVOUS)
override val events: SendChannel<Event> get() = _events

SdkSearch/SearchPresenter.kt at JakeWharton/SdkSearch

Kotlin公式リファレンスにも書かれていたのですね!

Names for backing properties
If a class has two properties which are conceptually the same but one is part of a public API and another is an implementation detail, use an underscore as the prefix for the name of the private property:


class C {
  private val _elementList = mutableListOf<Element>()
  val elementList: List<Element>
      get() = _elementList
}

Properties and Fields: Getters, Setters, const, lateinit - Kotlin Programming Language

クラス内の処理実装に利用するのが _elementList で、
外部にただ公開するだけのが elementList。

こうやって並べてみると、自然に馴染じめてしまう不思議。

ViewModel作成時のイメージとして持っておくと良い。

👉【Kotlin】バッキング・フィールド/プロパティ
👉【MVVM】ViewModel インスタンスの取得