「Android」カテゴリーアーカイブ

【ANDROID】【実質北海道一周】残りの表示部分を実装する。【完成】

前回までの状況はこちら。

最新ソースはこちら

https://github.com/takishita2nd/AroundHokkaido

残りの、数字を表示する部分を作成していきます。

完成までもう少しです。

必要なデータは、

全体の距離(km)と現在位置(km)

区間の距離(km)と現在位置(km)

パーセンテージは上の数字があれば計算で出せます。

全体の距離はjsonを読み込んだときに計算して保持っておくのが良いでしょう。

全体の距離はすでに覚醒済み。

区間のデータはgetPosition()で取得させるのが良いでしょう。

class StartEndPosition(startCity: String, endCity: String, position: Double, segment: Double) {
val startCityName : String = startCity
val endCityName : String = endCity
val positionDistance: Double = position
val segmentDistance: Double = segment
}
    fun getPosition() : StartEndPosition {
var tempDistance = 0.0
var start : String = ""
var end : String = ""
var loop : Boolean = false
var segment: Double = 0.0
var aaa: Double = 0.0
run {
citylist.cityList.forEach{
if(loop){
end = it.city
return@run
}else{
tempDistance += it.distance
if(resultDistance < tempDistance){
start = it.city
aaa = resultDistance - (tempDistance - it.distance)
segment = it.distance
loop = true
}
}
}
}
return StartEndPosition(start, end, aaa, segment)
}
}
distanceFromStart.text = distancefromSapporoFormat.format(aroundHokkaido.getResultDistance(),
aroundHokkaido.getResultDistance() / aroundHokkaido.getTotalDistance() * 100)
distanceSection.text = distanceFormat.format(startEnd.positionDistance,
startEnd.positionDistance / startEnd.segmentDistance * 100)

とりあえず完成だけど、ぶっちゃけこのアプリ自体、そんなに面白くないなぁ。

まぁ、一通りどんな感じでコーディングするのか、それを経験するのには良かったのではないでしょうか。

これとは違うけど、別アプリも考えてみようと思います。

【ANDROID】【実質北海道一周】移動距離に応じて表示を変える

前回までの状況はこちら。

簡単ですが、UIは作ったので、実際に移動距離から都市名を表示させる処理を作っていきます。

class StartEnd(startCity: String, endCity: String) {
    val startCityName : String = startCity
    val endCityName : String = endCity
}
class AroundHokkaido {

    fun getCity() : StartEnd {
        var tempDistance = 0.0
        var start : String = ""
        var end : String = ""
        var loop : Boolean = false
        run {
            citylist.cityList.forEach{
                if(loop){
                    end = it.city
                    return@run
                }else{
                    tempDistance += it.distance
                    if(totalDistance < tempDistance){
                        start = it.city
                        loop = true
                    }
                }
            }
        }
        return StartEnd(start, end)
    }

Jsonで作成した都市と距離のデータから、移動距離と都市間距離を比較しながら加算していき、都市間距離合計が移動距離を超えたときにそのときの都市を返します。

forEach()を使っているのですが、forEachは処理じゃなくて関数なので、途中で処理を抜けるには、breakではなくreturnになります。

それをrunというラベルを指定してreturnすることで、run{}を抜けるところまでジャンプできます。

ややこしい。

でも大分Kotlinにも慣れてきた気がする。

class MainActivity : AppCompatActivity() {

    private fun updateCitydistance(startEnd : StartEnd){
        startCity.text = startEnd.startCityName
        endCity.text = startEnd.endCityName
    }

kotlinはUIにアクセスするの楽だからいいね。

GPSって、思った以上にいい加減、というか、誤差が大きくて、動かしていなくても、1mぐらい移動したものと見なされるみたいです。

後々対処しないとだけど、今は、移動するのがめんどくさいので、このままにしておきます。

確認用に、Jsonを修正。

うん、きちんと変わりましたね。

修正しなきゃいけないところはあるけど、とりあえずはこれでいいか。

Cocos2d-xの開発環境を作成してAndroidで動かすまでの話

一応、プロジェクトを作成して、Hello Worldが出るまでやりました。

手順などは、Qiitaにまとめましたが、

https://qiita.com/takishita2nd/items/0b54af9860f54c65fd24

実際はもっと手こずったので、いろいろと愚痴を書きたい。

まず、Python2.7で無ければセットアップからプロジェクト作成まで動かないのだが、

Python3が動いているのは分かっているのにPython3の本体がどこにあるか分からない、という自体に。

そもそもWindowsにインストールした覚えがない。

ググってプログラムの本体を調べるコマンドを探しまして、

where python

って打てば良いんですけど、

これコマンドプロンプロのコマンドね。

最近はPowerShellをよく使うから。

C:\Users\[ユーザー名]\AppData\Local\Microsoft\WindowsApps\python.exe

にありました。

分かるか。

展開したPython2.7を展開し、環境変数のPATHの設定で、上のフォルダの記載がある場所の上にPython2.7のPATHを書かなければならない。

PATHの検索順をPython2.7→Python3に変えるんですね。

めんどくせぇ。

今時Python2.xなんて使うやついないよ。(たぶん)

もう設定元に戻したわ。

プロジェクト作るときだけ変えれば良い。

そして、もう一つ、Cocoa2d-xってWindowsでも動かすことができるんですが、

いわゆるマルチプラットフォームになっていて、C++の共通コードだけ記述すれば、他のOSでも動かすことができる。

しかし、Windowsで動かす場合は

Visual Studio 2017が必要。

2019ではダメらしい。

めんどくさい。

(一応動かしたけど、後でまとめるわ)

でも、動いたので、あとはガリガリC++のコードを書いていけば。

IDE何使えば良いんだ?

【ANDROID】【実質北海道一周】UIの実装

さて、

このUIを作成していきます。

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/startCity"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="36sp"
        app:layout_constraintBottom_toTopOf="@+id/endCity"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.425"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.528" />

    <TextView
        android:id="@+id/endCity"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="36sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.425"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.591" />

    <TextView
        android:id="@+id/textView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="↓"
        android:textSize="36sp"
        app:layout_constraintBottom_toTopOf="@+id/endCity"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.402"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/startCity"
        app:layout_constraintVertical_bias="0.525" />

    <TextView
        android:id="@+id/distanceSection"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="280dp"
        android:textAlignment="center"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toEndOf="@+id/textView3"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/distanceFromStart"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginBottom="364dp"
        android:textAlignment="center"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toEndOf="@+id/textView3" />
</androidx.constraintlayout.widget.ConstraintLayout>

レイアウトとか、細かいところよくわかっていないので、適当です。

もしかしたら、機種によってレイアウトが崩れるとかもあるかも。

次回は実際に表示する処理を作成していきます。

【ANDROID】【実質北海道一周】UIの検討。

さて、そろそろUIにも着手しようと思うのですが、

まずはどういった情報を表示するか、を整理した方がいいのかな、と思います。

ピックアップしてみると、

  • 現在の始点と終点(どの町と、どの町の間を移動しているか)
  • その区間の現在位置(何km中のkmの位置にいる、現在何%なのか)
  • 札幌(スタート地点)からの距離、全体の何%か

これらの情報が必要かな。

あと、表示をもっとシンプルにさせたいので、画面タップで表示を切り替えるとかも良いかもしれない。

北海道地図で位置が分かるのが一番良いけど、難易度が高そうなので、今回は見送ることにする。

まずは、こんな感じで行ってみましょうか。

【ANDROID】【実質北海道一周】距離をファイルに保存する。

前回までの状況はこちら。

最新ソースはこちら(gitHub)

https://github.com/takishita2nd/AroundHokkaido

今回はGPSの情報から取得した移動距離合計をファイルに保存する処理を作成していきます。

クラスを一つ作成し、北海道一周関連の処理はこのクラスの中で処理していきたいと思います。

package com.takilab.aroundhokkaido

import java.io.File

class AroundHokkaido {
    private val filename: String = "distance.txt"
    private val citylist: CityList = CityList()
    private var totalDistance: Double = 0.0
    private val activity: MainActivity = SingletonActivity.GetActivity()

    fun getDistance(): Double{
        val file = File(activity.filesDir, filename)
        if(file.exists()){
            totalDistance = file.readText().toDouble()
        }
        return totalDistance
    }

    fun updateDistance(distance: Double): Double {
        val file = File(activity.filesDir, filename)
        if(file.exists()){
            totalDistance = file.readText().toDouble()
        }
        totalDistance += distance
        file.writeText("%.3f".format(totalDistance))
        return totalDistance
    }
}

まず、Android内でファイルアクセスするためには、MainActivityが必要です。

exists()でファイルの存在の有無を確認し、存在していれば、ファイルに保存済みのデータを読み込みます。

ファイルはテキストで保存されているので、Double型に変換して取得します。

保存するときは、桁数を指定しないと、指数表記でテキスト保存されてDouble型に変換出来ないという問題があるので、桁数を絞っています。

これをMainActivityでUIに表示させます。

    private lateinit var aroundHokkaido: AroundHokkaido

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        SingletonActivity.SetActivity(this);

        aroundHokkaido = AroundHokkaido()
        val distance: Double = aroundHokkaido.getDistance()
        distanceText.text = "%.3f".format(distance)

        requestPermission()

~中略~

                            override fun onResponse(call: Call, response: Response) {
                                var str = response!!.body!!.string()
                                val jsonObject = JSONObject(str)
                                val jsonArray = jsonObject.getJSONArray("Feature")
                                for (i in 0 until jsonArray.length()) {
                                    val jsonData = jsonArray.getJSONObject(i)
                                    val geometry = jsonData.getJSONObject("Geometry")
                                    val distance = geometry.getDouble("Distance")
                                    val totalDistance: Double = aroundHokkaido.updateDistance(distance)
                                    val mainHandler : Handler = Handler(Looper.getMainLooper())
                                    mainHandler.post(Runnable {
                                        distanceText.text = "%.3f".format(totalDistance)
                                    })
                                }
                            }

まず、AroundHokkaido()の中でMainActivityを使用していますので、AroundHokkaidoの初期化はSingletonActivity.SetActivity(this);の後に行わなければなりません。

で、AroundHokkaidoから現在の移動距離を取得しUIに表示します。

これがアプリ立ち上げたときの初期表示値です。

WebAPIのレスポンスを取得したときの処理も同様にします。

【Android】【実質北海道一周】jsonを読み込ませる。

前回までの状況はこちら。

最新ソースはこちら(gitHub)

https://github.com/takishita2nd/AroundHokkaido

さて、前回作成したJsonファイルを、実際にAndroidアプリに読み込ませるのですが、

こちらの記事を参考にさせて頂きました。

https://qiita.com/Bluewind1997/items/c3f8e90e9fb19f47daee

assetsフォルダを作成して、その下にJsonファイルを作成して設置します。

あとはassetManagerを介せば、そのJsonファイルにアクセス出来ます。

ただ、assetManagerが使えるのはMainActivityだけ。

Androidのプログラミングでは、このMainActivityが重要でして、

Androidに関する重要な処理は、このMainActivityが無ければ使用できません。

なので、どこからでもMainActivityを使用できるように、シングルトンにしてしまえば良いのではと思いましたが、

Kotlinにはシングルトン(というか、staticクラス)という概念がないので、

ここだけJavaで書きました。

package com.takilab.aroundhokkaido;

import androidx.appcompat.app.AppCompatActivity;

public class SingletonActivity {
    private static AppCompatActivity _activity;

    public static void SetActivity(AppCompatActivity activity) {
        _activity = activity;
    }

    public static AppCompatActivity GetActivity(){
        return _activity;
    }
}

JavaとKotlinは混在できるんですね。

実際の開発現場では、どのようにMainActivityを扱っているんですかね?

このMainActivityを使ってJsonの読み出し。

package com.takilab.aroundhokkaido

class City(city: String, distance: Double) {
    val city: String = city
    val distance: Double = distance
}
package com.takilab.aroundhokkaido

import org.json.JSONException
import org.json.JSONObject
import java.io.BufferedReader
import java.io.InputStreamReader

class CityList {
    val cityList: ArrayList<City> = ArrayList()

    init{
        val activity: MainActivity = SingletonActivity.GetActivity() as MainActivity
        val assetManager = activity.resources.assets //アセット呼び出し
        val inputStream = assetManager.open("AroundHokkaido.json") //Jsonファイル
        val bufferedReader = BufferedReader(InputStreamReader(inputStream))
        val str: String = bufferedReader.readText() //データ
        try {
            val jsonObject = JSONObject(str)
            val jsonArray = jsonObject.getJSONArray("list")
            for (i in 0 until jsonArray.length()) {
                val jsonData = jsonArray.getJSONObject(i)
                val city: City = City(jsonData.getString("city"), jsonData.getDouble("distance"))
                cityList.add(city)
            }
        } catch (e: JSONException) {
            e.printStackTrace()
        }
    }
}
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        SingletonActivity.SetActivity(this);

        val cityList = CityList()
        for (city in cityList.cityList) {
            Log.d("Check", "${city.city} : ${city.distance}")
        }
2020-08-07 09:02:07.564 6520-6520/com.takilab.aroundhokkaido D/Check: 札幌 : 35.9
2020-08-07 09:02:07.564 6520-6520/com.takilab.aroundhokkaido D/Check: 小樽 : 20.1
2020-08-07 09:02:07.564 6520-6520/com.takilab.aroundhokkaido D/Check: 余市 : 15.9
2020-08-07 09:02:07.564 6520-6520/com.takilab.aroundhokkaido D/Check: 古平 : 6.4
2020-08-07 09:02:07.564 6520-6520/com.takilab.aroundhokkaido D/Check: 積丹 : 49.0
2020-08-07 09:02:07.564 6520-6520/com.takilab.aroundhokkaido D/Check: 神恵内 : 6.3
2020-08-07 09:02:07.564 6520-6520/com.takilab.aroundhokkaido D/Check: 泊 : 17.9
:
:

Pixel4aが発表されたぜ!仕様を確認する!

ようやく来たぜ正式発表。

Googleストアにラインナップされています。

リリース日は8月20日。

お値段、何と、Pixel3aより安いんです。

42900円。

それなのに、メモリ6GB、ストレージ128GB、プロセッサもSnapdragon600番台から700番台にスペックアップしています。

しかし、かなり削られた機能もありまして、

まず、アクティブエッジが無い。

端末をぎゅっと握るとGoogleアシスタントが起動するアレ。

まぁ、オイラもPixel3使っているけど、アクティブエッジはあまり使ってない。

そして、当然ながらMotion Senseも無い。

勿論ワイヤレス充電機能も。

そして、防水機能も無い。

下二つはPixel3aから搭載していないけど、Pixel3からの買い換え、と考えると、保留。

まだうちのPixel3が現役で稼働しているので、これが壊れたら購入候補に入るかもしれない。

ただ、もうストレージの容量がパンパンなのよね。

最近のゲーム容量食いまくりで。

重たいゲームはスマホでプレイするつもりは無い(むしろ今メインはPCゲーム)ので、ミドルレンジのスペックでも十分耐えられると思う。

悩む。

いや、今使っているの壊れたら買おう。

【実質北海道一周】都市と距離データを作成する。

前回までの状況はこちら。

さて、GPSから距離を求めることが出来たので、

今度は実際に使用する都市間距離のデータを作成します。

どこかに便利なデータが公開されていないかなー

って探してみたのですが、

ありませんでした。

公開されているデータが無いので、自分で作りました。

チマチマとGoogle Mapを使って、北海道一周で通る都市と、その都市間の距離を測定しました。

ルート検索を使うと、走行距離が出てくるので、このデータを、とりあえずはExcelに入力。

これをエディターにコピペして、置換を使ってタブスペースを削除。

ちなみに、ルートとしては、札幌をスタートして小樽へ向かい、反時計回りで一周して、石狩から札幌に戻るルートです。

疲れた。

【実質北海道一周】GPSの2点から距離を求める。

実質北海道一周アプリとは?

定期的にスマホのGPSの信号を取得し、その2点間のデータから移動距離を計測して蓄積。

北海道一周を行う場合、総移動距離が、北海道のどの位置に相当するか、というのを表示するアプリ(という物を想定しています。)

GPSデータから距離を求める処理はQiitaにまとめてあります。

https://qiita.com/takishita2nd/items/3f1d7800fe85de2273bd

ハマったのは、パーミッションの記載。

“android”と記載するところを”Android”と書いただけで無効化されてしまいます。

「WebAPIにアクセス出来ねぇ!」ってなって、冷静に確認したら、上記のようなミスをしていました。

今回はJavaではなくて、Kotlinを使用していますが、KotlinはJavaのインターフェースを使用できますし、その逆も可能です。

なんなら、Kotlinで書いたコードをコンパイルしたバイナリファイルをJVMで動かすことができます。

Kotlinの方が便利な所もありまして、Kotlinは限りなくNullポインタアクセスを考慮しなくて良い仕様になっていますし(ただ、独特なコードの書き方はまだ慣れない)

UIにアクセスする際も、コントロールのID名だけで直接アクセスできたりします。

Android、というか、Javaをメインでやっている人は、Kotlinを覚えておいても全く損は無いです。

いや、無駄な知識は無い、持っていれば持っているだけメリットがあります。

だから人生一生勉強

頑張ります。