カテゴリーアーカイブ Android

asaba 著者:asaba

【ButterKnife】バターナイフは明示的にgradleに書くべき

viewのメソッドを簡潔にかくことが出来るライブラリです。一般的なviewを使いたい時は、findViewByIdで紐付けるだけで使うことが

できますが、これが複数のviewとなると、同じようなコードができてしまいこれでは可読性に欠けてしまいます。

バターナイフは、このダブつくview定義を事前に定義させることでsetContentViewの下からviewの操作を可能にしてくれるので、複数の

ビューを使いたいけど管理が大変なエンジニアさんには重宝されています。こんな感じ↓

class ExampleActivity extends Activity {
@BindView(R.id.title) TextView title;
@BindView(R.id.subtitle) TextView subtitle;
@BindView(R.id.footer) TextView footer;

@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.simple_activity);
ButterKnife.bind(this);
// TODO Use fields...
}
}

 

今自分が開発しているアプリもバターナイフを使って管理しているのですが、グレイドル(また出たなお前)のバージョンを上げたら

やっぱりというべきかエラーに通せんぼされてしまいました。

 


Error:Execution failed for task ':app:javaPreCompileDebug'.
> Annotation processors must be explicitly declared now. The following dependencies on the compile classpath are found to contain annotation processor. Please add them to the annotationProcessor configuration.
- butterknife-6.1.0.jar (com.jakewharton:butterknife:6.1.0)
Alternatively, set android.defaultConfig.javaCompileOptions.annotationProcessorOptions.includeCompileClasspath = true to continue with previous behavior. Note that this option is deprecated and will be removed in the future.
See https://developer.android.com/r/tools/annotation-processor-error-message.html for more details.

訳してみました。

プロセッサは明示的に宣言されなければなりません。次のコンパイルクラスパスへの依存関係に、注釈プロセッサが含まれています。 annotationProcessor設定にそれらを追加してください。

 

どうやらバターナイフはグレイドルのバージョンに合わせてannotationProcessorとして定義しなければいけないみたいです。グレイドル

アップデート前は普通に定義しなくても使えていたのに・・・。

まあもうできたのが6年前なので仕様が変わっていても不思議じゃないですよね。という訳でannotationProcessorにバターナイフを定義してあと残り

なく解決です。

 

annotationProcessor "com.jakewharton:butterknife:6.1.0"
compileOnly "com.jakewharton:butterknife:6.1.0"

このライブラリに変わるものがすでに出てきているか分かりませんが、ライブラリとしては書くことが少なく学習コストも低いので

いとまがあれば使ってみたいと思います。

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

【Cordova】「The versions of the Android Gradle plugin and Gradle are not compatible.」エラーの対処法

ちょっとミスをして、Cordova アプリから Android プラットフォームの削除・再追加を行ったのですが、その時に発生したエラーについて。
Android Studio のバージョンを上げたのも原因だったのかも?

Gradle のバージョンに関するエラーで、全文は下記のとおり。

ERROR: The versions of the Android Gradle plugin and Gradle are not compatible.
Please do one of the following:
Update your plugin to version 2.4. This will require changes to build.gradle due to API changes.

エラー:Android GradleプラグインとGradleのバージョンは互換性がありません。次のいずれかを行ってください。プラグインをバージョン 2.4 に更新してください。これはAPIの変更により build.gradle への変更を必要とします。」とのこと。

 

そのため、エラー文に書いてある通り、build.gradle のバージョンを更新しました。
また、Android Studio の File > Project Structure の Project でも、バージョンを確認しました。
…が、最初はどこを直していいのかわからず、いろんなところを直しては戻し、また別のところの値を変え…とやっていたら、いつのまにか直っていた感じなので、確認箇所がこれでいいのかは不明です。

一応、参考にさせていただいたサイトを挙げておきます。

[Android Studio][gradle]gradleとAndroid plugin for gradleのバージョンを合わせる
https://qiita.com/azumak/items/c48c56447a7a345f2b43

 

以上、Android Studio で Gradle のバージョンエラーが発生した際の対処法についてでした。
あまり参考にならない気もしますが…。

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

【androidJava】BroadcastReceiverを試しに使ってみる

BroadcastReceiverとは、何かのタイミングで端末に特定の処理を通知するときによく使われる便利なライブラリです。

軽い機能であればfirebaseよりも手軽に実装することができるので、息抜きにミニアプリを作ってみたいと思ったときに試してみて

ください。

自分が書いたコードはこんな感じに仕上がりました。まずボタンを押すと、pickerがでてきます。そのpickerを使って時間を指定して、その時間になったらトーストで時間ですよ~とお知らせするシンプルなものになっております。お休みのときにささっと書いたので情報少しが古い&コードが乱雑ですがご容赦くださいまし。

MainActivity↓

</pre>
<pre>public class MainActivity extends AppCompatActivity {

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

        Button button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                TimePicker();
            }
        });
        }
        public void TimePicker(){
            final Calendar calender = Calendar.getInstance();
            int hour = calender.get(Calendar.HOUR_OF_DAY);
            int minute = calender.get(Calendar.MINUTE);

            TimePickerDialog dialog = new TimePickerDialog(
                this,
                new TimePickerDialog.OnTimeSetListener() {
                    @Override
                    public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
                        System.out.println(hourOfDay);
                        calender.setTimeInMillis(System.currentTimeMillis());
                        calender.add(Calendar.SECOND, 5);

                        Intent intent = new Intent(getApplicationContext(),
                                AlarmBroadcastReceiver.class);
                        PendingIntent pending = PendingIntent.getBroadcast(
                                getApplicationContext(), 0, intent, 0);
                        // アラームをセットする
                        AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
                        if (am != null) {
                            am.setExact(AlarmManager.RTC_WAKEUP, calender.getTimeInMillis(), pending);

                            Toast.makeText(getApplicationContext(),
                                    "Set Alarm ", Toast.LENGTH_SHORT).show();
                        }
                    }
                },
                hour,minute,true) ;
            dialog.show();
        }
}</pre>
<pre>

今回のお題であるBroadcastReceiverです。

</pre>
<pre>public class AlarmBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // ここに端末に対してしたい処理を書きます。例ではトーストになっているので変えても構わないです。
        Toast.makeText(context, "Received ", Toast.LENGTH_LONG).show();
    }
}</pre>
<pre>

マニフェストには、パーミッションでWAKE_LOCKを設定しておきます。

その後に、applicationタグのすぐ上に”AlarmBroadcastReceiver”を定義しておきます。これがないとBroadcastReceiverが反応しない

ので忘れないでくださいね。

</pre>
<pre><uses-permission android:name="android.permission.WAKE_LOCK"/></pre>
<pre><application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>

            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
    </activity>
    <receiver android:name=".AlarmBroadcastReceiver"
              android:process=":remote" />
</application></pre>
<pre>

レイアウトのほうはボタンだけなので割愛させていただきました。コードの量も少なめで実装できるので、メンテナンスにも苦労しなさそうです。おすすめです。

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

【Cordova】カメラプラグイン利用時にOutOfMemoryErrorでアプリが落ちる時の対処法

後輩君がササッと調べてくれました!
Cordova に カメラプラグイン「cordova-plugin-camera」を導入した際、ギャラリーから選択した画像のサイズが大きすぎてアプリが落ちるというバグが発生していました。
今までは、カメラプラグインのオプションの allowEdit を有効にして、画像を正方形にトリミングしていたのですが、Android では、その方法が推奨されていないので、トリミングを行わないように変更しました。
そしたら、画像サイズが大きすぎでアプリがクラッシュ…。
なお、エラーメッセージは「OutOfMemoryError: Failed to allocate a 75497480 byte allocation with 16773216 free bytes and 59MB until OOM」というものでした。

 

で、それについてぼやいたら、後輩君が検索してヒットしたページを送ってくれました。
それがこちら。

Simon Mac Donald: Change to Camera code in PhoneGap 1.9.0
http://simonmacdonald.blogspot.com/2012/07/change-to-camera-code-in-phonegap-190.html

こちらの記事によると、「getPicture メソッドに quality や targetWidth / targetHeight などのいくつかのパラメータを指定すると、メモリ不足エラーが発生する可能性があります」とのこと。
それらを思いっきりやってる…!ということで、記事に掲載されていたサンプルコードを見本に、コードを下記のように修正しました。

const options = {
    quality: 100,
    correctOrientation: true,
    saveToPhotoAlbum: true,
    destinationType: navigator.camera.DestinationType.DATA_URL,
    sourceType: navigator.camera.PictureSourceType.CAMERA,
    encodingType: navigator.camera.EncodingType.JPEG,
};
navigator.camera.getPicture((imageData) => {
    // 成功時の処理
}, (error) => {
    // 失敗時の処理
}, options);

quality は 100 のまま、encodingType を JPEG 形式に変更し、targetWidthtargetHeight は定義しないようにしました。
この状態で実行したところ、アプリが落ちなくなり、無事にカメラで撮影した画像データが取得できました!
また、sourceType を CAMERA から PHOTOLIBRARY に変更しても問題ありませんでした。

 

以上、Cordova のプラグイン「cordova-plugin-camera」利用時に、OutOfMemoryError でアプリが落ちる時の対処法でした。
というか、そもそも写真は PNG ではなく、JPEG で保存すべきでしたね…。
同じような現象にお悩みの方は、是非参考にしていただければと思います。

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

【androidJava】LocationManagerで現在位置が取れない時の処理

現在地を取得したい時はLocationManagerで取ることができますが、gpsの情報が不正確だったりgpsの許可が下りていなかった場合は nullで帰ってきてしまい正しい位置情報を取得することができません。しのぐ方法はいくつかあるのですが、自分はまず最初に位置情報を 取得させ、nullだった場合はLocationManager.NETWORK_PROVIDER(基地局からの現在位置の情報)を使いネットワークから取得 させています。

最初からgpsの設定していない場合はSettings.ACTION_LOCATION_SOURCE_SETTINGSを使ってgpsを使うように促して設定ページに移動 させます。これで最小限の設定が出来るので、後は端末のバージョンと相談しながら必要なパーミッションや機能をつければ実装完了です。


Location location = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);

if (location != null) {

  System.out.println(location + "there");

  onLocationChanged(location);

  GeoPoint homeposition = new GeoPoint(location.getLatitude(),location.getLongitude());

  mapController.setCenter(homeposition);

} else { location = mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

  System.out.println(location+ "null");

  onLocationChanged(location);

  GeoPoint homeposition = new GeoPoint(location.getLatitude(), location.getLongitude());

  mapController.setCenter(homeposition);

}
// GPSを設定するように促す
Intent settingsIntent =
        new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(settingsIntent);

 

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

【androidJava】gms:play-services-locationが使えない時の対処法

gmsplay-services-locationのバージョンが古かったので、アップデートしようとしたところでエラーが起きました。当然ですが新機種で使うにはアップデートが必要とのことだったので、渋々インストールしようとしたところ更に次のようなエラーが出た。(二枚目です)

could not findとのことなので、恐らくallprojectsメソッド内でgoogle()を定義し忘れていると思い目を通したら案の定何も無かった。
のでbuildscript内とallprojects内それぞれにgoogle()を定義して解決させました。
buildscript {
  repositories {
     jcenter()
     google()
}
allprojects {
 repositories { 
    jcenter()
    google()
}

google製のライブラリgms:play-services-locationを使うには、google様の名前を付けましょうねということですね。

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

【androidJava】path.xml内で複数のパスを記述するのは避けましょう

fileproviderを使う際に必要なcontentsスキームから成るディレクトリを作るには、pathのxmlファイルが必要になります。

このファイル内にはパスを二つ以上書くこともできるのですが、そうすると下から順番に読み込んでしまい、内部ストレージのパスであるstorage/emulated/0を読み込まなくなるので避けた方が無難です。Android5.0~7.0までは一番上のパスを呼んでくれるのですが、Android8.0は賢くないのか下から順番に探してくるみたいです。なのでAndroid8.0からの新しめのアプリを作る若しくはAndroid8.0向けにアップデートを考えているエンジニアさんは気をつけてくださいね。

これが正しい例↓

<pre><?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="storage/emulated/0" path="."/>
</paths>

これが避けた方が良い例↓

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="storage/emulated/0" path="."/>
<external-path name="storage/sd" path="."/>
</paths>

真っ当にリファレンスを読んでいればこんなことには遭遇しないと考えているので、今回は完全に自分向けの話題になってしまいました。まだストレージに関する全ての流れを把握した訳ではないので、しばらくはディレクトリ関係の話題が続きそうです・・・!

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

【Cordova】画像をトリミングできるプラグイン「cordova-plugin-crop」

今回は、画像加工のための Cordova プラグインについてご紹介。
画像のトリミングができる「cordova-plugin-crop」というプラグインです。
私はアルバムやカメラで撮影した写真を正方形に切り抜きたかったので、今回導入してみました。

導入にあたって、参考にさせていただいた記事はこちら。

Cordova – カメラを使用してクリックするか画像を選択した後、画像をトリミングします。|cordova tutorial
https://riptutorial.com/ja/cordova/example/23783/カメラを使用してクリックするか画像を選択した後-画像をトリミングします-

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

GitHub – jeduan/cordova-plugin-crop: Crop an image in Cordova
https://github.com/jeduan/cordova-plugin-crop

 

導入方法は、まずプラグインを下記コマンドでインストールします。

cordova plugin add --save cordova-plugin-crop

その後、下記のコードを画像トリミングをしたいタイミングで実行します。

plugins.crop(function success () {
  // トリミング成功時の処理
}, function fail () {
  // トリミング失敗時の処理
}, '[トリミングしたい画像パス]', { quality: 100 });

{ quality: 100 } はトリミングする際のオプションで、下記の3つがあります。

  • quality:画像の品質(Default:100)
  • targetWidth:トリミング後の画像の幅(Default:-1)
  • targetHeight:トリミング後の画像の高さ(Default:-1)

上で紹介した参考サイトでは、カメラプラグインと組み合わせて、撮影した写真を正方形にトリミングしていました。
そのコードはこちら。
一部オプションの値を修正したり、カメラ撮影をアルバムからの写真選択に変更したりしています。

navigator.camera.getPicture(onSuccess, onFail, {
    sourceType: window.navigator.camera.PictureSourceType.PHOTOLIBRARY,
    quality: 100,
    destinationType: Camera.DestinationType.FILE_URI,
    saveToPhotoAlbum: true,
    encodingType: window.navigator.camera.EncodingType.PNG,
});
function onSuccess(imageData) {
    plugins.crop(function success (data) {
        var image = document.getElementById('[撮影した写真を表示するimgタグのID]');
        image.src = data;
    }, 
    function fail () {
        // トリミング失敗時の処理
    }, imageData, {quality: 100, targetWidth: 200, targetHeight: 200});
}
function onFail(message) {
    // 写真撮影失敗時の処理
}

上記を実行したところ、写真選択後、トリミングの処理が実行されました!
が、写真選択からトリミング処理の画面が表示されるまでに少し時間がかかります。
このままだと少々ストレスになるので、ローディング画像を表示したり、そもそも起動を早められないか、調べてみたいと思います。

 

以上、画像のトリミングを行えるプラグイン「cordova-plugin-crop」についての紹介でした。
導入はとても簡単なので、是非ご活用ください。

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

テレビでもラジオでもない放送形態 i-dio (アイディオ)音楽好きにはうれしいサービスかもしれない。

TVでもラジオでもない、第三の放送形態として、”i-dio”というサービスが始まっているのをご存知でしょうか。

i-dio


新放送サービス『i-dio』は、地上アナログテレビ放送終了後に空いた周波数帯 (VHF-Low帯=99MHz~108MHz)を利用して創設された、既存のテレビでもラジオでもない全く新しい”第3の放送”です。受信機をお持ちであれば、契約などは原則必要ありません(今後有料サービスが個別に提供されることがあります)。
「i-dio」は、映像・音響・データなど、デジタルデータなら何でも送ることが可能です。また放送波で送信するため、通信とは異なり、輻輳もなく、不特定多数に情報を送ることができます。好きなときにコンテンツを楽しむことが出来る、蓄積型放送も予定しています。

http://www.i-dio.jp/service/

ということで、はじめからデジタルデータで送信することを前提にしており、映像も音声も送ることができ、なおかつ音声放送は高音質で送ることも可能とのことです。

なお、現在は音楽を中心としたコンテンツを配信するチャンネルが多いようです。

i-dioを受信するには専用のチューナーが必要ですが、現時点で既に(Radikoのような) サイマル放送も行わており、専用アプリからインターネット回線を経由して放送を聞くことも可能なようです。

TS PLAY by i-dio

TS PLAY by i-dio

VIP Co.,Ltd.無料posted withアプリーチ

従来の浜松で聞けるラジオ放送のうち、音楽メインのチャンネルといえば平日の”ラジオ日経第二”ぐらいしかなかったので、音楽好きにとってはありがたいサービスかもしれません。

興味のある方は一度試してみてはいかがでしょうか。

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

【Cordova】「Error initializing Network Connection: Class not found」エラーの対処法

現在開発中のアプリで発生したエラーです。
なお、発生したのは Android でした。
iOS でも発生しているかどうかはまだ未確認です。
恐らく、作業の最中にいくつかの不要なプラグインを削除したのですが…どうやら使用していたものも一緒に削除してしまったのが問題だったようです。

エラーは「Error initializing Network Connection: Class not found」というもので、翻訳結果は「ネットワーク接続の初期化エラー:クラスが見つかりません」とのことでした。

 

今回のエラーの対処方法については、こちらの投稿を参考にさせていただきました。

cordova – Android Phonegap 2.2 Network Connection: Class Not Found – Stack Overflow
https://stackoverflow.com/questions/14879438/android-phonegap-2-2-network-connection-class-not-found

この記事によると、プラグイン「cordova-plugin-network-information」を追加するとのこと。
…そういえば、不要プラグインを削除した時に一緒に消えていましたね…。

こちらのプラグインを追加するには、下記のコマンドを実行します。

cordova plugin add cordova-plugin-network-information

また、プラグインの GitHub ページはこちらから。

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

プラグインの追加が完了したら、あとはプロジェクトをビルドし実行してください。
私の環境では、エラーも消え、問題なくアプリを実行することができました。

 

以上、「Error initializing Network Connection: Class not found」エラーの対処法でした。
皆様も、プラグインの不用意な削除にはお気を付けください。

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