Android開発でJavaバージョンに関するビルドエラー

ビルドエラーの内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
> Could not resolve all files for configuration ':classpath'.
> Could not resolve com.android.tools.build:gradle:7.4.2.
Required by:
project :
> No matching variant of com.android.tools.build:gradle:7.4.2 was found. The consumer was configured to find a runtime of a library compatible with Java 8, packaged as a jar, and its dependencies declared externally, as well as attribute 'org.gradle.plugin.api-version' with value '7.5' but:
- Variant 'apiElements' capability com.android.tools.build:gradle:7.4.2 declares a library, packaged as a jar, and its dependencies declared externally:
- Incompatible because this component declares an API of a component compatible with Java 11 and the consumer needed a runtime of a component compatible with Java 8
- Other compatible attribute:
- Doesn't say anything about org.gradle.plugin.api-version (required '7.5')
- Variant 'javadocElements' capability com.android.tools.build:gradle:7.4.2 declares a runtime of a component, and its dependencies declared externally:
- Incompatible because this component declares documentation and the consumer needed a library
- Other compatible attributes:
- Doesn't say anything about its target Java version (required compatibility with Java 8)
- Doesn't say anything about its elements (required them packaged as a jar)
- Doesn't say anything about org.gradle.plugin.api-version (required '7.5')
- Variant 'runtimeElements' capability com.android.tools.build:gradle:7.4.2 declares a runtime of a library, packaged as a jar, and its dependencies declared externally:
- Incompatible because this component declares a component compatible with Java 11 and the consumer needed a component compatible with Java 8
- Other compatible attribute:
- Doesn't say anything about org.gradle.plugin.api-version (required '7.5')
- Variant 'sourcesElements' capability com.android.tools.build:gradle:7.4.2 declares a runtime of a component, and its dependencies declared externally:
- Incompatible because this component declares documentation and the consumer needed a library
- Other compatible attributes:
- Doesn't say anything about its target Java version (required compatibility with Java 8)
- Doesn't say anything about its elements (required them packaged as a jar)
- Doesn't say anything about org.gradle.plugin.api-version (required '7.5')

原因

Java のバージョンが合っていない

IDEの設定

Android Studio>Settings>Build,Execution,Deployment>Build Tools>Gradle>Gradle JKDでjava11を設定する
パスをコピーしておく

プロジェクト本体の設定

gradle.propertiesファイルにコピーしたパスを追記する。
例えば以下など

1
/Library/Java/JavaVirtualMachines/openjdk-11.0.1.jdk/Contents/Home

RailsにRedisを導入した際のメモ

redisライブラリの導入

Gemfileに以下を追加する。

1
2
gem 'redis'
gem 'hiredis-client'

Railsのキャッシュの設定

  • Railsのキャッシュのデフォルトの保存先はtmpファイルになっている(キャッシュストアの設定
  • Redisを使うように変更するには以下のようにする

対象ファイル:config.enveronments/production.rb

変更内容:

1
2
3
4
config.cache_store = :redis_cache_store, {
url: ENV['REDIS_URL'],
ssl: true, # この行はAmazon ElastiCache For Redisの場合のみ。ローカルのDocker開発環境の場合は不要
}

ENV['REDIS_URL']について

ENV['REDIS_URL']については、それぞれ以下のように設定する。

Amazon ElastiCache For Redis の場合

redis://hoge.serverless.apne1.cache.amazonaws.com:6379/0

ローカルのDocker開発環境の場合

redis://redis:6379/0

docker-compose.ymlに以下のように追記する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
web:
environment:
REDIS_URL: 'redis://redis:6379/0'
depends_on:
- redis

redis:
image: redis:latest
ports:
- "6379:6379"
volumes:
- redis-data:/data

volumes:
redis-data:
driver: local

キャッシュを利用するコード

上記の設定完了後、以下のコードでキャッシュが効くようになる。

1
2
3
4
5
6
key = "cache_count_" + params[:id]
result = Rails.cache.fetch(key, expires_in: 5.minutes) do
# キャッシュがなければここが実行される
count = get_count(params[:id])
count
end

と、基本的にはこれだけでOK。

注意点

  • Redisでは正規表現を使ってキャッシュを削除することができる
  • 例えばRails.cache.delete_matched('cache_count_*')
  • ただし、Amazon ElastiCache For Redis は正規表現を使ってキャッシュを削除することができない
  • Amazon ElastiCache For Redis はクラスター構成となっていて、キャッシュの保存先が分散されているため
  • 以下のエラーが発生する
  • CROSSSLOT Keys in request don't hash to the same slot

リストやハッシュをキャッシュする場合

  • 上記の設定では、キャッシュの対象は文字列のみ
  • リストやハッシュをキャッシュする場合は、$redisインスタンスを直接利用する必要がある

$redisの設定

config/initializers/redis.rbを作成し、以下のように記述する。

1
$redis = Redis.new(url: ENV['REDIS_URL'])

リストをキャッシュする場合

1
2
$redis.lpush('list_key', 'value')
$redis.lrange('list_key', 0, -1)

注意点

sslを有効にする場合、Rails.cacheではssl: trueのオプションがあったが、$redisではurlrediss://を指定する必要がある。
例えば、rediss://hoge.serverless.apne1.cache.amazonaws.com:6379/0とすると、sslが有効になる。

VuetifyのバリデーションをJavaScriptで実行する

html

1
2
3
4
5
<v-form ref="form">
<v-text-field
:rules="[rules.required]"
></v-text-field>
</v-form>

JavaScript

1
2
3
4
5
6
7
8
9
10
11
12
13
// バリデーション
let form = ref(null)
const rules = ref({
required: value => !!value || '',
})

const submit = async () => {
const validResult = await form.value.validate()
if (!validResult.valid) {
return
}
//以下、submitの処理
}

【kintone】プラグインアップロード時のタイムアウトエラー

kintone-plugin-uploaderコマンド実行時に以下のエラーが出ました。

エラーが発生しました TimeoutError: Waiting for selector .ocean-ui-dialog failed: Waiting failed: 60000ms exceeded

原因はplugin.zipの指定方法が間違ってました。

以下の通りに修正したらうまくいきました。

1
2
3
4
# 修正前
kintone-plugin-uploader plugin.zip
# 修正後
kintone-plugin-uploader dist/plugin.zip

言われてみればそうなのですが、エラーからは読み取りにくくて苦戦しました。。

Railsでアプリログのフォーマットを変更する方法

Railsでアプリログのフォーマットを変更する方法です。

以下の2ファイルを追加・修正します。

(追加)app/lib/local_dev_log_formatter.rb

1
2
3
4
5
6
7
class LocalDevLogFormatter < ActiveSupport::Logger::SimpleFormatter
def call(severity, timestamp, progname, msg)
formatted_severity = sprintf("%-5s", "#{severity}")
formatted_time = timestamp.strftime("%Y-%m-%d %H:%M:%S.") << timestamp.usec.to_s[0..2].rjust(3)
"[#{formatted_severity} #{formatted_time} ##{Process.pid}] #{msg}\n"
end
end

(修正)config/environments/development.rb

1
2
3
4
5
6
7
8
9
Hoge::Application.configure do

# 中略

config.log_formatter = LocalDevLogFormatter.new # 日時を出力するためにカスタムフォーマッターを指定
logger = ActiveSupport::Logger.new("log/#{Rails.env}.log", 5, 100 * 1024 * 1024)
logger.formatter = config.log_formatter
config.logger = ActiveSupport::TaggedLogging.new(logger)
end

app/lib配下に配置することとconfig.loggerの方にも設定が必要なところが分からなくてハマりました。。

Faraday::Error::ConnectionFailedエラーの解消

エラー

1
2
3
rake aborted!  
NameError: uninitialized constant Faraday::Error::ConnectionFailed
Did you mean? Faraday::ConnectionFailed

解決策

1
2
3
4
5
6
7
# cdする先のディレクトリは人によって違う。下のコマンドで確認できる。
# bundle show rails
cd /Users/hoge/.rbenv/versions/3.0.5/lib/ruby/gems/3.0.0/gems
grep -r "Faraday::Error::" .
sed -i '' 's/Faraday::Error::/Faraday::/g' ./elasticsearch-api-7.4.0/Rakefile
sed -i '' 's/Faraday::Error::/Faraday::/g' ./elasticsearch-transport-7.4.0/spec/elasticsearch/transport/client_spec.rb
sed -i '' 's/Faraday::Error::/Faraday::/g' ./elasticsearch-transport-7.4.0/lib/elasticsearch/transport/transport/http/faraday.rb

googleの翻訳APIをrailsで実行する方法

はじめに

googleの翻訳APIをrailsで実行する方法です。
APIキーを使えばjs側でも実行できますが、そうするとAPIキーがユーザーに漏れてしまうので、Railsなどのサーバーを経由するようにしましょう。

jsのコード

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
async translate(text) {
const url = '/translate';
try {
const response = await axios.post(url, {
text: text,
});

const data = response.data;
if (data.error) {
console.error('Error:', data.error);
return '';
} else {
return data.translation_text;
}
} catch (error) {
console.error('Error:', error.message);
return '';
}
},

Rails

gemインストール

Gemfileに以下の行を追加する

1
gem 'google-cloud-translate-v2'

ターミナルで以下のコマンドを実行する

1
bundle install

認証の設定

APIキーを利用することもできるのですが、gemライブラリを利用する場合はAPIキーではなく認証情報を利用する方法が便利です。

  1. GCPを開く
  2. API Managerを開く
  3. 認証情報を開く
  4. 対象のサービスアカウントをクリックもしくは新しく追加
  5. 「キー」タブからjsonをダウンロード
  6. プロジェクト直下にsecret_keyフォルダを生成
  7. secret_keyフォルダにjsonを配置する

参考
https://github.com/googleapis/google-cloud-ruby/blob/main/google-cloud-translate-v2/AUTHENTICATION.md

ルーティング

routes.rb

1
2
3
Rails.application.routes.draw do
post 'translate', to: 'google_api/translation#translate'
end

controllerのコード

  1. controllersフォルダの直下にgoogle_apiフォルダを作成する
  2. google_apiフォルダにtranslation_controller.rbファイルを作成する
1
2
3
4
5
6
7
8
9
10
11
12
13
require 'google/cloud/translate/v2'

class GoogleApi::TranslationController < ApplicationController
def translate
ENV["TRANSLATE_PROJECT"] = "hoge-project"
ENV["TRANSLATE_CREDENTIALS"] = "secret_key/hoge.json"
client = Google::Cloud::Translate::V2.new
translation = client.translate text, to: 'en'
render json: { translation: translation.text }
rescue Google::Cloud::Error => e
render json: { error: e.message }, status: :internal_server_error
end
end

【JavaScript】base64の画像をimgタグにセットする方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
async setImageToInput(base64Image, inputElement) {
// Base64形式の画像を<img>要素にセット
const img = document.createElement('img');
img.src = base64Image;

// 画像の読み込みを待つ
await new Promise((resolve) => img.onload = resolve);

// <img>要素の画像を<canvas>要素に描画
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);

// <canvas>要素の画像をBlobオブジェクトに変換
const blob = await new Promise((resolve) => canvas.toBlob(resolve));

// BlobオブジェクトをFileオブジェクトに変換
const file = new File([blob], 'image.jpg', {type: blob.type});

// FileオブジェクトをDataTransferオブジェクトに追加
const dataTransfer = new DataTransfer();
dataTransfer.items.add(file);

// DataTransferオブジェクトをinput要素のfilesプロパティにセット
inputElement.files = dataTransfer.files;

// changeイベントを明示的にトリガーする
inputElement.dispatchEvent(new Event('change'));
},

// input
const base64Image = document.getElementById(imgId).src;
const inputElement = document.getElementById('item_image');
this.setImageToInput(base64Image, inputElement).then(r =>
// セットした後の処理
);

ChromeDriverのバージョンエラー

エラー

1
2
session not created: This version of ChromeDriver only supports Chrome version 94
Current browser version is 96.0.4664.55 with binary path /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

原因

ブラウザのバージョンを上げたので、合わせてchromeDriverのバージョンを上げないといけないっぽい

解決策

1
brew upgrade chromeDriver

【mitmproxy】スマホ端末のネットワーク通信内容をパソコンで監視する方法

公式ページ
https://mitmproxy.org/

Macにmitmproxyをインストール

1
brew install mitmproxy

MacとAndroidで同じWi-fiに接続する

MacのWi-fiのIPアドレスを確認する
リンゴマーク>システム設定>ネットワーク>Wi-fi>詳細>TCP/IP>IPアドレス

Macで監視アプリを起動

1
mitmweb --web-port 10081 --listen-port 10080

Androidの設定>ネットワークとインターネット>対象のWi-fiの設定>プロキシを手動に変更する

  • プロキシのホスト名:MacのWi-fiのIPアドレス
  • プロキシポート:10080

Androidでhttp://mitm.it/にアクセスする
Androidの証明書をダウンロードする
設定>セキュリティ>詳細設定>暗号化と認証情報>証明書のインストール>CA証明書 から証明書をインストールする

Macでhttp://127.0.0.1:10081を開くとAndroidで通信した内容が表示される

Androidアプリを開発している場合はその設定も必要

AndroidManifest.xmlにnetworkSecurityConfigの行を追加する

1
2
3
<application
android:name=".Hoge"
android:networkSecurityConfig = "@xml/network_security_config">

app/src/main/res/xml/network_security_config.xmlを作成する

1
2
3
4
5
6
7
<network-security-config>
<debug-overrides>
<trust-anchors>
<certificates src="user" />
</trust-anchors>
</debug-overrides>
</network-security-config>

参考
iOS 14 端末での mitmproxy 設定方法
AFNetworkingのリクエストでCookieを扱う方法
MITMProxy - Set up Android Devices

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×