著者アーカイブ 村上

村上 著者:村上

【Android】アプリ内にデータを保存できる「SharedPreferences」

Androidでアプリを開発する際、ちょっとしたデータを保存したいときがあるかと思います。
Webであれば、Cookie や LocalStorage が使えますが、Android の場合でもよく似た仕組みがあります。
それがこちらの「SharedPreferences」です。

参考にさせていただいたサイトはこちら。

[Android] データを保存し Android Studio で確認 SharedPreferences
https://akira-watson.com/android/sharedpreferences.html

 

早速使い方はこちら。

SharedPreferences dataStore = getSharedPreferences("DataStore", MODE_PRIVATE);
Editor editor = dataStore.edit();
// 保存するデータを追加
editor.putString("input", "abcdefg");
editor.apply();

なお、getSharedPreferences() の第2引数で指定している MODE_PRIVATE とは「このアプリからのみ読み書き可能」という意味になります。
基本的には、これでOKだと思います。

また、データはほかにも下記の型を保存できます。

editor.putInt("DataInt", 123);
editor.putBoolean("DataBoolean", true);
editor.putLong("DataLong", 12345678909876L);
editor.putFloat("DataFloat", 12.345f);

そして、読み出しは下記のようになります。

String dataString = dataStore.getString("input", null);

読み出しについてはいたってシンプルですね。
なお、第二引数には、データを取得できなかった場合の代用値を指定します。

他の型の取得については下記のとおりです。

int dataInt = dataStore.getInt("DataInt", 0);
boolean dataBoolean = dataStore.getBoolean("DataBoolean", false);
long dataLong = dataStore.getLong("DataLong", 0);
float dataFloat = dataStore.getFloat("DataFloat", 0);

 

以上、アプリ内にデータを保存できる SharedPreferences の使い方でした。
データベースに保存するまでもないような、小さなデータなどでしたらこれで事足りるかと思います。
是非、便利に使ってください。

村上 著者:村上

【Android】XMLをJSONに変更できるライブラリ「JSONIC」

結論から言うと、私の環境ではうまく使えなかったので、実際の使用は見合わせました。
が、かなり便利そうだったので、いつか使うとき用に備忘録としてまとめます。

今回紹介するのは、「JSONIC」というJava用のシンプルかつ高機能なJSONエンコーダー・デコーダーライブラリです。
GitHubはこちらから。

GitHub – hidekatsu-izuno/jsonic: simple json encoder/decoder for java
https://github.com/hidekatsu-izuno/jsonic

…しかし、よく見たら、今後機能強化が行われることがないメンテナンスモードに移行するとのこと。
もし利用する場合は、jackson への移行をおすすめしているとのことでした。

 

使い方のサンプルコードはこちら。

import net.arnx.jsonic.JSON;

// POJOをJSONに変換します
String text = JSON.encode(new Hoge());

// JSONをPOJOに変換します
Hoge hoge = JSON.decode(text, Hoge.class);

いたってシンプルです。

また、XMLをJSONに変換したい場合は、下記のようにします。

Document doc = builder.parse(new File([変換したいXMLファイル]));
String xmljson = JSON.encode(doc);

例えば、下記のようなXMLファイルを変換すると、

<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Feed Title</title>
  <entry>
    <title>Entry Title</title>
  </entry>
</feed>

変換後のJSONは下記のようになります。

["feed", {"xmlns": "http://www.w3.org/2005/Atom"},
    ["title", "Feed Title"],
    ["entry",
        ["title", "Entry Title"],
    ]
]

なお、この時、タグ間の空白文字も TextNodeとして出力されるらしいので、これが不要な場合は、DOM作成時に取り除く必要があるとのことでした。

 

以上、簡単ではありますが、JSONIC ライブラリの使い方でした。
もし、JSONのエンコード・デコードをシンプルに行えるライブラリをお探しでしたら、参考にしていただければと思います。
が、最初に書いたように、JSONIC は今後機能強化を行わないとのことでしたので、利用する場合は、jackson を使用するようにしてください。

村上 著者:村上

【Cordova】初回起動時にcordova-plugin-ibeaconが表示するAlertを非表示にする方法

タイトル通り、cordova-plugin-ibeacon プラグインが表示しているアラートを非表示にする方法です。
実際に表示されるアラートはこちら。

表示されているメッセージ自体は「このアプリケーションがビーコンを検出できるようにアクセスを許可してください」なので、これ自体に問題はないのですが、文章はプラグインの中で指定されているものですし、このアラートとは別に、位置情報の取得許可を求めるダイアログが表示されるので、表示させないほうが綺麗かなと思います。
表示/非表示はお好みかもしれませんが、私の場合、現在開発中のアプリは日本語表記のみなので、英語のアラートは非表示にしようと思います。

 

さて、このアラートを表示させないようにする方法ですが、このプラグインを追加した時に追加される LocationManager.java というファイルの中を修正します。

で、このLocationManeger.java の302行目辺りに、AlertDialog の設定をしている記述がありますので、そこを確認します。
AlertDialog もしくは、アラートメッセージの「Please grant location access so this app can detect beacons.」で調べれば、すぐに見つかると思います。
そして、その記述の下の方に、builder.show(); という記述があり、ここで Alert を表示しています。
なので、これをコメントアウトします。

作業としては以上です!
あとは、一旦アプリを削除して再インストールするか、Android の設定 > アプリ からこのアプリの設定を開き、データを削除してから再度起動すれば、アラートが表示されないことを確認できるかと思います。

 

以上、cordova-plugin-ibeacon が表示しているアラートを非表示にする方法でした。
良かったら参考にしてください。

村上 著者:村上

【Cordova】現在の位置情報を取得できる「cordova-plugin-geolocation」プラグイン

タイトル通り、Cordovaで開発中のアプリで現在地の緯度・経度を取得する方法です。
今回使用したプラグインはこちら。

GitHub – apache/cordova-plugin-geolocation: Apache Cordova Plugin geolocation
https://github.com/apache/cordova-plugin-geolocation

このプラグインでは、現在の位置情報を1度だけ取得したり、もしくは定期的に位置情報をし続けることができます。

インストールコマンドはこちら。

cordova plugin add cordova-plugin-geolocation

実際のコードはこちら。

// 成功した時の処理
var onSuccess = function(position) {
    console.log('Latitude: ' + position.coords.latitude);
    console.log('Longitude: ' + position.coords.longitude);
};
// 失敗した時の処理
function onError(error) {
    console.log('code: ' + error.code);
    console.log('message: ' + error.message);
}

var option = { timeout: 30000 };
// 現在の位置情報を1度だけ取得
navigator.geolocation.getCurrentPosition(onSuccess, onError, option);

成功時の処理、失敗時の処理に加えて、オプションを追加することができます。
上記のコードではタイムアウトの時間を指定しています。
他にも、enableHighAccuracy : true を指定すると、高精度な位置情報を取得できます。
もし、なるべく正確な位置情報を取得したい場合は、こちらのオプションを追加してください。

定期的に位置情報を取得し続けたいときは、navigator.geolocation.watchPosition() を使います。
なお、引数は navigator.geolocation.getCurrentPosition() と同じです。

 

ちなみにおまけですが、2点間の距離を求める方法について、リンクを張っておきます。

地球上の2点間の直線距離を求める – Qiita
https://qiita.com/s-yoshiki/items/b0a6f2143db0e1a191e8

主に自分の備忘録のためのメモですが、恐らく緯度・経度を取得した時に行うことが多い処理ではないかなと思います。
こちらも是非参考にしてください。
 
以上、Cordovaのアプリで現在地の緯度・経度を取得する方法でした。

村上 著者:村上

【Android】「The minSdk version should not be declared in the android manifest file. You can move the version from the manifest to the defaultConfig in the build.gradle file.」エラー【未解決】

タイトル通り未解決のAndroid Studioのエラーについてです。
いくつかヒットした解決策を試したのですが解消されず…。

エラーはこちら。

The minSdk version should not be declared in the android manifest file. You can move the version from the manifest to the defaultConfig in the build.gradle file.

minSdk の指定を AndroidManifest.xml ではなく build.gradle で指定するようにという内容です。
なので、この指示通りに minSdkVersion を build.gradle に書き直したのですが…それでも解消せず。

記述箇所はこのような感じです。

android {
  ...
  defaultConfig {
    ...
    minSdkVersion 14
    targetSdkVersion 24
  }
  productFlavors {
    main {
      ...
    }
    afterLollipop {
      ...
      minSdkVersion 21
    }
  }
}

ちなみに、この内容は Android Developers のページを参考にしました。

アプリのバージョニング|Android Developers
https://developer.android.com/studio/publish/versioning?hl=ja

Cordova で作成した環境だから、というのもありそうですが、まだわかってはいません。
また、このエラーがあっても別にビルドや実機での実行は試すことができるので、今のところ、一旦放置しています。
が、ずっとウィンドウ上部に「Try Again」が表示されているのもうっとおしいので、早めに解決したいところですね。

 

解決策が判明したら、改めてご紹介したいと思います!

村上 著者:村上

【Android】HTTP Clientの「OkHttp」でAPIを実行する

タイトル通り、Androidアプリで APIを使う方法についてです。
今回は「OkHttp」という HTTP Client を使っています。

参考にさせていただいた記事はこちらから。

OkHttp(基本的なGET・POST) – Qiita
https://qiita.com/naoi/items/8d493f00b0bbbf8a666c

 

早速ですが、コードはこちらから。

String url = [APIのURL];
Request request = new Request.Builder().
        url(url).
        build();

OkHttpClient client = new OkHttpClient();

client.newCall(request).enqueue(new Callback() {
    @Override
    public void onFailure(Request request, IOException e) {
        e.printStackTrace();
    }

    @Override
    public void onResponse(Response response) throws IOException {
        Log.d("Response", response.body().string());
    }
});

こちらはGETの場合の記述方法です。
データの取得は非同期で行っています。
同期処理も行えるようですが、私の環境では実行時にエラーで落ちたので、使用していません。

こちらはPOST処理の場合。

String url = [APIのURL];
MediaType MIMEType = MediaType.parse("application/json; charset=utf-8");

RequestBody requestBody = RequestBody.create(MIMEType, [送信するdata]);
Request request = new Request.Builder().
        url(url).
        post(requestBody).
        build();

OkHttpClient client = new OkHttpClient();

client.newCall(request).enqueue(new Callback() {
    @Override
    public void onFailure(Request request, IOException e) {
        e.printStackTrace();
    }

    @Override
    public void onResponse(Response response) throws IOException {
        Log.d("Response", response.body().string());
    }
});

GET処理とほぼ同じですね。
違うのは、5行目からの Request の箇所です。
こちらも非同期で処理を行うように記述しています。

 

が、ここで問題が。
記述が間違っているのか、POST処理で Data がうまく渡せません…。
JSONで記述しているのですが、どうしても渡しているはずのデータが受け取れず。
現在調査中ですが…早く直してしまいたいところです。
解決策が見つけられたら、またご紹介したいと思います!

以上、Androidアプリで API を実行するためのHTTP Client「OkHttp」についてのご紹介でした。

村上 著者:村上

【MySQL】データが重複した行を除いて抽出する方法

今回は、MySQLのデータ抽出についてです。
今まで使ったことがなかったので知らなかったのですが、抽出したデータの重複している行を除いてデータを抽出することができるそうなので、こちらの方法について、主に自分の備忘録のためにまとめ。

参考にさせていただいた記事はこちら。

重複行を除外(All, DISTINCT) – データの取得 – MySQLの使い方
https://www.dbonline.jp/mysql/select/index13.html

 

早速、その方法ですが、重複しているかどうかを指定したいカラムの前に「DISTINCT」を付けるだけです。
具体的には下記のように指定します。

SELECT DISTINCT [カラム名] FROM [テーブル名];

なお、カラムは複数指定することもできます。
その場合は、下記のように指定します。

SELECT DISTINCT [カラム名1], [カラム名2], [カラム名3] FROM [テーブル名];

ちなみに、DISTINCT ではなく ALL と指定すると、重複した行もすべて抽出するできるとのことでしたが、これは指定しなかった場合と同じ動作なので、使うことはないと思います。

 

以上、MySQLで重複した行を除いてデータを抽出する方法でした。
今までなぜ使う機会がなかったのか疑問なくらい便利なオプションでした…。
今後は是非積極的に使っていきたいと思います!

村上 著者:村上

【Cordova】「cordova-plugin-fcm」で取得したトークンが登録されていない時の対処法

以前、「cordova-plugin-fcm」プラグインの getToken() でトークン取得できない時の対処法について紹介しましたが、こちらの方法で取得できたトークンが実は使えなかったので、さらなる対処法についてです。
一応下に以前の記事を載せておきますが、こちらは非推奨ですのでご注意ください。

【Cordova】プラグイン「cordova-plugin-fcm」のgetTokenでnullが返ってくるときの対処法
https://cpoint-lab.co.jp/article/201810/【cordova】プラグイン「cordova-plugin-fcm」のgetTokenでnullが返ってくると/

 

では、今回行った対応策ですが、まず Firebase Console Messaging の設定を確認します。
で、いつから変わったのかは知らないのですが、クラウドメッセージングの設定の APNs証明書を登録する項目で、この証明書に代わり、APNs 認証キーを設定できる様になっていました。
実際の画面はこちら。

推奨しているのは、こちらのAPNs 認証キーとのことでしたので、証明書からキーに変更します。
なお、認証キーは Apple DeveloperCertificates, Identifiers & Profiles ページから作成できます。
そして、この認証キーは一度しかダウンロードできないので、万が一にも消してしまわないように注意してください。

次に、Xcodeの設定です。
Xcode の Workspace Settings から、Build System を変更します。
恐らく、New Build System になっていると思いますので、これを Legacy Build System に変更します。

変更点は上記の2点です。
あとはいつも通り Build して実行したところ、無事に getToken() でトークンが取得できました!

 

以上、getToken() で null が返ってくるときの対処法でした。
Push通知に関しては、もしAndroidで問題なく動いているのなら、iOSの原因は十中八九 証明書周りのはずなので、まずはそのあたりを調査することをおすすめします。

村上 著者:村上

【Web】APIのテストを簡単に行えるソフト「Postman」が便利

タイトル通り、今回は API のテストを簡単に行えるソフトウェアのご紹介です。
偶然使っている人を知り、便利そうなので探してみました。

ダウンロードはこちらの公式サイトから。

Postman|API Development Environment
https://www.getpostman.com/postman

Windows だけでなく、Mac、Linux の環境でも使えます。

 

起動後のページはこちら。

Request を選択すると、APIのテストを行えます。
というか、私はまだこれしか使ったことがないので、他にどんな機能があるのかを知りません。
少しずつ使っていきたいですね。

APIのテスト画面はこちら。

画面中央やや上にある欄に、テストしたいAPIのURLを入力し、その左隣で GET もしくは POST を選択します。
そして、その下のタブから、APIに渡す値を指定します。
Param や Header、POST の場合は Body もきちんと用意されています。
必要な情報を入力し終えたら、あとは Send ボタンを押すだけ。
そうすると、下の Response エリアに結果が表示されます。

 

以上、APIのテストを簡単に行う方法でした。
API 自体の開発もそうですが、外部サービスが提供している API をいったん試してみたい時とかにも便利ですね!
作業がはかどりそうです。
Web開発者の方は、是非ダウンロードしてみてはいかがでしょうか。

村上 著者:村上

【Android】「Only the original thread that created a view hierarchy can touch its views.」の対処法

今日の記事は、Androidアプリ開発中に遭遇したエラーについてです。
修正はそこまで大変ではなかったのですが、使用頻度が低く、忘れそうだったので備忘録としてまとめます。

エラーは「Only the original thread that created a view hierarchy can touch its views.」というもので、こちらはメインスレッド以外で、TextView などの UI を変更しようとすると発生するエラーです。
シンタックスエラーとは違い、ビルドは通ってしまうので要注意ですね。

 

では、早速対処法についてご紹介。
今回参考にさせていただいたサイトはこちらです。

メインスレッド以外でUIを変更する方法 – Accele Biz IT開発技術 調査報告書
http://accelebiz.hatenablog.com/entry/2016/09/01/061934

エラーが発生したコードはこちら。

TextView textView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    textView = findViewById(R.id.[ID名]);
    showMessage();
}

private void showMessage(){
    try {
        /* 処理 */
        textView.setText("[表示したい文字列]");
    } catch (JSONException e) {
        e.printStackTrace();
    }
}

一部改変していますが、だいたいこんな感じ。
で、問題は、showMessage() 内の try/catch で指定した、setText() です。
やった事がなかったので知らなかったのですが、このようにメインスレッド以外で UI を操作することはできないようでした。

ですが、対処法もちゃんと用意されていました。
参考サイトそのままですが、Handler を使用して、別スレッドからメインスレッドに処理を依頼する方法です。
具体的には下記のとおりです。

private void showMessage(){
    final Handler mainHandler = new Handler(Looper.getMainLooper());
    try {
        /* 処理 */
        mainHandler.post(() -> {
            textView.setText("[表示したい文字列]");
        });
    } catch (JSONException e) {
        e.printStackTrace();
    }
}

2行目に Handler を宣言し、TextView の操作の記述を mainHandler.post() で囲うだけです。
これを追加したところ、問題なく TextView の操作を行うことができました。

 

以上、TextView などの UI の操作をメインスレッド以外から行う方法でした。
今回の解決策は、例えば何らかの処理を別スレッド&非同期で行っていて、結果が返ってきたタイミングで UI を変更したい、等の場合にも使えるかと思います。
もし、同じエラーでお困りの場合は、是非参考にしていただければと思います。