投稿

Androidアプリ「こえめと-声で操作するメトロノーム」を公開しました

「こえめと」は、楽器を両手で持ったまま、声で操作できるメトロノームです。  現在、GooglePlayでオープンテストという形で公開しています。アプリ(Androidのみ)は次からダウンロードできるので、興味のあるかたは使ってご意見等をお寄せください。 https://play.google.com/store/apps/details?id=mashro.com.wixsite.mashro.km03  趣味でアプリを作っているアマチュアなので、最小限の機能のみ搭載したシンプルな作りですが、それがかえって使いやすいように思います。  (その後、全面公開としました。また紹介動画をYouTubeにアップしました。) https://www.youtube.com/watch?v=cYpEThvyyZI 【特徴】 ・30~300の数字を言うとそのテンポでメトロノームが始動し、「止まれ」というと止まる。 ・図形が回転し、視覚的にもテンポをつかみやすい。 ・市販電子メトロノーム並みの精度(時間間隔の誤差の標準偏差±0.15%)。 ・無料で広告もなし。データの保存も外部送信もないのでプライバシーの問題もなし。 ・私自身、チェロの練習に使っているが、結構役立つと思う。 ・メトロノーム自体の音で音声認識が邪魔されることがあるので、外部スピーカーかイヤホン等を推奨するが、それらがなくても使える。 -------------------- 開発の経緯  1年半ほど前からチェロを習い始め、練習のたびにメトロノームアプリを使うのだが、スタートやストップ、テンポの変更をするたびに弓を置いて操作しなければならないのが煩わしかった。楽器を持ったままで音声で操作できるメトロノームくらいあるだろうと探してみたが、見当たらない。そこで、自分で作ることにした。 音声認識  まず、音声認識である。Androidには、SpeechRecognizerというクラスがあって、これを使うと簡単に音声認識できるらしい。 https://qiita.com/kaleidot725/items/8fe6b6f137a9a8710d21  こういったサイトを参考にして自分でやってみると、確かに簡単に、音声を文字にすることができた。ただし「ボタンをタップして音声入力する」という使い方しかできず、「ずっと待機状態にしていて...

超初心者の機械学習入門

イメージ
目的  自分の撮影した写真をもとにして、スマホで画像を判別するアプリを作る --------------------- 概要 ・スマホを使った画像分類の方法を教えてくれるサイトがいくつかあるが、その多くは既存の画像データセットを用いたものである。ここでは、自分の撮影した写真を教師データとして、画像の判別アプリを作る。 ・この方法を使えば、独自の視点から画像を判別するアプリを作ることができる。例えば、家族の一人にスマホを向ければ誰であるか答えるアプリや、子どもの絵とピカソの絵を区別するアプリなどを作ることができる。 ・ここで行うのは、TensorFlow Liteの形式で機械学習モデルを作り、これを組み込んだスマホ(ここではAndroid)のアプリを作ることである。 ・TensorFlow Liteの形式でモデルを作るための比較的簡易なやりかたとして、TensorFlow  Model Maker というライブラリを使う方法があったが、2024年3月現在、これは(普通のやり方では)使えない。TensorFlow のモデルをつくるには、少なくとも初心者は別の方法を使ったほうがいい。私は書籍に従ってKerasで作成した。Model Maker の代わりにMediaPipe Model Makerを使うと良いと言われているが、私はまだこのやり方でうまくいっていない。 ・上記モデルを組み込んだアプリを作る方法を非常に親切に教えてくれるサイトがある。その通りに入力しても動かないが、わずかの手直しで画像を分類するアプリを作ることができた。  なお、この記事は約2か月前に機械学習の勉強を始めた超初心者によるものです。不備な点や誤りがあると思いますが、どうかご指摘いただければありがたいです。 ---------------------- 画像分類のモデルを作る  スマホで扱える機械学習モデルの形式として「TensorFlow Lite」がある。これを使えば、例えば花にスマホをかざすとその花の種類を5種類の中から答えてくれるといったアプリを作ることができる。  この方法を教えてくれるサイトがいくつかあるが、その多くは既存の画像のセットを使ってモデルを作るものである。しかし私は、自分の撮影した写真を教師データとして画像を分類するアプリを作りたかったので、その方法を模索した。(事情...

KeyguardManager によるメモリリークはグーグルのバグらしい

イメージ
 KeygurardManagerによるメモリリークが確認された。どうやってこれを解消すればいいか検討したが、結論からいうと、どうやらこれはグーグルのバグで、解消できない可能性が高そうだ。(もし詳しい方がおられたら教えてください) ----------------------------  アプリを作ったら、メモリリークがないか確認しなければならない。  メモリリークとは、アプリが確保したメモリが不要になっても解放されないままになることで、使えるメモリが減ってしまい不具合の原因となる。その確認のためにリークキャナリー(LeakCanary)を入れて確認することが広く行われている。  リークキャナリーの入れ方についてはこちら。非常に簡単である。 https://zenn.dev/yass97/articles/e25960d5511c30  ただ、その読み方はちょっと難しい。今回確認されたリークは次のようなもの。  これを見ていくと、上から1/3くらいのところにKeyguardManager とあり、また、下から1/3くらいのところにAlarmActivityとある。さらにそのすぐ下にLeakinng:YES とあるので、結局、AlarmActivityというアクティビティの中にある、KeyguardManagerのインスタンスにリークがあるということなのだ。  ちなみに、KeyguardManager とは、スマホのロックを管理するクラスで、私は目覚まし時計を作る際に、スマホがロックされていてもアラームの画面だけは表示できるようにするために使ったのだ。  さて、ではどうやってこのメモリリークを解消するか。  メモリリークは多くの場合、アクティビティ等を閉じる段階(onPauseやonDestroy)において、リークの原因となっているオブジェクトを解放し、nullにしてやることで解消できる。このブログでも次のような例について、メモリリークが解消できたことを報告した。 https://marsh-mashro.blogspot.com/2023/08/broadcastreceiver.html https://marsh-mashro.blogspot.com/2023/08/handler.html  しかしKeyguardManagerのメモリリークはこのような方...

ボタンの重なりとelevation

elevationで画面要素のz軸方向の高さを決めるが、そのときの発見。 ボタンが重なった時、どう反応するかということ。 結論からいくと、重なったボタンがあるとき、上(elevationの値が大きいほう)のボタンが反応するときと、そうでないときがある。 両方のボタン下のボタンのelevationを0dp、上のボタンのelevationを2dpとすれば意図どおり上が反応するが、それ以外のときはよくわからない。 なぜこういうことを考えたかというと、「画面のどこでもタップすればヘルプに飛ぶ」というようなアプリを作ろうと考えて、画面全体を覆うような透明なボタンを作った。そのうえで、一時的に画面に普通のボタンを表示して、それはまた別の機能を持つようにしようと思ったところ、後者のボタンを押すと前者の透明なボタンが反応してしまう。 そこで、elevagionを操作すればこの問題が解決できるのでは、と考え、透明なボタンを10dp、一時的な普通のボタンを20dpに設定し、これならより上にある後者のボタンが反応するだろう、と思ったのだが、うまくいかず、やっぱり前者の透明なボタンが先に反応してしまう。で、いつものように悩んでいた。 この問題は、たまたま、透明なボタンのelevationを0dp、一時的なボタンのelevationを2dpとすることで解決できた。0dpと1dpではうまくいかないときがあり、また、3dp以上でもうまくいかないことがあった。 なお、ImageViewやTextViewはこれとは関係なく、それらが上にあってsetOnClickListenerが設定されていても、下にあるボタンのほうが優先的に機能するみたいだ。 「ようだ」とか「みたいだ」が多い記事ですみません。今度時間のあるときにちゃんと検証しようと思います。

固定電話がわりのSkype

固定電話がわりに050番号を使う  固定電話を置きたいが費用やスペースや配線の手間等の点で二の足を踏んでいる場合、一つの選択肢は「スマホで使える050番号サービスを契約し、古いスマホなどSIMの入ってないスマホにそのアプリを入れて家に置いておく」というものです。  費用が安い、スペースをとらない、配線の手間は不要、などのメリットがあります。 しかし多くの050番号サービスは撤退。使えるのは(多分)Skypeのみ  ところが、2023年夏頃、なぜか、OCNが提供している050プラスを初め多くの個人向け050番号サービスが軒並み撤退してしまいました。私が把握している限り、現在この用途で使えるのはSkypeの「Skype番号」というサービスのみです。受信だけなら費用は月300円(長期契約割引あり)です(発信するためには別途前払いのクレジットを購入するか、月額プラン(現時点で867円/月、無料通話枠あり)に入る必要があります)。 Skype番号を使うには  Skype番号を使うには、運転免許などの個人を証明する書類とスマホで自撮りした顔写真をアップするなどして認証を受ける必要があります。その過程でMicrosoftのAuthenticatorを使うので、申込の前にAuthenticatorがインストールされていなければインストールし、パスワードを確認しておく必要があります。この部分は結構面倒でした。また、私だけかもしれませんが、確認ボタンがスマホの下のほう(いつもは広告が表示されるので無視する場所)に表示されるので、気づかずに確認の制限時間をオーバーしてしまうということがありました。(スマホの画面全部に注意を払いましょう) Skype番号の特徴  Skype番号には、複数のスマホにアプリを入れて都合のよいスマホで通話できるという、他の050番号サービスになかった特徴があります。なお、留守電機能はありますが、応答の音声は英語です。 使うときの工夫  電話の着信を受けるためには基本的にはSkypeアプリを立ち上げて前面に置いておかなければなりませんが、スマホの設定のところで、「アプリ→Skype→詳細設定」として(機種による違いあり)、「通知」「他のアプリの上に重ねて表示」を許可しておくと、Skypeアプリがバックグラウンドにあったり画面消灯しているときでも着信を受けることがで...

SDK34におけるForegroundServiceの問題

 これまで動いていたアプリのTargetSDKを33から34に変えたところ、ForegroundServiceを立ち上げるところでいきなりエラー。その理由と対処法がわかった。  今回のバージョンアップで、ForegroundServiceには「サービスタイプ」を指定しなければならなくなった。  サービスタイプとは、そのフォアグラウンドサービスが、例えばメディア再生を行うものなのか、外部との通信を行うものなのか、といった種別のこと。次を参照。 https://developer.android.com/about/versions/14/changes/fgs-types-required?hl=ja 例えば、サービスがメディア再生を行うものであった場合は、マニフェストで、 パーミッションのところに、これまでは次の1文があれば良かった。 <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> 今後はそれに加えて、次の文を入れる必要がある。   <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" /> さらに、<service・・・></service>の・・・の部分に  android:foregroundServiceType="mediaPlayback" を追記することも必要。 この2点を追記すると、以前と同様に動くようになった。

ビルドエラー:Attempt to create a global synthetic for 'Record desugaring' without a global-synthetics consumer の解決

このエラーで苦労している人は他にはいないでしょうか。他の原因もあるかもしれないけど、私の場合はこれで解決できたので報告します。   【問題発生の経緯】 Aというアプリを複製してBというアプリを作った(複製の方法は、以前このブログで書いた次の方法)。 https://marsh-mashro.blogspot.com/2023/08/androidstudio.html ところが、次のエラーが出てビルドができない。 Attempt to create a global synthetic for 'Record desugaring' without a global-synthetics consumer 直し方はおろか、エラーの意味すらわからず途方に暮れた。そもそも、複製前のアプリと複製後のアプリはアプリ名を除いて全く同じなのに、なぜこんなことが起きるのか・・・。 検索すると次のようなページが出てくるが、読んでもよくわからない。ただ、どうやらJavaのバージョンに関係ありそうだということがわかった。 https://www.mongodb.com/community/forums/t/how-to-properly-connect-my-kotlin-android-app-with-mongodb-atlas-cluster/196264 https://stackoverflow.com/questions/75043114/android-build-produces-error-attempt-to-create-a-global-synthetic-for-record-d そこで、build.gradleの中のJavaのバージョンを表していそうなところだとか、Project Structureだとか、今まで触ったこともないようなところを闇雲に変更したり古いバージョンを使ってみたりしたが、もちろんエラーはなくならない。 【何とか解決】 結構絶望的な気分になっていたのだが、Bのもとになった空っぽのアプリはビルドができることに気づいた。ということはGradleの問題ではない。そこで、部分的にAアプリのコピーをしてBアプリにペーストし、そのたびにビルドを試す、ということをやって...

アンドロイドアプリ「相撲目覚まし」更新しました。

10月末に公開していた「相撲目覚まし」の新しいバージョンを公開しました。何とか今年中にできました。 画面を長押しすれば操作ガイドが現れたり、アラームをキャンセルしたときの音声をすぐにストップできるようにしたなど、使いやすくなったと思うので、インストールしている方はどうぞ更新してください。 https://play.google.com/store/apps/details?id=mashro.com.wixsite.mashro.dc06 です。 その後、スマホを画面オフにしてもアラームが鳴るよう改良したバージョンを別のアプリ「相撲目覚まし2」として公開しました。据え置きとしてではなくモバイルとして使用する場合にはこちらがおすすめです。 https://note.com/mashro/n/ncc9dc5302949

画面回転で苦労した話(原因はわかった)

画面を回転させると、なぜかレイアウトが崩れてしまう。 https://qiita.com/QiitaD/items/7d405e93f39a4a3c9d95 などを参考にさせていただいて、ちゃんと縦用の画面と横用の画面を作って、それぞれ layout と layout-land のフォルダに入れているのに、縦で立ち上げた画面を回転させても横用の画面にならず、縦用のレイアウトを無理やり横に合わせた形になってしまう。その逆も同じ。横で立ち上げた画面を縦にするときもうまくいかない。つまり、レイアウトの切り替えをやってくれないのである。その理由がわからず、ずいぶん悩んだ。 今度やっとその原因がわかったのだが、画面回転を検知するための設定に問題があった。具体的には、マニフェストの当該Activityに "android:configChanges="orientation|screenSize" を追記したとき、この問題が起きるようだ。 原因はわかったがまだ問題は残る。上記の追記は画面回転を検知するためには必要。 今回は、アプリの立ち上げ時にメッセージを出すにあたって、画面回転するたびに同じメッセージが出てはうるさいので、回転の後すぐはそれが出ないようにするために、この機能を使っていたのだった。 しかしこれをやると、画面のレイアウトが崩れてしまう・・・この両立をする方法はないのか。 (ちなみに、無理やり縦用と横用のレイアウトに違う名前を付けて、アクティビティ上で画面の向きを検知して 、 縦の時はsetContentView(縦用レイアウト)、横の時はsetContentView(横用レイアウト)としてみたが、 やはりレイアウトは切りかわらなかった。) 参考までに、画面回転の検知には、上記の追加を行ったうえで、以下のようなコードを AppCompatActivityの中に書く。この場合、画面が回転したらsharedPreferenceの"Rotated"がtrueになるので検知できる。 override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(new...

目覚まし時計アプリを公開します

 約1年かけて作っていたアプリ(アンドロイド用)が一応完成しました。昨日、グーグルの審査で承認されて、晴れて公開できるようになりました。  充電中のスマホや使用済みの古いスマホをアラーム付き置時計として使うアプリで、威勢のいい相撲の掛け声で目覚めて睡眠リズムを整えようとするものです。  タイトル:「相撲目覚まし-睡眠リズムを整える」 https://play.google.com/store/apps/details?id=mashro.com.wixsite.mashro.dc06   (アプリの特色) ①文字の色、背景の画像をお好みに応じて設定できます。ユーザーの撮影した写真などを背景とすることもできます。 ②最小限の動作でアラームの設定や解除などを行うことができます。 ③2種類のアラーム(相撲の掛け声/鳥の声とベルの音)を使用できます。いずれも音を止めた際に、あいさつ 、 日付、時刻、占いによる朝のメッセージを聞くことができます。 ④夜間は自動的に、ブルーレイが少ないなどリラックスできる画面(リラックス画面)となるように設定できます。就寝時にはさらに暗い画面(星空の画面など)とできます。 ⑤消灯予定時刻を知らせる音楽を流すことができます。 ⑥消灯時刻と起床時刻を記録することができます。 ※電源をつないだ状態での使用を想定しています。 ※設定できるアラームは24時間以内、1回に限ります。 ※スマホをオフにするとアラームは鳴りません。 ※個人情報を取得することはありません。外部との通信も一切行いません。 ※無料で、広告もありません。 (プライバシーポリシー)  ・本アプリは個人情報を取得することはありません。外部との通信も一切行いません。  ・スマホに保存されている画像を表示する機能がありますが、画像データへのリンクはアプリを終了すると消去されます。すなわち、後で同じ画像を表示するためには再度画像を選択する必要があります。   ※2023年12月30日に新バージョンに更新しました。 ※2025年12月20日に、画面をオフにしてもアラームが鳴るよう改良したものを、「相撲目覚まし2」として公開しました。↓ https://play.google.com/store/apps/details?id=mashro.com.wi...

エミュレーターのバグ?

イメージ
 現在作っている時計アプリについて、自分の実機以外の機種でも動くのか試しにエミュレーターを使って試してみた。新しい機種、新しいAPIでも動くかやってみようと、Pixel 6 Pro API 31を使った。  そしたら何と!変な時間が出るではないか。今までこんな経験はしたことがなかった。これまでも時差で9時間ずれていて一瞬驚いたことはあったが、今度はそうではない。半端にずれた時刻が表示されている。一方、エミュレーターのデフォルトの時計アプリは正しい時刻を指している。もしかして、今作っているアプリは最新機種には適合してないのか・・・。そこで、非常に簡単な、時間だけを表示するアプリを作ってみた。 class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super .onCreate(savedInstanceState) setContentView(R.layout. activity_main ) findViewById<Button>(R.id. button ).setOnClickListener { val now = Calendar.getInstance() val nowYear = now.get(Calendar. YEAR ) val nowMonth = now.get(Calendar. MONTH )+ 1 val nowDay = now.get(Calendar. DAY_OF_MONTH ) val nowHour=now.get(Calendar. HOUR_OF_DAY ) val nowMinute = now.get(Calendar. MINUTE ) findViewById<TextView>(R.id. tvDate ). text = " $ nowYear 年  $ nowMonth 月  $ nowDay 日 " ...

AndroidStudioのプロジェクトをコピーする

 コーディングがある程度進んだところで、プロジェクトをコピーする必要が出てきました。今までのプログラムは一応動いているのでとっておきたいが、新しいアイディアを加えることも試してみたいので。  AndroidStudioにはプロジェクトをコピーする機能がないので、自分でやらなければなりません。ネットを検索すると、プロジェクトフォルダを複製してそれに手を加える方法がいくつか出てきましたが、私は次のような方法でこれをやりました。これでも、今のところ問題なく動いています。 ----------------------  まず、新しいプロジェクトを新しい名前で作ります。今までのプロジェクトを「myApp」、新しいのを「myNewApp」としておきましょう。  まず、コピーです。  myApp の AndroidManifest を開いてそのテキストを全てコピーします。そしてmyNewApp のマニフェストファイルを開き、そこにペーストします。すなわち、myNewAppのマニフェストの内容を全て、myAppの内容に置き換えます。  同様に、MainActivityの内容を全て置き換えます。  MainActivity以外のActivityやServiceを、myAppのプロジェクトツールウィンドウからコピーして、myNewAppの同じフォルダにペーストします。  myAppのプロジェクトツールウィンドウから、resの配下にあるフォルダを全てコピーして、myNewAppのresフォルダにペーストします。  次に置換です。  myNewAppのマニフェストを開いて、ctrl+Rを使って「myApp」を「myNewApp」に置換します。  myNewAppのアクティビティやサービスを一つずつ開いて、「myApp」を「myNewApp」に置換します。通常は各アクティビティの最初の行に一つあるだけだと思います。  myNewAppのresの中のthemesを開いて(複数ある場合は順に開いて)、「myApp」を「myNewApp」に置換します。  【後で付け加え。時期によってはこれをやらないとうまくいかないことがあります】myAppとmyNewAppのbuild.Gradle(Project・・・)を開いて比較し、アプリ名以外の違いがあったら、myNewAppのほうをmyAppと同じ内容に...

BroadcastReceiverによるメモリリークが修正できた件。

  時計アプリを作っていて、アラーム時刻をサービスに送ろうとしてBroadcastReceiverを使ったら、メモリリークが発生。しかしそれを何とか修正した件。 最初に作った送信側のActivityがこれ。 class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_zoperation) //MyReceiverの登録 val filter1 = IntentFilter() filter1.addAction("this_is_alarm_time") registerReceiver(MyReceiver(), filter1) //ボタンを押すと findViewById(R.id.button).setOnClickListener{ //目覚まし時刻の入力(4桁の数字を入力) val alarmTime:String = findViewById(R.id.inputAlarmTime) .text.toString() val intent = Intent("this_is_alarm_time").apply { putExtra("alarmTime", alarmTime) } sendBroadcast(intent) } } } 受け側はこんな感じ。 var alarmTime2: String = "" class MyService : Service() { //MyReceiverをここに置く。 class MyReceiv...

Handlerによるメモリリークが修正できた件

  時計アプリを作っていた際に遭遇したメモリリーク。1秒ごとに、現在時刻をtvTimeNowというTextViewに表示するような簡単なプログラムだが、LeakCanaryで調べるとメモリリークがあることが判明した。 class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_zmain) val handler = Handler(Looper.getMainLooper()) val refresh = object : Runnable { override fun run() { //時刻を表示 val now = Calendar.getInstance() tvTimeNow.text= "${now.get(Calendar.HOUR_OF_DAY)}:${String.format("%02d", now.get(Calendar.MINUTE))}" handler.postDelayed(this, 1000) } } handler.post(refresh) } }  メモリリークについてよくわかっているとは言えないのだが、LeakCanaryによるとこのrefreshのところでリークがあるらしい。それで、これを解放するコードを書けばいいのか・・・?と試行錯誤してつぎのようになった。 class MainActivity : AppCompatActivity() { latein...

変数の名前を変える

 変数の名前を変えるのに、今まで、いちいち検索・置換をする方法しか知らなかった。グローバル変数や画面要素のidは、別画面でも検索・置換をしないといけないし、ミスしないように気をつけないといけないし、面倒だなあと思っていた。それが、ちょっと調べてみると次のようなサイトがあり、「変数を選んでshift+F6」をするだけで、Refactorできることがわかった。 sugoi_wada(Hikaru Wada) さん、ありがとうございます。  それで、作っているコードで、変数の名前をかなり大規模に変更。  Activityに出てくる変数は 「int〇〇」とか「str△△」とか、最初に型名をつけて、その変数が表示されるTextViewは「tv〇〇」「tv△△」にする、sharedPreferencesで値を保管するときはそのタグを「"int〇〇"」「"str△△"」など変数名にクオテーションマークをつけたものにする。変数名は長くなったけどずいぶん頭が整理された。どれか一つの名前がわかっていたら、残り2つの名前は見なくてもわかるし。  ちょっとの手間をかけたくなくて適当な名前をつけていたけど、やっぱりいい名前をつけたほうがいい。まあ、後でRefactorすればいいことなんだけど。  

<TextView>をブログに書けない

 このブログを書きながら、HTML画面でコードを書こうとすると、どうしてもエラーが消えないとか、表示が変になることがありました。  理由を調べたところ、Androidのプログラミングでは多用するfindViewById<TextView>とかに出てくる<TextView>。<>とそれではさまれた部分が問題のようです。こういうものを削除するとエラーも消えるし、表示もおかしくなりません。多分、HTMLでは<>で挟まれた言葉は何か特別のコマンドの意味があるからなんだろう、とは思うけど、ではどうするか。  他の方のサイト上でのコードの表示を見ると、時々<TextView><Button>などのないものがあるので、多分同じ理由でこれを削除したのだろうと思ったのですが・・・これまで調べたところ、このことに関する情報がネット上にありません。これって、プログラミングする人にとっては常識なのかなあ。

カッコつけすぎに注意

ときどき setOnClickListener の省略しない使い方がわからなくなるので復習。 こういうのを時々書いて、忘れないようにしなければならない。 class Listener: View.OnClickListener { override fun onClick(p0: View?) { findViewById(R.id.text1).text = "ボタンが押された" } } val listener = Listener() findViewById(R.id.button1).setOnClickListener(listener) ところで、これをやりながら気づいたのだが、次のものは機能しない。 findViewById(R.id.button1).setOnClickListener({view,View -> { findViewById(R.id.text2).text = "ボタンを押した"}}) ボタンは押せるけど、テキストが変わることはない。 なぜかというと、波カッコ({})が二重になっているから。つまり次が正解。 findViewById(R.id.button1).setOnClickListener({view,View -> findViewById(R.id.text2).text = "ボタンを押した"}) 従って、これなんかも動かない。 findViewById(R.id.button1).setOnClickListener {{ findViewById(R.id.text2).text = "ボタンを押した"}} 例によって理由はよくわからないけど、波カッコはただまとめるだけじゃなくて、その中に あるものをちょっと違うものにしてしまう働きもあるのだろう。 では、...

医療・福祉のための年齢計算2

2022年9月に「医療・福祉のための年齢計算2」というアプリを初めてリリースしました。誕生日を入れると 現在の年齢や、西暦・元号(昭和、平成、令和)の各年ごとの年齢を年表で見られるものです。 https://play.google.com/store/apps/details?id=com.nifty.masa_nakamura.nenreikeisan 別に医療・福祉でなくても良いですが、そういう業界で患者さんの年齢を知りたいときなどに元号表示されていると計算が面倒なことを知っていたので、このようなタイトルにしました。素人感満載なアプリですが、とりあえず動くものができたので感激でした。知り合いの人などに使ってもらえたのも嬉しかったです。

周囲の明るさに応じた画面の輝度の調整

現在、時計アプリの製作中なのですが、周囲の明るさに応じて画面の明るさを変えられたらいいなと思い、その部分をテストするためのアプリを作りました。 今までは入力も結果表示もスマホ画面か音声の出力しかやっていなかったので、周囲の明るさを取得する照度センサーや輝度を調整するバックライトの操作は「難しそう」の先入観がありました。 しかしやってみると輝度の調整は簡単でした。onCreate(・・・) の下、setContentView(・・・) の後に次の3行を付け加えるだけ。 (kotlin) val lp = window.attributes //ウインドウの属性を取得 lp.screenBrightness = 0.1f //属性の中で輝度を0.5に設定(最大値は1.0) window.attributes = lp なんなら、次の1行でもよい。(ただし後述の問題点あり) (kotlin) window.attributes.screenBrightness = 0.1f いっぽう照度の取得は少し面倒。SensorEventListenerというインターフェースが必要で、sensorManagerというクラスも使う必要があります。 次のコードで、スマホ付属の照度センサーの有無と、センサーがある場合にはその測定値が画面表示されます。 (kotlin) class MainActivity : AppCompatActivity(), SensorEventListener { //SensorEventListenerというインターフェースをつけておくことが必要。 private lateinit var sensorManager: SensorManager //SensorManagerを遅延初期化 private var lightSensor: Sensor? = null //SensorクラスのlightSensorをメンバ変数として作っておく(onCreate、onResumeの両方で使うので) private lateinit var te...

はじめまして!

2022年2月、60才を目前にして趣味でプログラミングを始めました。kotlinでアンドロイドのスマホ用アプリにチャレンジしています。 物忘れも多い年頃の独学の初心者でおまけにブログも初めてなので頓珍漢なことも多いと思いますが、どうぞよろしくお願いいたします。😽  使用しているPC:富士通 デスクトップPC D583/Win 11/MS Office H&amp;B 2019/Core i7-4770/wajunのWIFI/Bluetooth/HDMI/DVD/32GB/1TB SSD (中古パソコン再生品。自分と似たようなものか・・・)