カテゴリーアーカイブ Android

村上 著者:村上

【Cordova】端末のプラットフォームやバージョン情報を取得できるプラグイン「cordova-plugin-device」

Cordova アプリを開発中に、Android と iOS で処理を分けるなど、端末の情報を取得する必要があるときに便利なプラグイン「cordova-plugin-device」についてのご紹介です。
主に、プラグインによっては、Android でしか動作しないものがあったり、逆に iOS でのみ動作するものもあったりするのでそれの処理をかき分けたい時などに使っています。

GitHub のページはこちらから。

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

 

インストールは下記のコマンドで行います。

cordova plugin add cordova-plugin-device --save

準備は以上で完了です。
あとは、任意の場所でプラットフォームの種類などのデバイス情報を取得できます。

私が主に使うのは下記のコードです。

const device = window.device.platform;

switch (device) {
    case 'Android':
        // 端末が Android だった時の処理
        break;
    case 'iOS':
        // 端末が iOS だった時の処理
        break;
    default:
        // その他の処理
}

上記では、アプリを実行している端末が Android なのか iOS なのか、それ以外のものなのかを判定して、それぞれの処理を実行できます。

他にも、UUID を取得したり、バージョン情報を取得したりすることもできます。
取得できる情報は下記のとおりです。

  • device.model
  • device.platform
  • device.uuid
  • device.version
  • device.manufacturer
  • device.isVirtual
  • device.serial

また、端末の製造元や、現在の実行環境が実機なのかシュミレータなのかを判断することもできます。
使い方は下記のとおりです。

// 製造元を取得
const manufacturer = window.device.manufacturer;
// シュミレータかどうかを取得
const isSimulator = window.device.isVirtual;

なお、シュミレータかどうかの判定については、OS Xブラウザの場合は常に false を返すようです。

 

以上、アプリを実行している端末の情報を取得できるプラグイン「cordova-plugin-device」のご紹介でした。
プラットフォームの取得以外はまだ使ったことはありませんが、それだけでもかなり使えますので、是非ご活用ください。

  • この記事いいね! (0)
村上 著者:村上

【Android】「java.lang.ClassNotFoundException: Didn’t find class “android.support.v4.animation.AnimatorCompatHelper” on path: DexPathList」エラーの対処法

長々しいタイトルですが、今回は Cordova アプリを開発中に遭遇したエラーについて。
なお、プラットフォームは Android です。
Android 9 で、Adobe の画像加工機能がクラッシュする不具合が発生しており、それを修正している最中に遭遇しました。
一部のみ抜粋ですが「java.lang.ClassNotFoundException: Didn’t find class “android.support.v4.animation.AnimatorCompatHelper” on path: DexPathList」とのことでしたので、そのまま「“android.support.v4.animation.AnimatorCompatHelper”ファイルが見つかりません」という意味のようです。

 

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

AnimatorCompatHelper Class Not Found Exception using AppCompat 26.0.0 · Issue #396 · h6ah4i/android-advancedrecyclerview · GitHub
https://github.com/h6ah4i/android-advancedrecyclerview/issues/396

compile 'com.github.h6ah4i:android-advancedrecyclerview:feature~support_libraries_v26-SNAPSHOT'

記事内には上記コードを追加するという方法もありましたが、私の環境ではエラーが発生してうまくいきませんでした。

そのため、下記のコードを build.gradle の最後に下記を追加する方法を採用しました。

configurations.all {
    resolutionStrategy.eachDependency { DependencyResolveDetails details ->
        def requested = details.requested
        if (requested.group == 'com.android.support') {
            if (!requested.name.startsWith("multidex")) {
                details.useVersion '25.4.0'
            }
        }
    }
}

あとは、Sync Now を実行します。
なお、以前の投稿記事で紹介したように、AsyncTaskCompat.javaAsyncTaskCompatHoneycomb.java を手動で追加していたのですが、ファイルが既に存在しているとのエラーが発生したので、こちらの 2ファイルは削除しました。
で、エラーが発生したので Try Again を実行後、Build → Run したところ、問題なく動作しました。
「効果」のオプションを選択するとそこでクラッシュしていたのですが、再現しなくなりました。
一通り、追加したオプションを使ってみましたがそちらも問題なしでした。

 

以上、Android アプリで「java.lang.ClassNotFoundException: Didn’t find class “android.support.v4.animation.AnimatorCompatHelper” on path: DexPathList」エラーが発生した時の対処法でした。
どなたかの参考になれば幸いです。

  • この記事いいね! (0)
村上 著者:村上

【Android】複数のパーミッションをリクエストする方法

毎回書き方を忘れてしまうので、備忘録としてまとめます。
Android のアプリで、複数のパーミッションをリクエストする方法です。

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

Androidのパーミッションリクエスト(複数)- Qiita
https://qiita.com/tcb78/items/fd2e16eb7f1eacd0ba26

 

早速ですがコードは下記のとおりです。
onCreate() 内に下記を記述します。

private final int REQUEST_CODE = 1000;

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

    // Android 6, API 23以上でパーミッションの確認
    if(Build.VERSION.SDK_INT >= 23) {
        String[] permissions = {
                Manifest.permission.WRITE_EXTERNAL_STORAGE,
                Manifest.permission.ACCESS_COARSE_LOCATION,
                Manifest.permission.ACCESS_FINE_LOCATION
        };
        checkPermission(permissions, REQUEST_CODE);
    }
    // メインの処理を記述
}

なお、今回は位置情報とストレージへのアクセスをリクエストしています。
REQUEST_CODE の定義を忘れないように気を付けてください。私はよく忘れます。

次に、checkPermission() を下記のように定義します。

public void checkPermission(final String[] permissions,final int request_code){
    ActivityCompat.requestPermissions(this, permissions, request_code);
}

上記の処理を実行すると、許可されていないパーミッションのみリクエストされます。

最後に、onRequestPermissionsResult()requestPermissions() のコールバックを受け取ったときの処理を定義します。

@Override
public void onRequestPermissionsResult(int requestCode,
                                       @NonNull String[] permissions,
                                       @NonNull int[] grantResults) {

    if (requestCode == REQUEST_PERMISSION) {
        for (int i = 0; i < permissions.length; i++) {
            if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
         // パーミッションが許可された
               Log.d("Permission", "Added Permission: " + permissions[i]);
            } else {
                // パーミッションが拒否された
                Log.d("Permission", "Rejected Permission: " + permissions[i]);
            }
        }
    }
}

もし必要であれば、パーミッション別にリクエストが許可/拒否されたときの処理を記述することもできます。
状況に応じて追加してください。

追加するコードは以上です。
あとは、設定からパーミッションの許可を無効にするか、アプリをアンインストールしてから再インストールして実行すると、パーミッションリクエストのダイアログが表示されることが確認できると思います。

 

以上、Android アプリで複数のパーミッションをリクエストする方法でした。
困ったときは、是非コピー&ペーストしてご活用ください。

  • この記事いいね! (0)
村上 著者:村上

【Cordova】写真からExif情報を取得するプラグイン「cordova-exif」

今回は、写真から Exif 情報を取得するためのプラグイン「cordova-exif」について。
以前は JavaScript を使って取得していたのですが、色々修正することになったので併せてこちらも修正しました。

GitHub のページはこちらから。

GitHub – guilhermefarias/cordova-exif: This plugin, is the simplest way to get exif data of images at Cordova platform (Phonegap)
https://github.com/guilhermefarias/cordova-exif

 

実装方法ですが、まず下記のコードを実行します。

cordova plugin add https://github.com/domax/cordova-exif.git --save

なお、このプラグインを使うには cordova-plugin-cameracordova-plugin-file が必要です。
インストールされてない場合は、自動でこれらのプラグインもインストールされます。

ただし、プラグインのバージョンによっては競合が起こる事もあり、私の環境ではカメラプラグインのバージョンが新しすぎたようでエラーになりました。
そのため、最新のカメラプラグインやファイルプラグインを既にインストール済みの場合は、問題がなければ一度削除してから cordova-exif をインストールすることをおすすめします。

インストールが完了したら、あとは下記のコードで Exif 情報を取得できます。

CordovaExif.readData(imageURI, function(exifObject) {
  console.log(exifObject);
});

取得できるデータ一覧は上の GitHub のページに記載されているので、分からなくなった場合はご確認ください。

なお、カメラプラグインと合わせて使う場合は下記のように書きます。

function onSuccess(imageURI) {
  CordovaExif.readData(imageURI, function(exifObject) {
    console.log(exifObject);
  });
}
function onFail(message) {
  alert('Failed because: ' + message);
}
var options = {
  sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
  quality: 50,
  encodingType: Camera.EncodingType.JPEG,
  destinationType: Camera.DestinationType.FILE_URI
}
navigator.camera.getPicture(onSuccess, onFail, options);

なお、上記のプログラムでは、フォトアルバムから写真を選択するようにしています。

気を付けたい点としては、カメラプラグインのオプションで correctOrientationtrue に設定し、画像を正しい向きに直す処理を追加すると、取得できる Exif 情報が減りました。
私は写真から緯度経度を取得したかったので、上記の理由から correctOrientation を追加するのをやめました…。
なお、写真の向きは取得できたので、そちらで正しい向きに直す処理を追加することはできます。

 

以上、写真から Exif 情報を取得するためのプラグイン「cordova-exif」についてのご紹介でした。
インストール時に若干手間取りましたが、便利なプラグインですので是非ご活用ください。

  • この記事いいね! (0)
takahashi 著者:takahashi

AndroidのGPUレンダリングを有効にすれば描画が快適になる…かも?

Androidで描画の速度が遅い…という方はGPUレンダリングの設定を行うことで改善する場合があるようです。

Androidのスクロールを大きく改善する?「GPUレンダリング」機能をONにしてみよう – TeraDas

まず、システム設定を開きます。

中からシステムをタップすると下のような画面になります。

開発者向けオプションをタップ。

“GPUレンダリングを使用” “HWオーバーレイを無効” の2項目を有効化します。

これで画面の描画に常にGPUが使用されるようになり、画面描画時のCPUの負荷が減ります。

ただし、機種によってはGPUの性能が低かったりするとかえって動作が遅くなってしまったり、CPUで処理させた方が高速だったりするケースもありますし、あまり変わらいケースもあるようです。

ON/OFFそれぞれの状態で動作を確認してみてどちらの方が動作が早くなるか確認しながら設定するといいかもしれません。

ちなみに、開発者オプションは初期状態では表示されていないので、端末情報のビルド番号を複数回タップして表示させる必要があります。

Androidスマホ/タブレットで「開発者向けオプション」をオンにする – @IT

  • この記事いいね! (0)
村上 著者:村上

【Cordova】Abobeの画像加工機能を実装できるプラグイン「phonegap-plugin-csdk-image-editor」

本来ならばこちらの記事を先に投稿するべきだったかも…。

昨日の記事で、「phonegap-plugin-csdk-image-editor」というプラグインを導入した際に遭遇したエラーについての対処法について紹介しましたが、今日はそのプラグインの導入方法についてです。

GitHub のページはこちらから。

GitHub – CreativeSDK/phonegap-plugin-csdk-image-editor: A PhoneGap plugin for the Creative SDK Image Editor.
https://github.com/CreativeSDK/phonegap-plugin-csdk-image-editor

 

実装方法ですが、まずは本命のプラグインを導入する前に phonegap-plugin-csdk-client-auth プラグインをインストールする必要があります。
で、その際に、各プラットフォームの クライアントIDクライアントシークレットが必要になるので、下記の URL から登録する必要があります。

Adobe I/O Console
https://console.adobe.io/integrations

あとは上記で登録した ID などを使って、下記のコマンドを実行します。

cordova plugin add --save phonegap-plugin-csdk-client-auth --variable CSDK_CLIENT_ID_IOS="[iOS のクライアントID]" --variable CSDK_CLIENT_SECRET_IOS="[iOS のクライアントシークレット]" --variable CSDK_CLIENT_ID_ANDROID="[Android のクライアントID]" --variable CSDK_CLIENT_SECRET_ANDROID="[Android のクライアントシークレット]"

こちらの実行が完了したら、下記のコマンドを実行し、画像加工用のプラグインをインストールします。

cordova plugin add --save phonegap-plugin-csdk-image-editor

準備はこれで完了です。
あとは、任意の場所で下記のコードを実行すればOKです。

function success(newUrl) {
    // 画像加工が成功した時の処理
    console.log("Success!", newUrl);
}
function error(error) {
    // 画像加工が失敗した時の処理
    console.log("Error!", error);
}

var imageUrl = "[加工したい画像のURI]";
var options = {
    outputType: CSDKImageEditor.OutputType.JPEG,
    tools: [
        CSDKImageEditor.ToolType.EFFECTS,
        CSDKImageEditor.ToolType.CROP
    ],
    quality: 50
};
// エディターを起動
CSDKImageEditor.edit(success, error, imageUrl, options);

メソッドやオプションについてのガイドは下記からご確認頂けます。

API guide
https://github.com/CreativeSDK/phonegap-plugin-csdk-image-editor/blob/master/docs/api.md

 

以上、Adobe Creative SDK の画像加工機能を実装できるプラグイン「phonegap-plugin-csdk-image-editor」のご紹介でした。
ただし、昨日の記事でも書きましたが、別途ライブラリの追加が必要なのでご注意ください。

  • この記事いいね! (0)
村上 著者:村上

【Cordova】「phonegap-plugin-csdk-image-editor」プラグイン導入時に遭遇したエラーの対処法

今回は、Cordova のプラグイン「phonegap-plugin-csdk-image-editor」を導入しようとした際に遭遇したエラーです。
なお、現在も違うエラーに苦戦中…。
…既存のコードを修正したほうが早いかもしれません。

エラーメッセージは「java.lang.NoClassDefFoundError: Failed resolution of: Landroid/support/v4/os/AsyncTaskCompat;」です。
ちなみに、Android Studio で実行した際表示されたエラーメッセージ冒頭に書かれているエラーは「java.lang.NoClassDefFoundError: Failed resolution of: Landroid/support/v4/os/BuildCompat;」でしたが、そちらではなく「java.lang.NoClassDefFoundError: Failed resolution of: Landroid/support/v4/os/AsyncTaskCompat;」で検索したところ有効な記事にたどり着けました。

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

android – java.lang.NoClassDefFoundError: Failed resolution of: Landroid/support/v4/os/BuildCompat – Stack Overflow
https://stackoverflow.com/questions/39601370/java-lang-noclassdeffounderror-failed-resolution-of-landroid-support-v4-os-bui

 

で、対処法ですが、「support/v4/os/AsyncTaskCompat」関連のファイルが参照できないことが問題なので、手動で追加すればOKです。
下記の画像のように、java ディレクトリの直下に android.support.v4.os というディレクトリを作成します。

あとは、作成したディレクトリ内に、AsyncTaskCompat.javaAsyncTaskCompatHoneycomb.java のファイルを下記のコードで作成します。

AsyncTaskCompat.java

/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package android.support.v4.os;
import android.os.AsyncTask;
import android.os.Build;
/**
 * Helper for accessing features in {@link android.os.AsyncTask}
 * introduced after API level 4 in a backwards compatible fashion.
 */
public final class AsyncTaskCompat {
    /**
     * Executes the task with the specified parameters, allowing multiple tasks to run in parallel
     * on a pool of threads managed by {@link android.os.AsyncTask}.
     *
     * @param task The {@link android.os.AsyncTask} to execute.
     * @param params The parameters of the task.
     * @return the instance of AsyncTask.
     */
    public static <Params, Progress, Result> AsyncTask<Params, Progress, Result> executeParallel(
            AsyncTask<Params, Progress, Result> task,
            Params... params) {
        if (task == null) {
            throw new IllegalArgumentException("task can not be null");
        }
        if (Build.VERSION.SDK_INT >= 11) {
            // From API 11 onwards, we need to manually select the THREAD_POOL_EXECUTOR
            AsyncTaskCompatHoneycomb.executeParallel(task, params);
        } else {
            // Before API 11, all tasks were run in parallel
            task.execute(params);
        }
        return task;
    }
    private AsyncTaskCompat() {}
}

AsyncTaskCompatHoneycomb.java

/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package android.support.v4.os;
import android.os.AsyncTask;
/**
 * Implementation of AsyncTask compatibility that can call Honeycomb APIs.
 */
class AsyncTaskCompatHoneycomb {
    static <Params, Progress, Result> void executeParallel(
            AsyncTask<Params, Progress, Result> task,
            Params... params) {
        task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
    }
}

上記 2つのファイルが作成出来たら、アプリを一度 Clean してから Build → 実行してください。
私の環境では、問題なく動作しました!

 

以上、「phonegap-plugin-csdk-image-editor」プラグインを導入時に遭遇したエラー「java.lang.NoClassDefFoundError: Failed resolution of: Landroid/support/v4/os/AsyncTaskCompat;」の対処法でした。
「phonegap-plugin-csdk-image-editor」プラグインの導入方法そのものについては、後日ご紹介する予定です。

  • この記事いいね! (0)
takahashi 著者:takahashi

確かにSIMフリーのAndroid端末でも防災速報が受信できた話

先日の大雨は久々に不安を感じるレベルでした。

側溝から水が噴水のようにあふれていたり、道路に水が冠水してしまっていたり、極めつけは普段名前の聞かないような川の周辺まで警報が出て、ちょっと恐怖を感じました。

冠水こそありましたが、川の氾濫という最悪の自体がギリギリ回避できて、ほっとしました。

ところで、先日SIMフリーのAndroid端末でも、Android8.1から標準で緊急速報が受信できるようになったという話をご紹介しました。

こちらの記事ではIIJ社が行った実験による緊急速報の受信の様子をご紹介しましたが、実際に今回の増水による避難勧告発令時に、自分が所有するPixel 3a(Android 9)でも実際に緊急速報を受信することができました。

実際にはこのような画面になりました。

前回ご紹介したIIJ社の実験の通り、最初に内容のない緊急速報を受信し、そのすぐ後に詳細な内容を受信しました。

以前使っていたXperia Z5(Softbank版 Android 6)では警報を受信しても専用の通知音がなるだけでしたが、Pixel 3aの場合は通知音が流れた後、内蔵の読み上げエンジンで全文が音声で読み上げられるようになっていました。

これはロック画面を解除していない状態でも行われ、スマホを開くことなく警報内容を確認することができるので、安心できます。

この機能はAndroid 8.1以降のAndroidには標準で含まれているため、SIMフリーであってもモバイル回線に接続されていればメーカーやキャリア側で意図的に無効化されない限りは8.1以降のすべてのAndroidで受信できそうです。

いままで、こういった重要な機能が搭載されていないといった理由でSIMフリー版のスマホを購入がちょっと心配になるパターンもあったのですが、今後はそういった縛りを受けることなく機種を選ぶことができそうなのはとてもありがたいですね。

  • この記事いいね! (0)
村上 著者:村上

【Android】「Duplicate class android.support.v4.app.INotificationSideChannel found in modules classes.jar (androidx.core:core:1.0.0) and classes.jar (com.android.support:support-compat:27.0.2)」エラーの対処法

長々としたタイトルですが、今回は Android Studio で発生したエラーについてです。
なお、ネイティブアプリではなく、Cordova で開発したアプリです。
エラーメッセージはもっと長かったので割愛します。

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

gradle – Duplicate class android.support.v4.app.INotificationSideChannel found in modules classes?
– Stack Overflow

https://stackoverflow.com/questions/55909804/duplicate-class-android-support-v4-app-inotificationsidechannel-found-in-modules/55932544

こちらの記事にはエラーメッセージが掲載されていますが、まさしくこのような感じのメッセージでした。
そしてこれだけでは何をどう直していいのかが分からない…。

 

さて、解決方法ですが、gradle.properties というファイルに下記の 2行を追加するだけです。

android.useAndroidX=true
android.enableJetifier=true

ただ、私の環境では gradle.properties がなかったので、作成してから追加しました。
なお、作成するときは、プロジェクト直下のファイルを右クリックし、表示されたメニューの New > File から作成しました。
画面イメージは下の画像のとおりです。

あとは、普段通りビルドをしたところ、発生していたエラーが解消されました。

…が、あとになって、不要なプラグイン「cordova-plugin-firebase」を削除して再度実行したところ、エラーそのものが発生しなかった模様…。
たまにやってしまうのですが、不要なプラグインはすぐに消すようにしたほうが良さそうですね。

 

以上、Android Studio で発生したエラーの対処法でした。
エラーメッセージが長い&意味がわかりにくいのでとりあえず検索しましたが、有効な解決方法がヒットしてよかったです。
ご参考になれば幸いです。

  • この記事いいね! (0)
村上 著者:村上

【Android】LinearLayoutで囲んだページをスクロールさせる方法

Android アプリを修正中に、LinearLayout で囲った要素をスクロールさせたかったので、その対処法です。
…というか、LinearLayout って要素がいくら増えてもスクロールしない仕様なのですね。
今後もうっかりこの仕様を忘れて「あれ?」となる未来が見えそうなので、忘れないようにしなければ。

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

LinearLayout をスクロールさせる方法(ScrollViewの使用方法) – [サンプルコード/Androidアプリ] ぺんたん info
http://pentan.info/android/app/sample/linear_scroll.html

 

対処方法としましては、スクロールさせたい LinearLayout を ScrollView で囲むだけです。
サンプルコードは下記のとおりです。

<ScrollView
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_height="fill_parent"
  android:layout_width="fill_parent">
  <LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <!-- 表示したい要素 -->

  </LinearLayout>
</ScrollView>

XMLファイルに記述する場合、上記のようにすれば、ページをスクロールすることができます。

なお、参考サイトでは、Activity のファイルで指定する方法についても掲載されておりますので、お好きな方法を採用してください。
個人的には、XML ファイルに追加する方法の方が楽だし分かりやすいと思います。

使用する際の注意点としましては、ScrollView は指定する子要素が 1つでなければいけないということが挙げられます。
なので、複数の要素をスクロールさせたい場合は、LinerLayout などのレイアウト要素を用いて、複数の要素を 1つにまとめる必要があります。

また、上記の方法では縦スクロールが有効になりますが、もし横スクロールを行いたい場合は、ScrollViewHorizontalScrollView に変更してください。

 

以上、Android の LinerLayout をスクロールさせる方法でした。
皆様は、私のようにうっかり仕様を忘れてしまわないようにご注意ください。

  • この記事いいね! (0)