Androidのメモとか

ポキオの日記です。今日も遅延してない。

MacBook Airの調子が悪いのでmacOS Big SurをクリーンインストールしてNode.jsとPythonの環境をanyenvで整える

タイトルがながい。

ポキオ MacBook Air Big Sur anyenv Node.js Python

突然の絶不調

突然MacBook Airの調子が悪くなってしまったので、この際Big Surをクリーンインストールして、開発環境を整えてみます。

Big Surのクリーンインストール

これを参考に起動可能なボリュームを作成し、クリーンインストール

relativelayout.hatenablog.com

無心でHomebrewをインストール

「とりあえず生」みたいなノリ。

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Node.jsとPythonの環境をanyenvで整える

今回はめんどくさいのでanyenvで環境を整えます。まずはインストール。

brew install anyenv

そして初期化。

anyenv init

で、なぜか怒られる。

# Load anyenv automatically by adding
# the following to ~/.zshrc:

eval "$(anyenv init -)"

言われたとおりに.zshrceval "$(anyenv init -)"を追加して、反映。

source .zshrc

そして再度初期化。

anyenv init

また怒られた。DV彼氏みたい。

ANYENV_DEFINITION_ROOT(/Users/pokiiio/.config/anyenv/anyenv-install) doesn't exist. You can initialize it by:
> anyenv install --init

言われたとおりに初期化。

anyenv install --init

これで良いはず。

anyenv + nodenvでNode.js環境を整える

nodenvのインストール。

anyenv install nodenv
zsh -l

で、nodenvでLTSなNode.jsをインストール。

nodenv install -l
nodenv install 14.18.0
nodenv global 14.18.0
zsh -l

バージョン確認。

node -v

14.18.0が入ってるっぽいのでヨシッ。

v14.18.0

Python

pyenvもインストール。

anyenv install pyenv
zsh -l

新しめのやつをインストール。

pyenv install -l
pyenv install 3.10.0
pyenv global 3.10.0
zsh -l

念の為バージョン確認。

python3 --version

うん、大丈夫そう。

Python 3.10.0

ちなみに、pythonpipPython 3.x系になっちゃうんですね。ちょっと事故りそうで心配ですが、まぁいいです。Python 2.x系を叩きたければpython2を使えということですね。

pokiiio@pokiiio-MacBook-Air ~ % which python
/Users/pokiiio/.anyenv/envs/pyenv/shims/python
pokiiio@pokiiio-MacBook-Air ~ % which python3
/Users/pokiiio/.anyenv/envs/pyenv/shims/python3
pokiiio@pokiiio-MacBook-Air ~ % python --version
Python 3.10.0
pokiiio@pokiiio-MacBook-Air ~ % python3 --version
Python 3.10.0
pokiiio@pokiiio-MacBook-Air ~ % which pip
/Users/pokiiio/.anyenv/envs/pyenv/shims/pip
pokiiio@pokiiio-MacBook-Air ~ % which pip3
/Users/pokiiio/.anyenv/envs/pyenv/shims/pip3
pokiiio@pokiiio-MacBook-Air ~ % pip --version
pip 21.2.3 from /Users/pokiiio/.anyenv/envs/pyenv/versions/3.10.0/lib/python3.10/site-packages/pip (python 3.10)
pokiiio@pokiiio-MacBook-Air ~ % pip3 --version
pip 21.2.3 from /Users/pokiiio/.anyenv/envs/pyenv/versions/3.10.0/lib/python3.10/site-packages/pip (python 3.10)

ふーん。

pokiiio@pokiiio-MacBook-Air ~ % python2 

WARNING: Python 2.7 is not recommended. 
This version is included in macOS for compatibility with legacy software. 
Future versions of macOS will not include Python 2.7. 
Instead, it is recommended that you transition to using 'python3' from within Terminal.

Arduion関係のセットアップ

こちらを参考に。

relativelayout.hatenablog.com

台風に備えて気圧計を作る

台風がちょっと楽しくなる?

ポキオ 台風 気圧計 M5StickC BMP280

そうだ、気圧計を作ろう。

今年も台風シーズンがやってきましたね。台風が好きな人はそう多くはないと思いますし、身の安全や食料の確保などいろいろやらなければならないことは多いですよね。でもエンジニアなら、気圧計も作って設置しておきましょう。

ポキオ 台風 気圧計 M5StickC BMP280

材料はこちら。まずM5StickC。

コンパクトでディスプレイがついているマイコンで、今回はディスプレイに気圧を表示させつつ、クラウドにデータを飛ばすような実装をしてみようと思います。

そして、気圧センサーはBMP280を使います。

気圧センサーといえばおなじみのモジュールになります。モジュールのVCC、GND、SCL、SDAをそれぞれM5StickCの3.3V、GND、26、0のピンに接続しておきます。

コーディングはArduino IDE

M5StickCなのでUI FLOWでもコーディングできると思いますが、既存の豊富なライブラリを使うためにArduino IDEでコーディングしていきます。また、今回はデータをAmbientに飛ばして可視化してみようと思います。(いつもお世話になってます!)

#include <Ambient.h>
#include <Adafruit_BMP280.h>
#include <Wire.h>
#include <M5StickC.h>

#define INTERVAL 5*60*1000
#define MY_SSID "xxxxx"
#define MY_PW "xxxxx"
#define ID xxxxx
#define KEY "xxxxx"

Adafruit_BMP280 bme;
WiFiClient client;
Ambient ambient;

void setup() {
  M5.begin();
  M5.Lcd.setRotation(3);

  WiFi.begin(MY_SSID, MY_PW);
  M5.Lcd.print("Connecting");
  while (WiFi.status() != WL_CONNECTED) {
    M5.Lcd.print(".");
  }

  Wire.begin(0, 26);
  while (!bme.begin(0x76)) {
    M5.Lcd.println("BMP280 init fail");
  }

  ambient.begin(ID, KEY, &client);
}

void loop() {
  M5.Lcd.fillScreen(BLACK);
  float pressure = bme.readPressure();

  M5.Lcd.setCursor(0, 0);
  M5.Lcd.setTextFont(4);
  M5.Lcd.setTextSize(1);
  M5.Lcd.print("pressure[hPa]");

  M5.Lcd.setCursor(0, 26);
  M5.Lcd.setTextFont(7);
  M5.Lcd.setTextSize(1);
  M5.Lcd.printf("%4.0fhPa", pressure / 100);

  ambient.set(1, pressure / 100);
  ambient.send();

  delay(INTERVAL);
}

M5StickCはArduino IDE向けにもライブラリがあり、面倒なWi−Fi接続やディスプレイ操作が簡単にできるのでサクッとコーディングできますね。

いざ起動

こんな感じで自宅の2階の壁に貼って観察を監視します。

ポキオ 台風 気圧計 M5StickC BMP280

台風が来る前に気圧計を設置しましたが、1012hPa前後からスタートし台風接近とともにみるみる気圧が低下。

ポキオ 台風 気圧計 M5StickC BMP280

ついに994hPA前後まで到達。

ポキオ 台風 気圧計 M5StickC BMP280

今回は台風がそこまで接近しなかったこともあり994hPa止まりでしたが、2年前の台風のときは968hPaまで低下しました。

relativelayout.hatenablog.com

relativelayout.hatenablog.com

台風は恐ろしいものではありますが、こんな感じで自然現象をデータで可視化できると、ちょっと台風が楽しくなる?…なりませんね(笑)

Arduinoと3Dプリンタで4灯式信号機を作る

父は減速現示が好き。

ポキオ Arduino NeoPixel 4灯式信号機

4歳息子「信号機がほしい」

息子が日本信号の鉄道用信号機のガチャガチャを見てから、信号機がほしいと言って聞かないわけです。

まぁ、無いなら作ればいい。ということで、今回は4灯式信号機を作ってみます。

www.tomytec.co.jp

イメージはこんな感じ。進行、減速、注意、停止の現示が可能な信号機を作ります。

3Dプリンタでそれっぽい信号をつくる

なにはともあれ、信号っぽいガワを作っていきます。

ポキオ Arduino NeoPixel 4灯式信号機

Fusion 360で、信号機本体にひさしをくっつけて、それっぽくしていきます。今回は、めんどくさいので信号機の裏側や支柱などは作らないでおきます。

光源はNeoPixel

今回使用する光源はNeoPixelのLEDテープを使います。

ポキオ Arduino NeoPixel 4灯式信号機

普通のLEDを使ってもいいんですが、抵抗を挟んだりするのが面倒なのと、配線も複雑になるので、今回はこのNeoPixel系のLEDテープを使います。これだと、GND、電源、信号線の3つだけ繋げば動作させる事ができます。

全部合体させるよー

こんな感じです。

ポキオ Arduino NeoPixel 4灯式信号機

LEDテープはLED4つ分のところでハサミで切って使用しています。GND・電源・信号の線をArduinoのピンに接続していきますが、信号の線は5Vピンに近いA0ピンにさしています。

NeoPixelの特徴でもあるんですが、色をRGBで指定するため、赤は良いとしても、黄色と青(緑)色は現物を見ながら調整しています。

// 黄色
255, 128, 0

// 青色
64, 255, 0

一旦は上記のようなRGB値にしています。

光らせた様子はこちら

光を拡散させたかったので、透明のフィラメントでレンズを作り、LED部分を覆っています。

ポキオ Arduino NeoPixel 4灯式信号機

いい感じいい感じ。

ポキオ Arduino NeoPixel 4灯式信号機

信号機を綿棒の箱に輪ゴムでくっつけて、早速息子氏に遊ばせてみました。2.5秒ごとに信号が節操なく変わるようにプログラミングしてしまったので、若干ビジーかなと思ったんですが、息子的には代わる代わる信号が変わって面白そうな様子でした。

4歳息子「中継信号機と踏切がほしい」

ひとしきり遊んだあとに、息子氏が「中継信号機と踏切も」と言い出したので、おいおいそちらも着手しようと思います(笑)

コードはこちら

#include <Adafruit_NeoPixel.h>

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(4, A0, NEO_GRB + NEO_KHZ800);

void setup() {
  pixels.begin();
}

void loop() {
  for(int i = 0; i < 4; i++){
    switchSignal(i);
    delay(2500);
  }
}

// 0:停止 1:注意 2:減速 3:進行
void switchSignal(int i){
  long light1[4] = {pixels.Color(0, 0, 0),pixels.Color(0, 0, 0),pixels.Color(255, 128, 0),pixels.Color(0, 0, 0)};
  long light2[4] = {pixels.Color(255, 0, 0),pixels.Color(0, 0, 0),pixels.Color(0, 0, 0),pixels.Color(0, 0, 0)};
  long light3[4] = {pixels.Color(0, 0, 0),pixels.Color(255, 128, 0),pixels.Color(0, 0, 0),pixels.Color(0, 0, 0)};
  long light4[4] = {pixels.Color(0, 0, 0),pixels.Color(0, 0, 0),pixels.Color(64, 255, 0),pixels.Color(64, 255, 0)};

  pixels.setPixelColor(0, light4[i]);
  pixels.setPixelColor(1, light3[i]);
  pixels.setPixelColor(2, light2[i]);
  pixels.setPixelColor(3, light1[i]);
  pixels.show();
}

Sonos Roamことはじめ

ろーーーむ!

ポキオ Sonos Roam

Sonos Roamとは

オーディオメーカーSonosから発売されたポータブルスピーカーというやつです。

www.sonos.com

以前参加したSonosのイベントを発端に、だんだんSonosにハマってきてしまったわけですね。はい。

relativelayout.hatenablog.com

今回のRoamは最近日本で発売されたばかりなんですが…。

www.bcnretail.com

ヨドバシさんで先行販売らしく…。

ポキオ Sonos Roam

ほう…、オンラインストアでも買えるのね…。

ポキオ Sonos Roam

で、気づいたら自宅にあった、というわけです。

ひとまずUnboxing

箱に布製の「とって」みたいなものが付いてるんですよね。

ポキオ Sonos Roam

波平さんみたいで可愛いですよね(そこじゃない)。

ポキオ Sonos Roam

箱の中はこんな感じ。毎度おなじみの不織布で包まれています。

ポキオ Sonos Roam

不織布の中には、この色白の子。

ポキオ Sonos Roam

裏側にはType-Cの充電ポートと、電源ボタンっぽいやつ。

ポキオ Sonos Roam

操作系はすべてスピーカーの上側(?)にまとまっています。ボタン類は他のSonos製品と同じような感じで、UXも同じような感じなので、マニュアルを読まずに使い始められるのがいいですね。

ポータブルスピーカーを家の中で?

Roamはポータブルスピーカーであって、Wi−FiだけでなくBTにも対応しているのが特異的な部分であることは承知をしていますが、ひとまず家の中で使ってみます。あくまでもSonosのスピーカーであることには変わりないので、Wi−Fi接続をして他のSonosスピーカーと連携することもできるのがすごいところです。

ポキオ Sonos Roam

こちらは弊家のリビングの間取りと、既存のSonosスピーカーたち。普段は3つのOneを連携させて音楽を聞いています。(訳あって、PlaybarはTVと接続し、独立して使っています)

ポキオ Sonos Roam

まずはWFH中の音楽鑑賞。手元にRoamを置いて、3つのOneとRoamを連携させて音楽を聞いてみました。

ポキオ Sonos Roam

もともとWFHしている場所が部屋の端によっているため、最適なリスニングポジションではなかったものの、手元にRoamを置いたことで、

  • Roamのおかげで音楽、とくにボーカルの解像度が上がったような感じ
  • Oneが3つあることによる包まれてる感じ

上の2つがうまい塩梅で両立しているような環境となりました。また、コンパクトなRoamのおかげで、机の上に置いても邪魔にならない感じが非常に良いです。

ポキオ Sonos Roam

次に同様にOne 3つと連携させたまま、Roamをキッチンに持っていってみます。というのも、間取りの関係で、リビングの3つのOneの音楽がキッチンでは聞きづらいと常々感じていたものの、キッチンのためだけにOneを増設するのも微妙かなと思っていたわけです。

ポキオ Sonos Roam

Roamはバッテリー内蔵で、先述の通りコンパクト。しかも縦置きもできるので、我が家の狭いキッチンでも置き場に困りません。そして、コンパクトなのにパワフルな音を出せるので、意外と音がうるさい料理中もしっかり音楽に没頭(料理も頑張ってますが)できました。リビングに行っても、キッチンに戻っても、シームレスに音楽が聞ける体験は、本当に素晴らしいですねぇ。そして、必要なときだけ持っていけるのは、ポータブルスピーカーならではのメリットですね。

というわけで

  • My New Gear : Sonos Roam
  • ポータブルスピーカーだけど、まだ家の中でしか使ってないよ
  • でも、家の中でも機動性を活かして、いろいろ使えるすごいやつ
  • 既存のSonosシステムと連携ができる
  • コンパクトだけどいい音

サマるとこんな感じでしょうか。屋外でのレビューはまた今度!

娘の夏休みの宿題のデイリー進捗を可視化してみた

見える化

ポキオ Arduino Todo カンバン Adafruit Neopixel

意外と多いタスク

小1の娘は初めての長い夏休みを堪能しつつ、初めての夏休みの宿題をこなしています。意外と学校の宿題も多く大変そうだなぁと思いつつ、親がいちいち「あれやった?」みたいなポーリングによる進捗確認は工数だけがかかる作業なのであまりしたくありません。

そこで、デイリーでこなすべき宿題の進捗を可視化できるガジェットを作ってみました。

Arduinoで作っていきます

イメージとしては光り物で、タスクが一覧できる物理的なカンバンを作って、タスクごとに光らせるんですが、タスクが終わったらボタンを押して光っている色を変える感じ。

ポキオ Arduino Todo カンバン Adafruit Neopixel

とりあえず家に転がってたArduino Mega互換ボードに、NeopixelのLEDとスイッチを接続。スイッチはプルアップとして使うので、スイッチはGPIOとGNDにつなげます。Neopixelは信号線を1つでも良かったのですが、無心で作ってたので、複数信号線を作ってしまいました…(笑)

ポキオ Arduino Todo カンバン Adafruit Neopixel

さらに、3DプリンタでLEDを覆うようなパーツを作って・・・。

ポキオ Arduino Todo カンバン Adafruit Neopixel

これらをすべてOSBボードに打ち付けて、できました。

動作の様子はこちら

起動直後はすべてのタスクが赤く光ります。

ポキオ Arduino Todo カンバン Adafruit Neopixel

タスクを終えて、ボタンを押すと赤→青になります。

ポキオ Arduino Todo カンバン Adafruit Neopixel

全部のタスクが終わると、白色点滅。

全クリ時に、おめでとう感を出していくスタイルです。

導入してみてどうだった?

普段はWFHな私ですが、仕事中も娘の進捗が見えて非常によかったです。また、娘も達成感を味わえるようで、進んでArduinoの電源を入れて宿題に取り組んでました。

とりあえず、大成功?

コードはこんな感じ

#define使えよ…(笑)

#include <Adafruit_NeoPixel.h>

int b1 = 0;
int b2 = 15;
int b3 = 17;
int b4 = 19;
int b5 = 21;

int l1 = 12;
int l2 = 10;
int l3 = 5;
int l4 = 8;
int l5 = 7;

Adafruit_NeoPixel pixels1 = Adafruit_NeoPixel(2, l1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixels2 = Adafruit_NeoPixel(2, l2, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixels3 = Adafruit_NeoPixel(2, l3, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixels4 = Adafruit_NeoPixel(2, l4, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixels5 = Adafruit_NeoPixel(2, l5, NEO_GRB + NEO_KHZ800);

bool stat1 = false;
bool stat2 = false;
bool stat3 = false;
bool stat4 = false;
bool stat5 = false;

void setup() {
  Serial.begin(9600);

  pinMode(b1, INPUT_PULLUP);
  pinMode(b2, INPUT_PULLUP);
  pinMode(b3, INPUT_PULLUP);
  pinMode(b4, INPUT_PULLUP);
  pinMode(b5, INPUT_PULLUP);

  pixels1.begin();
  pixels2.begin();
  pixels3.begin();
  pixels4.begin();
  pixels5.begin();

  pixels1.setBrightness(64);
  pixels2.setBrightness(64);
  pixels3.setBrightness(64);
  pixels4.setBrightness(64);
  pixels5.setBrightness(64);
}

void loop() {
  stat1 = stat1 || (digitalRead(b1) == LOW);
  stat2 = stat2 || (digitalRead(b2) == LOW);
  stat3 = stat3 || (digitalRead(b3) == LOW);
  stat4 = stat4 || (digitalRead(b4) == LOW);
  stat5 = stat5 || (digitalRead(b5) == LOW);

  if (stat1) {
    pixels1.setPixelColor(0, pixels1.Color(0, 0, 255));
    pixels1.setPixelColor(1, pixels1.Color(0, 0, 255));
  } else {
    pixels1.setPixelColor(0, pixels1.Color(255, 0, 0));
    pixels1.setPixelColor(1, pixels1.Color(255, 0, 0));
  }

  if (stat2) {
    pixels2.setPixelColor(0, pixels1.Color(0, 0, 255));
    pixels2.setPixelColor(1, pixels1.Color(0, 0, 255));
  } else {
    pixels2.setPixelColor(0, pixels1.Color(255, 0, 0));
    pixels2.setPixelColor(1, pixels1.Color(255, 0, 0));
  }

  if (stat3) {
    pixels3.setPixelColor(0, pixels1.Color(0, 0, 255));
    pixels3.setPixelColor(1, pixels1.Color(0, 0, 255));
  } else {
    pixels3.setPixelColor(0, pixels1.Color(255, 0, 0));
    pixels3.setPixelColor(1, pixels1.Color(255, 0, 0));
  }

  if (stat4) {
    pixels4.setPixelColor(0, pixels1.Color(0, 0, 255));
    pixels4.setPixelColor(1, pixels1.Color(0, 0, 255));
  } else {
    pixels4.setPixelColor(0, pixels1.Color(255, 0, 0));
    pixels4.setPixelColor(1, pixels1.Color(255, 0, 0));
  }

  if (stat5) {
    pixels5.setPixelColor(0, pixels1.Color(0, 0, 255));
    pixels5.setPixelColor(1, pixels1.Color(0, 0, 255));
  } else {
    pixels5.setPixelColor(0, pixels1.Color(255, 0, 0));
    pixels5.setPixelColor(1, pixels1.Color(255, 0, 0));
  }

  pixels1.show();
  pixels2.show();
  pixels3.show();
  pixels4.show();
  pixels5.show();

  if (stat1 && stat2 && stat3 && stat4 && stat5) {
    congrats();
  }
}

void congrats() {
  for (int i = 0; i < 100; i++) {
    setColor(255, 255, 255);
    delay(500);
    setColor(0, 0, 0);
    delay(500);
  }

  setColor(255, 255, 255);
  while (1) {}
}

void setColor(int r, int g, int b) {
  pixels1.setPixelColor(0, pixels1.Color(r, g, b));
  pixels1.setPixelColor(1, pixels1.Color(r, g, b));
  pixels2.setPixelColor(0, pixels1.Color(r, g, b));
  pixels2.setPixelColor(1, pixels1.Color(r, g, b));
  pixels3.setPixelColor(0, pixels1.Color(r, g, b));
  pixels3.setPixelColor(1, pixels1.Color(r, g, b));
  pixels4.setPixelColor(0, pixels1.Color(r, g, b));
  pixels4.setPixelColor(1, pixels1.Color(r, g, b));
  pixels5.setPixelColor(0, pixels1.Color(r, g, b));
  pixels5.setPixelColor(1, pixels1.Color(r, g, b));

  pixels1.show();
  pixels2.show();
  pixels3.show();
  pixels4.show();
  pixels5.show();
}

Android 12でBluetoothは位置情報権限の呪縛から解かれる

久々にAndroidの話。

ポキオ Android 12 BLUETOOTH_SCAN BLUETOOTH_CONNECT permission

tl:dr

  • いままではBluetoothの利用には位置情報の権限が必要でした
  • Android 12からBluetooth専用の権限が新設され、位置情報の権限は不要になります

developer.android.com

忌まわしき位置情報の権限

Androidの話なので、iOSユーザーの方はポカーンって感じかもしれないですが。

ポキオ Android 12 BLUETOOTH_SCAN BLUETOOTH_CONNECT permission

Androidはユーザーのプライバシーを守るために、Android 6からRuntime Permissionsを実装し、アプリがスマホの一部のリソースを使う前に、アプリがユーザーに対して権限の付与を尋ねるという機能が入りました。

たとえば、地図アプリや、アプリでどこかのスポットにチェックインしたりするときなど、アプリがスマホの位置情報をアクセスする際は、予めユーザーに対して位置情報へのアクセスを許可してもらう必要があり、許可がおりて初めて位置情報にアクセスできるようになります。

ただし、ここでポイントなのは、Bluetooth(BLE)やWi−Fiのスキャンをする際も位置情報アクセスの権限取得が何故か必要ということです。Android側のロジックとしては、BLEビーコンやWi−Fiのアクセスポイントのスキャン結果とそれぞれの電波強度から位置情報が推測できるため、そのような制約を設けていると思われるのですが、アプリを使っているユーザーからは、そんな内部の都合なんて理解できるはずがありません。

結果として、アプリとしては位置情報がほしいわけでもないのにBLEやWi− Fiを使う際は、ユーザーに対して位置情報へのアクセス権限を求めざるを得ず、ユーザーにとってみれば、なぜ位置情報へのアクセスを求められているのかがわからず、変に怪しまれるということが多々あったわけです。

ようやくAndroid 12で仕様が変わります

この状況が2021年秋にリリースされるAndroid 12で大きくかわります。

ポキオ Android 12 BLUETOOTH_SCAN BLUETOOTH_CONNECT permission

Android 12では、新たにBluetooth利用のための権限が2つ新設されます。

これにより、今までAndroidManifest.xmlで、

 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

のように宣言していた位置情報アクセスの権限でしたが、BLEのスキャンと接続をするだけであれば、上記の権限は不要で、

<uses-permission android:name="android.permission.BLUETOOTH_SCAN"
                 android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

というように、専用の権限利用の宣言だけをすれば良くなりました。ユーザーの見た目的にもBLE利用の際に求められる権限は、

Allow [an app] to find, connect to, and determine relative position of nearby devices.

のような、わかりやすい理由で権限を求められるようになります。

戦いはこれで終わりなのか?

というわけで、新しいOSでは、BLE利用と位置情報利用のための権限が分かれたことで、ユーザーフレンドリーな仕様に一歩近づいたわけです。

ポキオ Android 12 BLUETOOTH_SCAN BLUETOOTH_CONNECT permission

ただし、これはあくまでもAndroid 12のデバイスで動作するアプリの話であって、依然として大多数を占めるAndroid 11以下のデバイスでは関係ない話です。

なので、アプリデベロッパーとしてはぬか喜びすることなく、当面の間はAndroid 12で増えた権限のハンドリングをしつつ、Android 11以下のデバイスを考慮した設計が必要になりそうです。悲しいかな、デベロッパーの諸兄姉は目をつぶっていてもif文を無限にコーディングできるスキルを持っているはずなので、容易い話かと思いますが。

一方でユーザーも、急にアプリが位置情報の権限を要求してきても焦らずに、許可・不許可をする必要があります。もしかしたら、Bluetoothを使いたいだけなのに位置情報の権限を要求しているのかもしれません。(まぁ、そういうときは、アプリはその旨をユーザーに伝えるべきですが)位置情報に限らずそのような権限はあとからでも不許可に倒すことも可能なので、脳死で許可・不許可をせずに、冷静に考えて決めてほしいなと願っています。

でも、あんまり不許可にしないでね!もしかしたらバグるかもしれないから!(笑)

Androidアプリ開発 74のアンチパターン

Androidアプリ開発 74のアンチパターン

  • 作者:深見 浩和
  • 発売日: 2017/09/27
  • メディア: 単行本(ソフトカバー)

テレワーク用の椅子(5脚目)

ついに5脚目。

ポキオ カスケード Cascade Mountain Tech Compact High Back Aluminum Chair

テレワーク用の椅子の紆余曲折

いままで色々試してきました。

relativelayout.hatenablog.com

結局、最後に買った「ポンコタン ハイバックチェア」が一番しっくり来ていました。

なんですが、毎日座ってたせいで、ファブリックの縫い目がほつれ始めてきていました。

コストコ怪しいハイバックチェアが・・・

で、コストコでなにやらコスパの良さそうなハイバックチェアが売っていました。

ポキオ カスケード Cascade Mountain Tech Compact High Back Aluminum Chair

すぐにカートに入れちゃう癖やめたいところですが、なんと約3500円。

ポキオ カスケード Cascade Mountain Tech Compact High Back Aluminum Chair

きっと本国のメリケン人が乗っても壊れないんだろうなとか思うと、耐久性も期待できそうだったので早速購入。

Unboxingと組み立て

ポンコタンのハイバックチェアと同じように収納バッグに入ってて、非常にコンパクト。

ポキオ カスケード Cascade Mountain Tech Compact High Back Aluminum Chair

で、ひとまず開封。骨組みを組み立てるところまでは良かったが・・・。

ポキオ カスケード Cascade Mountain Tech Compact High Back Aluminum Chair

ファブリックの座面を骨組みに取り付けるのが本当に大変。未使用でファブリックが伸びてないのか、なかなか骨組みに入らず10分ほど格闘。最後はなんとか入りましたが。

ポキオ カスケード Cascade Mountain Tech Compact High Back Aluminum Chair

ちなみに、足はこんなタイプ。地面が砂地などでも潜り込まないような構造になっていますが、ポンコタンと異なり、この足は取り外しができないようです。

ポキオ カスケード Cascade Mountain Tech Compact High Back Aluminum Chair

で、完成。

座り心地は?

まず、ファーストインプレッションとして、

(ポンコタンのハイバックチェアと比べると…)

  • 背もたれは低めで、ハイバックというかミッドバック。
  • 左右方向のホールド感は低め。
  • 前後方向のホールド感は低めで、浅め。
  • 座面はちょっとだけ高め。
  • 大きめのヘッドレストがついてて快適。
  • 背もたれ上部に、左右方向に伸びる骨が入ってて安定感がある。

僕も割とお尻が大きい方ですが、それでも余裕があるので、ポンコタンより欧米寄りというのがわかります。とまぁ、色々差異はあるものの、なかなかの座り心地。耐久性の評価はこれからですが、すぐに壊れてもコストコなので返品しちゃえばいいしね。そう考えても3500円というのはコスパ高いですね。

ポキオ カスケード Cascade Mountain Tech Compact High Back Aluminum Chair

というわけで、カスケードマウンテンテックのハイバックチェアでした。次こそはHelinox買うん・・・だ・・・!

「Androidのメモとか」は、Amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、Amazonアソシエイト・プログラムの参加者です。

このブログは個人的なメモ書きであったり、考えを書く場所であります。執筆者の所属する団体や企業のコメントや意向とは無関係であります。また、このブログは必ずしも正しいことが書かれているとは限らず、誤字脱字や意図せず誤った情報を載せる場合がありえます。それが原因で読者が不利益を被ったとしても、執筆者はいかなる責任も負いません。ありがとうございます。