20191023のAndroidに関する記事は6件です。

スマホのセンサーとManticoreのクルマのデータを使ったSDLアプリを作ってみた

SDLアプリコンテストって?

SDLアプリコンテスト2019は、SDLの普及を目的としたSDLコンソーシアム日本分科会の協力で実施するもので、今回が2回目の開催となります。
本コンテストでは、四輪と二輪の両方を対象に、SDLに対応するアプリ(Android、iOSアプリ)を広く募集します。年齢、性別、国籍等は不問で、個人・チームどちらでも応募可能です。
SDLアプリコンテスト2019の応募締切は2019年10月31日までですので、リンク先を確認して、急いで応募しよう(来年にも期待!)

SDLとは?

SDLアプリコンテスト2019の「SDLとは」のページを確認しよう!

今回のサンプル「フェード現象の警告」

フェード現象とは?

自動車やオートバイでの走行中に摩擦ブレーキを連続使用した結果、ブレーキの効き(制動力)が低下すること。
Wikipediaより

初心者の時、こんな感じの思い出はないでしょうか?(事故まではないかw)
スクリーンショット 2019-10-23 19.39.31.png

一定の角度以上で下っていたら警告したい

以下の画像をクルマの車載モニターだとしよう。一定の角度で一定時間以上下っている場合、シフトレバー操作をエンジンブレーキがかかるポジションにしているか注意したい
image.png

【今回未実装】警告が出ていたポイントをクラウドに収集

今回は、スマホのセンサーとManticoreのクルマのデータを使ったサンプルの説明に特化したい為、実装は省略しています。
しかし、検出ポイントをクラウドで収集して、他のドライバにシェアすることにより、

・下っている最中ではなく、付近に近づいたら事前に警告したり
・警告が発生するポイントって、案外走り屋としては面白い?

などの使い道が出てくると考えている。

今回のソースと前提の資料

今回のサンプルは、Githubに格納しています。
SDLアプリとAndroidアプリの違いや基本的なサンプルについては、SDLアプリコンテスト広島 SDLハンズオンの資料で確認していただきたい。

サンプルの動作ムービー

リンクの動画をご確認ください。

スマホのセンサーデータを取得するには?

SDLServiceは、android.app.Serviceクラスを継承しています。なので、シンプルにSensorEventListenerをimplementsしてあげるだけです。

SDLService.javaの77行目付近
public class SdlService extends Service implements SensorEventListener {
    private static final String TAG         = "SDL Vehicle";
    public static final String PORT_NAME           = "port";

さらに、Activityの場合は、onCreateに記載しますが、Seviceクラスの場合は、onStartCommandにSensorManagerの定義を記述します。

SDLService.javaの159行目付近
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (null == intent || intent.equals(null) || intent.getData() == null){Log.e("Log", "the intent in onStartCommand is null");}
        Bundle bundle = intent.getExtras();
        if (bundle != null)
        {
            TCP_PORT = bundle.getInt(PORT_NAME);
        }
        sensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
        rotationSensor = sensorManager.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR);
        sensorManager.registerListener(this, rotationSensor,
                SensorManager.SENSOR_DELAY_NORMAL);
        startProxy();

        return START_STICKY_COMPATIBILITY;
        //return START_STICKY;
    }

余談ですが、160行目付近のintentのNullチェックを行っている部分は、MainActivityからパラメータ渡しで情報を受け取っている部分です。
MainActivityで画面に入力されたManticoreのポート番号をSDLSeviceに渡して、Manticoreに接続するために使っています。

SDLService.javaの160行目付近
        if (null == intent || intent.equals(null) || intent.getData() == null){Log.e("Log", "the intent in onStartCommand is null");}
        Bundle bundle = intent.getExtras();
        if (bundle != null)
        {
            TCP_PORT = bundle.getInt(PORT_NAME);
        }

センサーをの値を実際に取得しているのは、SDLService.javaの546行目付近からです。
サンプルなので超適当で、シフトレバーの状態がオートマ車はDRIVEの状態で、超雑ですが、50Hzくらいの周期でセンサーデータが飛んできているので、だいたい10秒くらい20度くらい傾いたら警告を表示するだけのサンプルになっています。

SDLService.javaの546行目付近
    public final void onSensorChanged(SensorEvent event) {
        if(event.sensor.getType() ==  Sensor.TYPE_GAME_ROTATION_VECTOR){
            //シフトがドライブの時だけ
            if(prndl != null) {
                if ("DRIVE".equals(prndl.toString())) {
                    float[] rotMatrix = new float[9];
                    float[] rotVals = new float[3];

                    SensorManager.getRotationMatrixFromVector(rotMatrix, event.values);
                    SensorManager.remapCoordinateSystem(rotMatrix,
                            SensorManager.AXIS_X, SensorManager.AXIS_Y, rotMatrix);

                    SensorManager.getOrientation(rotMatrix, rotVals);
                    float azimuth = (float) Math.toDegrees(rotVals[0]);
                    float pitch = (float) Math.toDegrees(rotVals[1]);
                    float roll = (float) Math.toDegrees(rotVals[2]);

                    if (pitch < -20) {
                        counter++;
                    } else if (pitch > 20) {
                        counter++;
                    } else {
                        counter = 0;
                    }

                    if (counter > 20) {
                        showAlert("マニュアル車なら2~3速のギアで、オートマ車も2レンジか3レンジで速度調整してください");
                        counter = 0;
                    }
                }
            }
        }
    }

Manticoreで警告表示するWindowを出すのは、SDLService.javaの423行目付近のshowAlertメソッドを使っています。
これだけで、警告表示ができるとはすごくシンプル!alert.setDuration(5000);で5秒だけ表示するようにしています。

SDLService.javaの423行目付近
    public void showAlert(String text){
        Alert alert = new Alert();
        alert.setAlertText1(text);
        alert.setDuration(5000);
        sdlManager.sendRPC(alert);
    }

さらに、ManticoreからText to Speechで音声を再生した場合(英語のみ)、以下のコードをコピペして"Test"の部分をしゃべらせたいワードに変更すれば音声での警告も行えます

SDLService.java
sdlManager.sendRPC(new Speak(TTSChunkFactory.createSimpleTTSChunks("TEST")));

Manticoreからクルマのデータ(擬似データ)を取得する

Manticoreからクルマの擬似データをSDLアプリに送信することができます。送信するための画面はManticoreの右側にあるVEHICLE DATAの部分です。
image.png

今回はシフトレバーの値が取りたいので、「Prndl」の項目を選択して、シフトの状態を選択します。

image.png

変更された都度データを受信するプログラムは、SDLService.javaの244行目付近になります。
シフトレバーの状態は、onVehicleDataNotification.getPrndl();で取得できます。
ここで書かれているNotificationListenerは、定期的にデータが送信されるわけではなく、Manticoreで値を変更した都度データが飛んでくると思ってください

SDLService.javaの244行目付近
                    sdlManager.addOnRPCNotificationListener(FunctionID.ON_VEHICLE_DATA, new OnRPCNotificationListener() {
                        @Override
                        public void onNotified(RPCNotification notification) {
                            OnVehicleData onVehicleDataNotification = (OnVehicleData) notification;

                            sdlManager.getScreenManager().beginTransaction();

                            prndl = onVehicleDataNotification.getPrndl();

最後に

今回開発に使った環境については、SDLアプリコンテスト広島 ハンズオン事前資料に記載しています。
まだまだSDLについては、情報が少ないですが、どんどん情報公開してサンプルを充実できるようにがんばっていきます!

今回記事やハンズオンの資料を作りにあたり、田中さんの記事が非常に参考になりました。こちらも合わせて読んでいただければと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Cocos2d-x 3.17.2をiOS, Androidでコンパイルできないんですけど

現在(2019/10/23)の最新版v3.17.2でCocos2d-xで久々にiOSとAndroidでHello worldをコンパイルした。
プロジェクトデフォルトのHello worldのコンパイルをするのにググったり苦労したのでヒントなど。

iOS

xcode 11でコンパイルするとエラーになる。

error : Argument value 10880 is outside the valid range [0, 255] btVector3.h

btVector3.hの

#define BT_SHUFFLE(x,y,z,w) ((w)<<6 | (z)<<4 | (y)<<2 | (x))

#define BT_SHUFFLE(x, y, z, w) (((w) << 6 | (z) << 4 | (y) << 2 | (x)) & 0xff)

に置き換える

https://stackoverflow.com/questions/58064487/xcode-11-cocos2dx-compilation-problem-argument-value-10880-is-outside-the-vali

Android

NDK

NDKは、cocos2d-x 3.17.1時点で16なので、Android NDK 16bを選んだ。

https://discuss.cocos2d-x.org/t/which-ndk-to-use-on-3-17-1/45584
We still used NDK16.

ダウンロードはこちらから
https://developer.android.com/ndk/downloads/older_releases.html?hl=ja

Android Studio

そして、Android Studio 3.5が最新であるがコンパイルができない。

Caused by: org.gradle.internal.UncheckedException: Build command failed.

make: *** No rule to make target `cocos2djs'.  Stop.

Android Studio 3.2を使うとコンパイルできる。
https://teratail.com/questions/178744
のコメント欄より)

ダウンロードはこちらから
https://developer.android.com/studio/archive.html

とりあえずは動かせた。

cmake推奨となっているようでAndroid Studioの最新版でコンパイルしたい場合はビルドツールをndk-buildからcmakeに変更するといいのかもしれない。
https://qiita.com/ugonight_nanase/items/0cab13437dfa2ae003bd

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

「基本からしっかり身につくAndroidアプリ開発入門」やってみた

基本からしっかり身につくAndroidアプリ開発入門

はじめに

 やあ、大学の課題地味に多くて忙しいのであるが、時間が余ってもどうせしょうもないことにしか時間を使わないので、何かをしようと思った私だ。いや誰だ。俺か。

前述した通り暇だからなんかしようと考えたのである。

大学の図書館にある技術書を読み漁りつつ評価とメモをqiitaに書いていく。

ということを思いついて、今回手にしたのは重厚で現代的な表紙の「Androidアプリ開発入門」だ。
すでにRuby on Railsでなんちゃって開発はできるので、アプリ開発もできたら、サービスを展開する時幅が広がるので時間を削って学習するメリットはあると考えた。

内容

    開発環境

  • OS:(俺は)Mac
  • 言語:Kotlin
  • 使用ソフト:Android Studio

chapter1 

Android studioのインストールから開発環境設定まで。

chapter2

Kotlinの書き方基礎


  • 変数と型の宣言

  • 配列、リスト、マップ

  • 条件式(if,when)とレンジ

  • 繰り返し文(while)

  • 関数(デフォルト引数、可変長引数...etc)
  • クラス...etc

chapter3

計算機アプリ(割引計算アプリ)を作る。
AndroidStudioにLabelForがないこと以外は、非常によい掴みになっている。


  • ファイル構造の把握

  • GUIの作り方

  • システムの作り方

  • 画面遷移のやり方

  • 多言語対応、デバックのやり方...etc

chapter4

データの保存とデータベースの使いかた。
SharedPreferences/リストビュー

chapter5

世界時計アプリを作る。

chapter6

アプリの通信とバックグランドでの処理について。
(Thred/Handler/AsyncTask...etc)
リサイクラービュー

chapter7

外部ストレージ

chapter8

デプロイ

つまづいたところ

chapter3 - activity_main.xml

アプリのヘッダーの部分が表示されない。
1.目のマークをクリック
Android_2.png
2.全てにチェックを入れる。

chapter4 - 文字列リソースの定義

view all attributesを開いてもlabelForの欄がない。

chapter5 -リストビュー用ミニアプリ

レイアウトファイルを作る時、Root elementをandroidx.constraintlayout.widget.ConstraintLayoutすることに注意!!

textClockがPaletteを選ぶ場所になかったので
DesignタブからTextタブに切り替えて、下のソースコードを追加。

<TextClock
android:id="@+id/textClock"
android:layout_width="173dp"
android:layout_height="89dp"
android:textSize="64sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.100000024"
tools:text="10:00" />

エラー文を見ると「TextClockが使えるバージョンにしよう」みたいなことを言われるので、v17/activity_main.xmlactivity_main.xml(v17)のファイルの生成を要求されるので従う。
次からはv17/activity_main.xml activity_main.xml(v17)のファイルを編集する。

chapter6-リサイクラー用ミニアプリ

RecyclerViewをDesignタブのAttributeタブで編集できない。
Textタブに切り替えて、
android:id="@+id/timeZoneList"
をタグの中に追加
layout_width,layout_heightも同様。

感想

Kotlin書籍1冊目だから比較ができないが、非常に読みやすいと感じた。
特にクラスや関数、メソッドあたりが自分の中でごちゃごちゃしていたので、こんなかんじで設計したり使ったりするんだなーってのがわかった。
また、スクリーンショットが複数あるので、基本的にストレスなくスムーズに進めながらアプリ開発の基礎を理解することができた気がする。
しかし、メソッドが豊富に使われているので記憶が定着しているうちに読み進めるか、何周かしたほうがいいと考える。

    よかったところ

  • Kotlinの基本文法の解説が詳しい。また、それぞれのコードの例とその結果が文法理解に役立つ。
  • コードの例が豊富
  • 文法解説は簡潔でわかりやすいと感じた(主観)
  • 小物アプリ開発のtutorialが複数用意されている。また、常にスクリーンショットが用意されており開発GUI操作でつまづかない
  • 複数のアプリ開発でフローを理解できる
  • 初心者でもとっつきやすい

    よくなかったところ

  • Android StudioのGUIが書籍のスクリーンショットと少し差異がある。(しょうがない)
  • 書籍が分厚い(しょうがない)
  • なんでかしらんけどlabelForがAttributeにない。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

react-native-sqlite-2@3.0.1 リリースしました

原文: Announcing react-native-sqlite-2@3.0.1! - DEV Community ?‍??‍?

InkdropというアプリをReact Nativeで作っていて、PouchDBを動かすためにWebSQL互換のライブラリが必要だったのでreact-native-sqlite-2を作りました。

なんで?

すでにreact-native-sqlite-storageというSQLiteを扱うためのライブラリが存在しますが、拙作の方には少しアドバンテージがあります:

本ライブラリはこれらの問題を解決します。

What's new in 3.x

Androidにとって大きな改善点があります!

より新しいSQLite3をAndroidで

最新のAndroid OSのバージョンであっても、標準で搭載されているSQLiteのバージョンはいくつか古いものです。
iOSの方が新しいものが使えるのに。
React Native SQLite 2はこのアップデートによってsqlite-androidを使うようになり、SQLiteの新機能が使えるようになりました:

これでiOSでは出来たのにAndroidでは実装できないという悩みが減ります。
自分はFTS5が使いたかった。これはビルドフラグが単純に付いてないだけだったけど。

以降は使い方です。

Getting started

Add react-native-sqlite-2 to your dependencies:

$ npm install react-native-sqlite-2 --save

Link native dependencies

From react-native 0.60 autolinking will take care of the link step but don't forget to run pod install.

$ react-native link react-native-sqlite-2

iOS

If using cocoapods in the ios/ directory run

$ pod install

Android

Please make sure AndroidX is enabled in your project by editting android/gradle.properties and adding 2 lines:

android.useAndroidX=true
android.enableJetifier=true

Usage

import SQLite from "react-native-sqlite-2";

const db = SQLite.openDatabase("test.db", "1.0", "", 1);
db.transaction(function(txn) {
  txn.executeSql("DROP TABLE IF EXISTS Users", []);
  txn.executeSql(
    "CREATE TABLE IF NOT EXISTS Users(user_id INTEGER PRIMARY KEY NOT NULL, name VARCHAR(30))",
    []
  );
  txn.executeSql("INSERT INTO Users (name) VALUES (:name)", ["nora"]);
  txn.executeSql("INSERT INTO Users (name) VALUES (:name)", ["takuya"]);
  txn.executeSql("SELECT * FROM `users`", [], function(tx, res) {
    for (let i = 0; i < res.rows.length; ++i) {
      console.log("item:", res.rows.item(i));
    }
  });
});

There is a test app in the test directory.

Using with PouchDB

It can be used with pouchdb-adapter-react-native-sqlite.

import PouchDB from "pouchdb-react-native";
import SQLite from "react-native-sqlite-2";
import SQLiteAdapterFactory from "pouchdb-adapter-react-native-sqlite";

const SQLiteAdapter = SQLiteAdapterFactory(SQLite);
PouchDB.plugin(SQLiteAdapter);
var db = new PouchDB("mydb", { adapter: "react-native-sqlite" });

Further informations

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

タブレット非対応apkをタブレットにインストールする

スマホで使っているアプリで、「大画面で見たいからタブレットに入れたいな」と思うことがあります。
しかし、タブレットでGooglePlayを開いて検索しても検索結果に出てこず、アプリページのリンクを直接タブレットで開くと「お使いのデバイスはこのバージョンに対応していません。」の表示が。
image.png

ただ、諦めるのはまだ早いです。
OSが対応している場合はインストールできる可能性があるので、その方法を記したいと思います。

仕組み

インストールできるOSは、アプリコードのminSDKVersionで決まります。
なので、対応していないOSの場合はapkのインストール時に弾かれるため、インストールすることはできません。
一方、OSは対応している場合は、制作側がGooglePlayコンソールで対応アプリから除外している可能性があります。

  • タブレット端末で使われる想定をしていないアプリ
  • 対象CPUが限られている場合
  • 検証が十分にできていない場合
  • 特定の機能が入っていない場合(位置情報やマイク・カメラなどなど)
  • 端末固有の不具合が発生する場合

必要な機能が入っていない場合やCPUが対応外、不具合がある場合はインストールできたとしても使えないかもしれませんが、他の理由の場合はインストールして使うことができる可能性があります。

注意

制作側が意図して除外していると考えられるため、なにか不具合が生じても自己責任です。
制作側に問い合わせたり、うまく動かないとレビューするのはやめましょう。
あくまで、個人的にちょっと快適に使えたらなということで、備忘録がてら記事にしています。

インストール手順

3行で言うと

1. apkを探して持ってくる
2. 追加ファイルをコピーする(必要があれば)
3. インストールして追加ファイルを配置する

です。
簡単ですね。

1. apkを探して持ってくる

まずは、スマホにapkをインストールします。
この時、パッケージ名をメモっておきましょう。
GooglePlayのurlから調べることができます。
https://play.google.com/store/apps/details?id=パッケージ名
今回は、example.hoge.fugaとします。

インストールできたら、端末をPCと接続して、adbコマンドを実行し、パッケージ名とapkの保存場所を調べます。

adb shell pm list packages -f example.hoge.fuga

すると、検索結果が出力されます。

package:/data/app/example.hoge.fuga中略==/base.apk=example.hoge.fuga

base.apkというのがapk本体なので、これをPCに持ってきます。

 adb pull /data/app/example.hoge.fuga中略==/base.apk

こうすると、今のディレクトリにbase.apkがコピーされます。
(分かりづらいので名前を変更すると分かりやすいです)

2. 追加ファイルをコピーする(必要があれば)

100MBを超えるアプリの場合、obbという仕組みを利用して、apkとは別に拡張ファイルがスマホに入っています。
Android/obb/パッケージ名
ファイルエクスプローラーやターミナルで見られるので、探してフォルダごとPCにコピーします。

3. インストールして追加ファイルを配置する

ファイルが揃ったのでインストールします。
今回はタブレットに入れるのが目的だったので、タブレットを接続して下記コマンドを実行します。

adb install base.apk

apkのインストールは完了です。

追加ファイルがある場合には、ファイルエクスプローラーやターミナルを使い、先程コピーしてきたobbのフォルダをタブレットの
Android/obb
にコピーすればOKです。

タブレットにアプリが表示されるはずなので、起動して成功すれば完了です。

備考

GooglePlayからの配信形式がapkではなくaabの場合は、スマホにインストールした時点で解像度やCPUに最適化されたリソースだけがインストールされるため、タブレットで動かない可能性があります。

最後に

以上、タブレット非対応apkをタブレットにインストール方法でした。
あまりやる機会はないかもしれませんが、大画面で使いたいアプリが使えるようになるのは便利です。
なにか不具合が起こったとしても自己責任で、制作側にはなんの責任も落ち度もないため、試す場合はそれを理解した上で行っていただければと思います。
また、不具合が起きた場合はすぐアンインストールし、以後使わないようにしましょう。
アプリによっては制作側が不具合のログを取っている場合があり、それに雑音が加わる場合がありますので。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

KotlinのExtensionでNoSuchMethodError

KotlinのExtension機能で詰まったのでメモ。
OS側のクラスを拡張して作ったんですが「そんなメソッドねぇよ!」と怒られるの巻。

環境

Android, Kotlin 1.3.50

背景

android.os.Parcel にBooleanを書くメソッドがないので
Parcel.readBoolean, Parcel.writeBoolean として作った

fun Parcel.writeBoolean(value: Boolean) {
    if (value) {
        this.writeByte(1)
    } else {
        this.writeByte(0)
    }
}

fun Parcel.readBoolean(): Boolean {
    return this.readByte() == 1.toByte()
}

現象

OS ver device result
Android10 Pixel3 問題ない
Android9 Pixel3a Parcelで落ちる
Android7 HUAWEI honor 8 Parcelで落ちる
Android6 Galaxy Grand Prime Parcelで落ちる

エラー

Parcelの拡張関数としてアプリで定義しているのに、なぜかOS側のjarを読み込もうとして落ちている

Fatal Exception: java.lang.NoSuchMethodError: No virtual method writeBoolean(Z)V in class Landroid/os/Parcel; or its super classes (declaration of 'android.os.Parcel' appears in /system/framework/framework.jar!classes2.dex)

対応内容

readCustomBoolean, writeCustomBoolean にRenameした

反省

めちゃ一般的な名前はやめよう、、、

参考

Kotlinの拡張関数のガイドライン
https://dev.classmethod.jp/smartphone/kotlin-extensions-guideline/

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む