こんにちは。バイクで走ってる時の走行ログをとるのに中華サイコンを買いました。
↑この記事でも使っているのですが、データ処理をスマホ上で完結させるためにアプリを作ったので色々メモしておきます。
FITファイルとは
Garminのデバイス等で採用されている、スポーツ・フィットネスデバイスの情報共有プロトコル?です。詳しくは以下を見てください。
今回僕が買った中華サイコン↑は、アプリを通してデータをFIT形式で出力できます。ただ、これはバイナリファイルなのでそのまま開いても人間には解読不能です。
そこで、FitCSVToolというありがたいプログラムが公式から配布されています。
詳細は省きますが、javaを使える環境にダウンロードして
java -jar FitCSVTool.jar hogehoge.fit
でhogehoge.csv
が生成されるといった具合です。
使用デバイスによって何が書き出されるかは違うのですが、僕の場合次のようなCSVが生成されました
gist4b2b46ca9137e1d8b5492e01c8ce4795
なんか余計な項目が多くて見づらいですね…………
一応解説を入れます。上の方は無視して、11行目Data,8,record,...
からを見てください
項目 | 解説 | 備考 |
---|---|---|
timestamp | タイムスタンプ。ただし、1989/12/31 00:00:00 UTC からの経過時間である*1 |
1017550364→UNIXtoDate(1017550364+631065600)=2022年03月30日13:52:44(JST) *2 |
position_lat,position_long | 緯度,経度。ただし、単位がsemicircle となっており要変換 |
degrees = semicircles * ( 180 / 231 )*3 |
distance,altitude | 移動距離、高度[m] | 高度はなんかずれが発生してるっぽいけどバイクで走ってるだけだからあまり気にしていない |
speed | 移動速度[m/s] | 単位に注意 |
他は、要らんかなって……
緯度経度ですが、(426478976,1651643904)を例にとると、それぞれ180をかけて2の31乗で割ると(35.7470548153,138.439192772)となります。*4
スマホで使うために
ここからは、なんとなくしかわかってないので、何をしたら動くようになったかをメモしていく感じです。Androidアプリを作っていきます。そのへんの詳細は割愛。
jarをプロジェクトに組み込む
ダウンロードしたFIT SDKの中からFitCSVTool.jar
をプロジェクトに追加します。
こちらを参考に。以上。
アプリに外部ストレージの読み書き権限を与える
- AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.example.fiteditapp"> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" /> ......
tools:ignore="ScopedStorage"
は、AndroidStudioくんが入れろというので入れました。
パーミッションチェックも入れます。
- MainActivity.java
... public class MainActivity extends AppCompatActivity { private static final int PERMISSION_EX_STORAGE = 10884; @Override protected void onCreate(Bundle savedInstanceState) { ... // permission check if(checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED || checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED){ System.out.println("Permission denied!"); requestPermissions(new String[]{ Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE },PERMISSION_EX_STORAGE); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); // https://docs.kii.com/ja/guides/cloudsdk/android/quickstart/install-sdk/activity-implementation-note/ if (requestCode == PERMISSION_EX_STORAGE) if (grantResults.length <= 0 || grantResults[0] != PackageManager.PERMISSION_GRANTED) { Toast.makeText(this, "権限がないため使えません", Toast.LENGTH_LONG).show(); } }
適当にボタンを設置して、それを押したら端末からfitファイルを選択してFitCSVToolに突っ込むようにします。
... private static final int READ_FIT_FILE = 20884; private void openFile(){ Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType("*/*"); //なんでも読み込み startActivityForResult(intent, READ_FIT_FILE); } ... @Override public void onActivityResult(int requestCode, int resultCode, Intent resultData) { super.onActivityResult(requestCode, resultCode, resultData); if(resultCode != Activity.RESULT_OK){ System.out.println("intent result error"); return; } if(requestCode == READ_FIT_FILE){ Uri uri = resultData.getData(); if(canWriteFile()){ String fullPath = getFullPath(uri); CSVTool.main(new String[]{fullPath}); } ... } private String getFullPath(Uri uri){ String path = uri.getPath().split(":")[1]; String root = Environment.getExternalStorageDirectory().getAbsolutePath(); return root + "/" + path; }
getFullPath
というのは、ファイル選択したときに返ってくるuriから、FitCSVToolに投げられる形のファイルパスに変換する関数です。
getPath(uri)
をすると/document/primary:fitcsv/hogehoge.fit
みたいなのが帰ってきて、:
の部分をEnvironment.getExternalStorageDirectory().getAbsolutePath()
で得られる/storage/emulated/0
に置き換える必要があります。*5
startActivityForResult
は非推奨らしいのですが、僕はこれしか知らないのでこれで書きました。要はインテントでスマホ内のファイルを選択してuriを取得できれば良いです。
実行
ファイルパスが取得できたらString []
で送り込めばOKです。CSVTool
で、アタマにFit
がついてないので注意
諸々についてはこちらを見てください↓
参考
- FIT SDK | Garmin Developers
- UNIX時間⇒日付変換 - 高精度計算サイト
- Conversion between semicircles and latitude units - Geographic Information Systems Stack Exchange
- Android Studioでアプリプロジェクトにjarファイルを追加する方法【Android】 - AppSeedのアプリ開発ブログ
- Android での実装における注意点
*1:https://developer.garmin.com/fit/protocol/ のFigure 4.
*2:1989/12/31 00:00:00 UTCのUNIX時間が631065600なので
*3:-180~180度を符号付き32ビットに格納している
*4:道の駅にらさきのすぐ近くですね https://goo.gl/maps/nruijexnn6WbTMTu9
*5:結合するときに間に/を忘れずに入れる