コミュニティ電子化

2024年7月27日

課題

地域当番が広報冊子や地域情報(回覧板)を地域住民に配る。

今でも当たり前に行っている習慣ですが、

現在の通信技術や環境を考えると無駄な作業に感じてしまいます。

そろそろブラッシュアップのタイミングではないでしょうか?

紙を物理的に配布するコストの削減を目指します。

電子化の対象

・広報冊子

・地域情報

・市からの通達

電子化のメリット

・紙の削減(エコ、SDGs貢献)

・配送削減(ガソリン(CO2)、マンパワーの削減、SDGs貢献)

電子化のデメリット

・全ての人に行きわたらない(スマートフォンが必要)

・既存企業の経済の喪失

対策

・全てに人に行きわたらない

解決策)

スマートフォン貸与。

最安だと個人契約でも1台月額500円、デバイス1台0円~3000円。

大型契約だともっとディスカウントできるのではないか。

印刷代、配送代とのトレードオフ。

・既存企業の経済の喪失

解決策)

既存企業と提携して経済活動の代替を目指す(印刷 → ネットワーク管理)

構想

・システム構築

Webシステム、アプリの作成(dat&開発)

・展開

モデルエリア(理解の高いエリアと低いエリアの2地域)を設定して試験。

フィールバックして市全エリアに展開。

将来

・更なる電子化、市サービスとの連携

・他地域への横展開

・売り込み(管理費を収益源とする)

HTMLファイルを表示する

2024年7月15日

開発環境
OS:Windows 11
SDK:VS Code + Flutter 3.7.12

概要

アプリ内のローカルストレージに格納したhtmlファイルを画面に表示します。

WebViewウィジェットを準備する

HTMLファイルはWebViewウィジェットを通して表示します。

そのため、WebViewパッケージをインストールする必要があります。

サンプルプロジェクトを生成して動作確認してみます。

webview_flutterをインストールします。

HTMLファイルを準備する

次にHTMLファイルを準備します。

<!DOCTYPE html>
<html lang="ja">

  <head>
    <meta charset="UTF-8">
    <title>Top Page</title>
  </head>

  <script>
    function sendData1() {
      // Flutterへデータ送信
      sample.postMessage("1");
    }
    function sendData2() {
      // Flutterへデータ送信
      sample.postMessage("2");
    }
  </script>

  <body>
    <h1>Please tap a button.</h1>
    <br>
    <br>
    <button onclick="sendData1()">Send Data 1</button>
    <br>
    <br>
    <button onclick="sendData2()">Send Data 2</button>
  </body>
</html>

ボタンが2つあるHTMLファイル(top.html)を作成しました。

プロジェクトフォルダ内に「html」フォルダを作成し、その中に作成したhtmlファイルを格納します。

次にpubspec.yamlのassets項目にhtmlファイルを定義します。

  assets:
    - html/top.html

WebViewウィジェット実装

main.dartにWebViewウィジェットを追加します。

ネットワーク上のurlにアクセスして表示するわけではないため、htmlのロード処理もあわせて追加する必要があります。

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:webview_flutter/webview_flutter.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  late WebViewController controller;
  late Future<void> controllerInitialization;

  @override
  void initState() {
    super.initState();
    controllerInitialization = initController();
  }

  Future<void> initController() async {
    final html = await rootBundle.loadString('html/top.html');
    controller = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..addJavaScriptChannel('sample', onMessageReceived: (result) async {
          switch (result.message) {
            case "1":
              print("call 1.");
              break;
            case "2":
              print("call 2.");
              break;
          }
        })
      ..loadRequest(
        Uri.dataFromString(
          html,
          mimeType: "text/html",
          encoding: Encoding.getByName("utf-8"),
        ),
      );
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<void>(
      future: controllerInitialization,
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.done) {
          return Scaffold(
            appBar: AppBar(title: const Text("Test Page")),
            body: WebViewWidget(controller: controller),
          );
        } else {
          return const CircularProgressIndicator();
        }
      },
    );
  }
}

※Android向けのビルドが失敗した場合はこちら↓をチェックしてみてください。

動作確認

デバッグモードで起動しました。

HTMLのテキストと2つのボタンは期待通りに表示されています。

次にボタンを押し分けてみると・・・

ターミナルに「call 1.」、「call 2.」が表示されました。

ボタン操作も処理できることが確認できました。

今回は以上です。

ビルドエラー解消(JAVA_HOME)

2024年7月15日

開発環境
OS:Windows 11
SDK:VS Code + Flutter 3.7.12

概要

久しぶりにFlutterの動作確認をしようとサンプルプロジェクトを生成し、Android向けにビルドしたら失敗しました。

Android向けビルド時に発生したビルドエラーの解消方法についての話。

Flutter ビルドエラーの発生

サンプルプロジェクトを生成。

AndroidスマホをPCにUSB接続し、デバイスをチェック。

スマホのデバイスIDを取得し、デバイスIDを指定してデバッグ起動。

たったこれだけの手順でビルドエラーが発生してしまいました。

以前はビルドできたはずなんですが。。。

エラー内容は、以下。

環境変数「JAVA_HOME」に指定したディレクトリが存在しないってことのようです。

ということでディレクトリを見てみると・・・

ディレクトリ「jre」の直下はディレクトリ「bin」のみ。

そのディレクトリ「bin」の直下も.makerファイルのみと見事にもぬけの殻になっていました。

そういえば、最近、Android StudioのバージョンをFlamingoからIguanaにバージョンアップしたんだったっけ。。。

環境変数を編集する

ということでAndroid Studioの実体を探してみると・・・

環境変数を編集します。

Flutterビルドエラーの解消

ターミナルを立ち上げなおして再度、ビルドしてみます。

ビルドが成功し、スマホ上でサンプルアプリが起動しました。

今回は以上です。

com.google.android.play.coreの警告に対処する

2024年7月15日

開発環境
OS:Windows 11
SDK:Android Studio Iguana | 2023.2.1 Patch 1

概要

Google Play Consoleの受信トレイにcom.google.android.playに関する警告がきており、8月31日までに対処が必要とのことで対応しました。

警告を確認する

Google Play Consoleの受信トレイにcom.google.android.playに関する警告が届きました。

警告の内容を確認すると、

com.google.android.play.core(1.8.0)がAndroid 14(sdk 34)に対応できなくてアプリがクラッシュするため、それを回避するために8月31日までにライブラリの参照を変更しなさい。

とのことのようです。

com.google.android.play.coreって何に使ってたんだろうか?

com.google.android.play.coreの使用状況を確かめる

まずは警告が届いたアプリのソースコードを確認します。

Android Studioで立ち上げ、「com.google.android.play」で検索してみると・・・

検索の結果、In-App Reviewのモジュールがヒットしました。

import com.google.android.play.core.review.ReviewManagerFactory
import com.google.android.play.core.review.ReviewManager

build.gradleのライブラリを確認すると

今回の警告対象である「com.google.android.play:core-kt」が見つかりました。

 dependencies {

    implementation("com.google.android.play:core-ktx:1.8.1")

}

「com.google.android.play:core-kt」を削除してビルドしなおしてみるとReviewManagerのインポートで参照エラーがでました。

「com.google.android.play:core-kt」の代替ライブラリが必要のようです。

ライブラリを差し替える

改めてIn-App Reviewの実装方法を公式サイトで確認するとライブラリが変わっていました。

 dependencies {

    implementation 'com.google.android.play:review-ktx:2.0.1'

}

ということで「com.google.android.play:core-ktx」を「com.google.android.play:review-ktx」に変更し、ビルドしてみると・・・

これで警告の対応が完了です。

お疲れさまでした。

アプリにIn-App Reviewを組み込む

2024年7月15日

開発環境
OS:Windows 11
SDK:Android Studio Iguana | 2023.2.1 Patch 1

概要

AndroidアプリにIn-App Reviewを組み込みます。

In-App Review

In-App Reviewとはアプリの評価やレビューの入力を促すポップアップ機能です。

アプリの操作中に意図したタイミングでポップアップさせることができます。

アプリの評価やレビューはアプリの改善に役に立つため、In-App Reviewの実装はおススメです。

In-App Review実装の流れ

実装していきます。

まずはbuild.gradleにライブラリを組み込みます。

 dependencies {

    implementation 'com.google.android.play:review-ktx:2.0.1'

}

次に必要なモジュールをインポートします。

import com.google.android.play.core.review.ReviewManagerFactory
import com.google.android.play.core.review.ReviewManager

Activityの起動時にレビューマネージャーを生成します。

    private lateinit var reviewmanager : ReviewManager

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        reviewmanager = ReviewManagerFactory.create(this)

    }

あとは適当な場所(画面起動時やイベント終了後など)でポップアップ処理をコールします。

    val request = reviewmanager.requestReviewFlow()
    request.addOnCompleteListener { task ->
        if (task.isSuccessful) {
            val reviewInfo = task.result
            val flow = reviewmanager.launchReviewFlow(this@MapsActivity, reviewInfo)
            flow.addOnCompleteListener { _ ->

            }
        }
    }

In-App Reivewの実装は以上です。

デバッグ方法

デバッグをしたい場合、FakeReviewManagerを使用します。

FakeReviewManagerをインポートします。

import com.google.android.play.core.review.ReviewManagerFactory
import com.google.android.play.core.review.ReviewManager
import com.google.android.play.core.review.testing.FakeReviewManager

FakeReviewManagerを生成します。

    private lateinit var reviewmanager : ReviewManager

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

//        reviewmanager = ReviewManagerFactory.create(this)
        reviewmanager = FakeReviewManager(this)

    }

ポップアップ処理は変更不要です。

FakeReviewManagerのデバッグではポップアップは表示されず、正常系のシーケンスのみ確認できます。

ステップ実行してみるとrequestReviewFlowに成功し、launchReviewFlowがコンプリートします。

これでIn-App Reviewの組み込みは終了です。

お疲れさまでした。