著者アーカイブ 村上

村上 著者:村上

【Android】「Configuration on demand is not supported by the current version of the Android Gradle plugin since you are using Gradle version 4.6 or above.」の対処法

今回も、Android Studioでアプリを開発中に遭遇したエラーについてです。
最近、何だかエラー遭遇率が妙に高い気が…。
特に、変なところをいじってはいないはずなので、気のせいだと良いのですが。

さて、今回のエラーはこちら。

Configuration on demand is not supported by the current version of the Android Gradle plugin since you are using Gradle version 4.6 or above.

先日まで動いていはずなのですが、今日起動してビルドしようとしたところ、上記のようなエラーが出ました。
こちらをGoogle翻訳に掛けた結果は、「Gradleバージョン4.6以上を使用しているため、Android Gradleプラグインの現在のバージョンではオンデマンドでの設定はサポートされていません。」とのこと。
どうやらサポートされてない設定を使っているようでした。
…なぜ急に?

 

で、調べたところ下記の記事がヒットしました。

Configuration on demand is not supported by the current version of the Android Gradle plugin – Stack Overflow
https://stackoverflow.com/questions/49990933/configuration-on-demand-is-not-supported-by-the-current-version-of-the-android-g

この記事によると、まず、gradle.properties で指定している「org.gradle.configureondemand」という記述を削除します。
が、上記に該当する記述は見つからず…一旦、置いておくことに。

そして次に、Setting から、Build, Execution, Deployment > Compiler を開きます。

そうすると、下の方に「Configure on Demand」という箇所があるので、ここのチェックを外します。
上の画像だと、赤枠で囲っている場所です。
あとは、Apply を押してから、OKを押せば設定は完了です。
その後、いつも通りビルドを行ったところ、問題なくビルドが成功し、無事にアプリも実行できました。

 

以上、「Configuration on demand is not supported by the current version of the Android Gradle plugin since you are using Gradle version 4.6 or above.」エラーの対処法でした。
エラー文だけでは意味が分からなかったのですが、案外あっさりと解決できたので良かったです。
自分が書いたコード以外のところでエラーが出ると若干ヒヤッとしますね…。
もし同じエラーでお困りの方がいらっしゃいましたら、参考にしていただければと思います。

村上 著者:村上

【React】「react-router」でLinkタグを使わないページ遷移の方法

昨日の記事に引き続き、今回もReactでのページ遷移の方法について。
前回は、Linkタグでのページ遷移について書きましたので、今回は関数内でのページ遷移方法についてです。

ちなみに、前回の記事はこちらから。

【React】「react-router」でのページ遷移の実装方法

 

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

react-routerのページ遷移をhandleで行う時にはwithRouterを使う – Qiita
https://qiita.com/junara/items/a4a98c27dc23fd53ebb9

ベースとなるページは前回の記事で作成したものを、ほぼそのまま流用します。

import React from 'react'
import { BrowserRouter, Route, Link } from 'react-router-dom'
import Detail from './Detail'
 
const App = () => {
  return (
      <BrowserRouter>
        <div>
            <ul>
                <li><Link to='/'>Home</Link></li>
                <li><Link to='/about'>About</Link></li>
                <li><Link to='/friends/10'>Friends</Link></li>
                <li><Link to='/detail'>Detail</Link></li>
            </ul>
            <hr />
 
            <Route exact path='/' component={Home} />
            <Route path='/about' component={About} />
            <Route path='/friends/:ids' component={Friends} />
            <Route path='/detail' component={Detail} />
        </div>
    </BrowserRouter>
  );
}
 
const Home = () => (
  <div>
    <h2>Home</h2>
    Homeページです
  </div>
)
const About = () => (
  <div>
    <h2>About</h2>
    Aboutページです
  </div>
)
const Friends = ({ match }) => (
  <div>
    <h2>Friends</h2>
    Friendページです{match.params.ids}
  </div>
)
export default App

追加しているのは、Detailページとそのページへのリンクです。

そして、そのDetailのページがこちら。

import React from 'react';
import { withRouter } from 'react-router';

class Detail extends React.Component {
  handleToAboutPage = () => {
    this.props.history.push('/about')
  }

  render() {
    return (
      <div>
        <button onClick={this.handleToAboutPage}>
          aboutページへ
        </button>
      </div>
    )
  }
}

export default withRouter(Detail)

こちらはAboutページへ遷移するためのボタンが表示されたページです。

上記のコード通り、関数でページ遷移を行うときは、6行目の this.props.history.push([遷移先ページ]) を使います。
ポイントは、最後のexport defaultで指定している Detail を withRouter で囲っている点です。
ページ遷移を実装するときには、こちらの処理が必要になります。
なお、今回別ファイルでDetailページを作成したので、ベースとなるページの3行目にある通り、Detailページを import する作業をお忘れなく。

 

以上、Linkタグを使わずに、関数内でページ遷移を行う方法でした。
ただ、サンプルコードをそのままコピーしただけなので、ベースのページとは少し書き方が違っています。
ベースページでは、const を使っていますが、Detailページでは class を使っているんですよね。
Detailページもベースに合わせたいのですが、書き方が違うのか、const で宣言すると、エラーになってしまい…只今修正中です。
それとも、この書き方でなければいけない何かがあるのかも?
とりあえず、引き続き調査したいと思います。

村上 著者:村上

【React】「react-router」でのページ遷移の実装方法

今回はタイトルにもある通り、CordovaとReactで作成しているアプリにページ遷移を導入する方法についてです。
流石に1ページだけではアプリらしくないですからね。

なお導入方法について、参考にさせていただいた記事はこちら。

react-router@v4を使ってみよう:シンプルなtutorial – Qiita
https://qiita.com/m4iyama/items/b4ca1773580317e7112e

 

さて、導入ですが、まずは下記のコマンドで react-router-dom をインストールします。

npm install react-router-dom

事前準備はこれだけ。
あとは、実際にコードを書いていきます。

import React from 'react'
import { BrowserRouter, Route, Link } from 'react-router-dom'

const App = () => {
  return (
      <BrowserRouter>
        <div>
            <ul>
                <li><Link to='/'>Home</Link></li>
                <li><Link to='/about'>About</Link></li>
                <li><Link to='/friends/10'>Friends</Link></li>
            </ul>
            <hr />

            <Route exact path='/' component={Home} />
            <Route path='/about' component={About} />
            <Route path='/friends/:ids' component={Friends} />
        </div>
    </BrowserRouter>
  );
}

const Home = () => (
  <div>
    <h2>Home</h2>
    Homeページです
  </div>
)
const About = () => (
  <div>
    <h2>About</h2>
    Aboutページです
  </div>
)
const Friends = ({ match }) => (
  <div>
    <h2>Friends</h2>
    Friendページです{match.params.ids}
  </div>
)
export default App

ちなみに、上記のファイルを実際に画面に表示しているのはこちらのコードです。

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';  // 上記のコードが書かれたjsファイル

ReactDOM.render(
    <App />,
    document.getElementById('root')
);

ほぼサンプルコードのままですが、動作を理解するにはぴったりです。
まず、 BrowserRouterタグで一番外側を囲い、Routeタグで表示させたいページとそのURLを指定しています。
リンクについては、Linkタグを使います。
こちらは、HTMLのaタグとイメージが近いと思います。

また、ページ遷移をした際、値を渡すことも可能です。
11行目のfriendsページへのリンク先のように、ページ名の後に /[値] と指定します。
また、16行目のように、URLから値を受け取れるようにします。
そして、受け取った値は、34行目からのFriendsページで取得・表示をしています。
今回は、値を表示させているだけですが、値によって表示するデータを変えるなどの処理が行えます。

基本的なことは、以上が分かっていれば問題なく実装できるかと思います。

 

以上、react-routerでページ遷移を実装する方法でした。
次回は、Linkタグを使わずに、関数内でページ遷移する方法についてご紹介できればと思います。

村上 著者:村上

【Android】「error: resource android:attr/fontVariationSettings not found.」の対処法

今回もAndroidをビルドした際のエラーについて。
最初、ログには「AAPT2 error」としか表示されなかったので、全く意味が分からなかったのですが、詳細を表示したところ、「error: resource android:attr/fontVariationSettings not found.」とのエラーだということが分かりました。
こちらのエラー文によると、「android:attr/fontVariationSettings」というリソースが見つからないという事でしたが、そもそもそんな場所を触った記憶もなく…。

 

で、エラー文で検索をかけたところ、こちらの記事が参考になりました。

android studio 3.0.1 で AAPT2 error が出た時の対応 – Qiita
https://qiita.com/kako351/items/7775157358aaf00da6f9

こちらの記事によると、アプリの build.gradle に、下記を追加して再ビルドすれば良いとのことでした。

configurations.all {
    resolutionStrategy {
        force 'com.android.support:support-v4:27.0.2'
    }
}

試したところ、私の環境でも問題なくビルドが成功しました!

他にも、gradle.properties ファイルに、下記を追加するという方法もあるようでしたが、投稿者の環境ではこの方法では解決しなかったとのことです。

android.enableAapt2=false

たしか、私の環境でも、こちらは意味がなかったような記憶があります。

なので、まずは build.gradle への記述をお試しすることをおすすめします。

 

以上、Android Studio のエラー「error: resource android:attr/fontVariationSettings not found.」の対処法でした。
なお、エラーログに具体的なエラー内容を表示させる方法については、こちらの記事を参考にしてください。

【Android Studio】「Compilation failed to complete」エラーの対処法
https://cpoint-lab.co.jp/article/201809/【android-studio】「compilation-failed-to-complete」エラーの対処法/

Android Studioのエラーって、たまに良く分からないものとかがあったりするので、こうして詳細を表示するように設定しておくと、エラーの種類よっては原因が分かったりすることもあります。

村上 著者:村上

【Android】「No toolchains found in the NDK toolchains folder for ABI with prefix: mipsel-linux-android」エラーの対処法

タイトルにある通り、Android Studioで発生したエラーの対処法についてです。
エラー文はこちら。

No toolchains found in the NDK toolchains folder for ABI with prefix: mipsel-linux-android

NDKツールチェーンフォルダに必要なファイルが足りないことが原因のようでした。

 

今回エラー解消で参考にさせていただいた投稿はこちらから。

“No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el-linux-android”・Issues #15・google/filament・GitHub
https://github.com/google/filament/issues/15

この中に、AndroidのDeveloperサイトから、NDKをダウンロードしてきて、それを適切な場所に置く、という対処法があり、こちらを行いました。

まず、下記から自分の環境に対応したパッケージをダウンロードします。

NDK のダウンロード|Android NDK|Android Developers
https://developer.android.com/ndk/downloads/?hl=zh-en


私の場合は、「Windows 64 ビット」のパッケージをインストールしました。
ただ、サイズが 700MB くらいあるので、少し時間がかかります。
ダウンロードが完了したら展開しておきましょう。

次に、Android SDKのある場所を開きます。
私のWindows環境では、C:\Users\[ユーザー名]\AppData\Local\Android\sdk でした。
そこにある ndk-bundle フォルダの中の、さらに toolchains フォルダを開きます。

そのフォルダ内に、mips64el-linux-android-4.9mipsel-linux-android-4.9 が足りていなかったため、ダウンロード・展開をしたファイルからその2つをコピーします。

あとは、Android Studio に戻って、再ビルド(もしくは Try Again)を実行します。
私の場合は、これでビルドが完了しました。

 

以上、「No toolchains found in the NDK toolchains folder for ABI with prefix: mipsel-linux-android」というエラーの対処法でした。
こういう、ファイルが足りない系のエラーって面倒ですね…。
が、何とか解決できてよかったです。
もし同じ状況に陥った場合は、是非参考にしてみてください。

村上 著者:村上

【Corodva】Android端末で実行した時に変更内容が反映されない時の対処法

昨日投稿した 【Android】Create React AppとCorodvaで作成したAndroidアプリにプラグインが追加できない時の対処法 の内容とも少し関わってくるのですが、Create React AppとCorodvaで作成したアプリが、何故かAndroidでだけ変更内容が反映されないという状況に陥ったので、その対処法についてです。
この現状が起こるのはAndroidだけで、BrowserとiOSについては何の問題もなく、変更内容が反映されていて…。
原因が分からず、かなり苦しめられました。

 

さて、解決方法ですが、何てことはなく、単にパッケージもしくはプラットフォームのバージョンが新しすぎたせいでした。
今回、アプリの環境をつくるにあたり、Cordovaのバージョンを 7.1.0 から 8.0.0 にアップデートしたのですが、それが原因のようです。
もしくは、Android自体のバージョンが高すぎたのかもしれませんが…とにかく、バージョンが新しすぎて、Androidのファイルが正しく作られていませんでした。
そのため、cordova buildなどの Cordovaのコマンドが正常に働いていなかったのかもしれませんが…エラーが表示されなかったので、発見がかなり遅くなりました。
バージョンに思い至ったのも偶然だったので、もしかしたらこれ以上に解決まで時間が可能性もあり…ぞっとしませんね。

ということで、Cordovaのバージョンを、以前と同じ 7.1.0 に戻したところ、あっけなく変更箇所がアプリに反映されました。
さらに、昨日紹介したプラグインが正常にインストールされない問題についても、バージョンを下げてプラットフォームを再インストールしたところ、必要なファイルが正常に作成されたため、特に修正する必要もなくインストールに成功しました。
…容易にバージョンを上げないようにしなければ…!

 

以上、Cordovaで変更した内容が反映されないときの対処法でした。
とりあえずは、パッケージのバージョンは容易に上げないようにすべきですね…。
古すぎるのもまずいとは思いますが、新しすぎでも問題のようですので、最新より1つ下のバージョンくらいがちょうどいいのかもしれません。
皆様もバージョンによる不具合には十分お気を付けください。

村上 著者:村上

【Android】Create React AppとCorodvaで作成したAndroidアプリにプラグインが追加できない時の対処法

長いタイトルですが、本日これが起こったので、自分のための備忘録として対処法をまとめます。

開発環境は、Create React App と Cordovaを使っています。
こちらについては、下記の記事のとおりに作成しましたので、ご参考ください。

Create React App & Cordovaでアプリをつくる環境を整える 2018年4月時点 – Qiita
https://qiita.com/bathtimefish/items/113154e89650b351b5b7

 

さて、本題のプラグインの追加ですが、まず追加したいプラグインは下記の2つです。

・https://github.com/petermetz/cordova-plugin-ibeacon
・https://www.npmjs.com/package/cordova-plugin-bluetooth-serial

が、この2つを追加したところ、cordova build android が動かなくなる状況に…!

エラー文によると、androidディレクトリ以下の ressrc、そして AndroidManifest.xml が何故かつくられていないことが原因でした。
そのため、対処法としてはまず一旦プラグインを削除し、Androidのプラットフォームを削除・再作成を行いました。

で、その時点でビルドを行い、正常にビルドが完了するかを確認しました。
この時点では問題なかったのですが、エクスプローラでファイルを確認してみると、やはり res、src、AndroidManifest.xml がない…。
なので、他のCordovaの環境から、上記ファイルをコピー&ペーストして、package名や、ディレクトリ構造をコピー先の環境に合わせるというアナログな手法を取ってみました。
その後、再度プラグインを入れ直したところ、どうやら正常にインストールできた模様。
そして、最後に再度ビルドを行いましたが、今度は正常に完了しました!
試しに実機を接続して、cordova run androidを実行してみましたが、こちらも正常に実行され、問題なくアプリが起動しました!

 

ということで、凄くアナログな方法ではありますが、この方法で何とか無事にプラグインの導入が完了しました!
…アナログだろうが動けばいいんです…!
もし同じようなヵ所でお困りの方がいらっしゃいましたら、良ければ参考にしてください。

村上 著者:村上

【Android】画像のExif情報から緯度・経度を取得する方法

先日ご紹介した、写真のExif情報から写真の向きを取得する方法に続き、今回は位置情報を取得する方法についてです。
なお今回も、「ExifInterface」というライブラリを使っています。

ちなみに、以前紹介した写真の向きの取得方法についてはこちらの記事から。

【Android】写真のExif情報から写真の向きを取得する方法
https://cpoint-lab.co.jp/article/201809/【android】写真のexif情報から写真の向きを取得する方法

 

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

// 写真から緯度経度を取得
File f = new File([画像のファイルパス]);
Uri uri = Uri.fromFile(f);
InputStream in = null;
try {
    in = getContentResolver().openInputStream(uri);
    ExifInterface exifInterface = null;
    if (in != null) {
        exifInterface = new ExifInterface(in);
        String latitude = exifInterface.getAttribute(ExifInterface.TAG_GPS_LATITUDE);
        String longitude = exifInterface.getAttribute(ExifInterface.TAG_GPS_LONGITUDE);
        String latitudeRef = exifInterface.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF);
        String longitudeRef = exifInterface.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF);
        // 緯度経度の値を変換
        Double lat = ExifLatitudeToDegrees(latitudeRef, latitude);
        Double lng = ExifLongitudeToDegrees(longitudeRef, longitude);
    }
} catch (IOException e) {
    e.getStackTrace();
    Log.e("ExifActivity", e.getMessage());
}

取得できた緯度経度は、それぞれ lat変数、lng変数に代入されています。
が、この関数では、緯度経度が度分秒という60進数で表現されています。
そのため、場合によってはこの値を10進数に変換する必要があります。

変換はこちらの関数を使いました。
参考サイトのURLをメモしておくのを忘れてしまいました…。
第一引数に、北緯・南緯、もしくは東経・西経を指定し、第二引数に緯度もしくは経度の値を指定します。
上のコードでは、11行目と12行目でそれぞれ緯度経度を変換しています。

// 60進数を10進数に変換
private double ExifHourMinSecToDegrees(String exifhourminsec) {
    String hourminsec[] = exifhourminsec.split(",",0);
    String hour[] = hourminsec[0].split("/",0);
    String min[] = hourminsec[1].split("/",0);
    String sec[] = hourminsec[2].split("/",0);

    double dhour = (double)Integer.parseInt(hour[0]) / (double)Integer.parseInt(hour[1]);
    double dmin = (double)Integer.parseInt(min[0]) / (double)Integer.parseInt(min[1]);
    double dsec = (double)Integer.parseInt(sec[0]) / (double)Integer.parseInt(sec[1]);
    double degrees = dhour + dmin / 60.0 + dsec / 3600.0;

    return degrees;
}

// 緯度の変換
private double ExifLatitudeToDegrees(String ref, String latitude) {
    return ref.equals("S") ? -1.0 : 1.0 * ExifHourMinSecToDegrees(latitude);
}

// 経度の変換
private double ExifLongitudeToDegrees(String ref, String longitude) {
    return ref.equals("W") ? -1.0 : 1.0 * ExifHourMinSecToDegrees(longitude);
}

 

以上、写真から位置情報を取得する方法でした。
なお、当然ですがExifに位置情報が保存されていなければ取得できません。
その場合は、現在の位置情報を取得するなり、もしくは「位置情報を取得できませんでした」というメッセージを取得するなどの処理を追加するほうが良さそうですね。
このあたりはお好みで実装してください。

村上 著者:村上

【Android】写真のExif情報から写真の向きを取得する方法

タイトル通り、今回は写真の Exif 情報を取得する方法についてです。
ちなみに Exifとは、デジカメやスマートフォンで撮影した画像データに、撮影条件に関するメタデータを追加して保存できる、画像ファイル形式の規格のことをいいます。
例えば、撮影日時とかカメラの機種、カメラの向きなどが保存されています。

で、AndroidでExifを扱うときには、ExifInterface というサポートライブラリを利用します。

Android Developers Blog: Introducing the ExifInterface Support Library
https://android-developers.googleblog.com/2016/12/introducing-the-exifinterface-support-library.html

 

さて、使い方ですが、まず build.gradle に下記を追加します。

implementation "com.android.support:exifinterface:26.1.0"

追加する場所は dependencies{} の中です。
build.gradle を変更すると、Sync Now というリンクが表示されるので、これをクリックします。
エラーが表示されなければ、無事にライブラリが追加できました。

あとは、Activityにコードを追加してきます。

File f = new File([画像のファイルパス]);
Uri uri = Uri.fromFile(f);
int orientation = 1;
InputStream in = null;
try {
    in = getContentResolver().openInputStream(uri);
    ExifInterface exifInterface = null;
    if (in != null) {
        exifInterface = new ExifInterface(in);
        orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);
    }
} catch (IOException e) {
    e.getStackTrace();
    Log.e("ExifActivity", e.getMessage());
} finally {
    if (in != null) {
        try {
            in.close();
        } catch (IOException ignored) {
        }
    }
}

結果は orientation という変数に入ります。
もし正常だったら 1 の値が入りますが、左に90度回転していた場合は 6 が、右に90度回転していた場合は 8 が、180度回転していた場合は 3 が入ります。
これに関しては、下記の記事を参考にしました。

iPhoneからアップロードしたJPEG写真が横向きになる問題(EXIF, Orientation)
https://qiita.com/RichardImaokaJP/items/385beb77eb39243e50a6

 

画像の回転については、以前紹介したこちらの記事を参考にしてください。
【Android】ImageViewの画像を180度回転させる方法
https://cpoint-lab.co.jp/article/201809/【android】imageviewの画像を180度回転させる方法/

 

以上、Exifから画像の向きを取得する方法でした。
次回は、位置情報の取得について説明できたらと思います。

村上 著者:村上

【アプリ】写真加工機能を手軽に実装できる「Adobe Creative SDK」

まだAndroidに導入途中なので、詳しい実装方法はご紹介できないのですが、まずはこんな便利なサービスがあるというご紹介まで。

写真にフィルターをかけたり、スタンプを押したりできる無料のSDKが、Adobeから提供されています。
サービス名は、タイトルにある通り「Adobe Creative SDK」です。
公式サイトはこちらから。
Adobe Creative SDK
https://www.adobe.io/apis/creativecloud/creativesdk.html
Androidだけでなく、iOSやWebにも対応しています。
Web版だけは試したことがありますが、とても簡単でした!

なお、こちらの記事も参考になりますので、ぜひご覧ください。
https://qiita.com/84d010m08/items/566415df1914ca097082
https://qiita.com/84d010m08/items/566415df1914ca097082

 

こちらのサービスを使うにはアカウント登録とアプリ登録が必要なので、今回はそちらをご紹介。
まずAdobeアカウントを、Adobeの公式サイト右上のログインから作成してください。

アドビ公式サイト:クリエイティブ、マーケティング、文書管理ソリューション
https://www.adobe.com/jp/

アカウントがすでにある人は、ログインしてください。

ログインで来たら、下記からコンソールに移動します。

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

そのページに「New Integration」というボタンがあるので、そこから新規のアプリを登録します。
なお、アプリ名などは後で変更できますので、ご安心を。
ちなみに、この登録だけではアプリストアでの公開ができないらしいので、テスト用ならOKですが、のちのち公開するなら審査を通してください。
この作業についても、このコンソール画面からできます。
スクリーンショットをとる手間などはありますが、審査自体は思ったよりもすんなり通りましたね。

 

各プラットフォームごとの導入方法については、下記のドキュメントを参考にしてください。

Documentation
https://www.adobe.io/apis/creativecloud/creativesdk/docs.html

 

以上、簡単ですが、Adobe Creative SDK についてでした。
Androidに導入が完了しましたら、改めて手順をまとめたいと思います。