ケツリカ(結論から理解)するFlutterでAndroid固有の機能を使う方法
どうやってFlutterでAndroid固有の機能を作るのか
なぜ、DartにMainActivity.ktをインポートする必要がないのか
固有の機能を含めたUIを構築
lib\main.dart
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(const MainApp());
}
class MainApp extends StatefulWidget {
const MainApp({super.key});
State<MainApp> createState() => _MainAppState();
}
class _MainAppState extends State<MainApp> {
static const platform = MethodChannel('samples.flutter.dev/battery');
// バッテリーレベルを格納する変数
String _batteryLevel = 'Unknown battery level.';
Future<void> _getBatteryLevel() async {
String batteryLevel;
try {
final result = await platform.invokeMethod<int>('getBatteryLevel');
batteryLevel = 'Battery level at $result % .';
} on PlatformException catch (e) {
batteryLevel = "Failed to get battery level: '${e.message}'.";
}
setState(() {
_batteryLevel = batteryLevel;
});
}
Widget build(BuildContext context) {
return MaterialApp(
home: Directionality(
textDirection: TextDirection.ltr,
child: Scaffold(
appBar: AppBar(
title: const Text('Battery Level'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: _getBatteryLevel,
child: const Text('Get Battery Level'),
),
Text(_batteryLevel),
],
),
),
),
),
);
}
}
kotlinでバッテリーを取得
android\app\src\main\kotlin\com\example\batterylevel\MainActivity.kt
package com.example.batterylevel
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import android.content.Context
import android.content.ContextWrapper
import android.content.Intent
import android.content.IntentFilter
import android.os.BatteryManager
import android.os.Build.VERSION
import android.os.Build.VERSION_CODES
class MainActivity: FlutterActivity() {
private val CHANNEL = "samples.flutter.dev/battery"
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {
// このメソッドはメインスレッドで呼び出されます。
call, result ->
if (call.method == "getBatteryLevel") {
val batteryLevel = getBatteryLevel()
if (batteryLevel != -1) {
result.success(batteryLevel)
} else {
result.error("UNAVAILABLE", "バッテリーレベルが利用できません。", null)
}
} else {
result.notImplemented()
}
}
}
private fun getBatteryLevel(): Int {
val batteryLevel: Int
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
val batteryManager = getSystemService(Context.BATTERY_SERVICE) as BatteryManager
batteryLevel = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
} else {
val intent = ContextWrapper(applicationContext).registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
batteryLevel = intent!!.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) * 100 / intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
}
return batteryLevel
}
}
解説
パッケージ宣言
package com.example.batterylevel
アプリケーションのパッケージ名を指定している。逆ドメイン形式で書かれ、アプリケーションの一意性を保つために使用される。
インポート文
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import android.content.Context
import android.content.ContextWrapper
import android.content.Intent
import android.content.IntentFilter
import android.os.BatteryManager
import android.os.Build.VERSION
import android.os.Build.VERSION_CODES
FlutterActivity: Flutterのメインエントリポイントで、Flutter UIが表示される場所。
FlutterEngine: Flutterのエンジンを管理し、Dartコードとネイティブコードのブリッジを提供する。
MethodChannel: Flutterとネイティブ(Android)間で通信するためのチャネル。
Context や Intent などのAndroid API: Androidデバイスのコンテキスト情報を取得したり、バッテリー情報を取得するために使用される。
クラス宣言
class MainActivity: FlutterActivity() {
private val CHANNEL = "samples.flutter.dev/battery"
FlutterActivityを継承することで、FlutterアプリがAndroidで正しく動くための基本的な機能をすぐに使えるようになり、特別な設定をしなくても、Dartで書いたコードがそのままAndroidの画面に表示されるようになる。
CHANNEL: MethodChannelの名前。この名前を使ってDartコードと通信する。
configureFlutterEngine メソッド
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {
call, result ->
if (call.method == "getBatteryLevel") {
val batteryLevel = getBatteryLevel()
if (batteryLevel != -1) {
result.success(batteryLevel)
configureFlutterEngine: Flutterエンジンを設定するためのメソッドで、FlutterActivityのライフサイクルに沿って呼び出される。
MethodChannel: Flutter側からこのチャネルを介して送信されるメッセージ(例: getBatteryLevel)を受け取り、それに応じた処理を行う。
バッテリー情報を取得するロジック
getBatteryLevel() というメソッドを呼び出して、デバイスのバッテリー情報を取得し、それをresult.successメソッドでFlutterに返す。
バッテリー情報が取得できなかった場合や何か問題があった場合、result.errorを呼び出してエラーメッセージをFlutterに送信する。
参考文献:
感想:参考文献はコードが意外と古いので自分なにりアレンジすると良いかもしれません。
Discussion