投稿

8月, 2023の投稿を表示しています

エミュレーターのバグ?

イメージ
 現在作っている時計アプリについて、自分の実機以外の機種でも動くのか試しにエミュレーターを使って試してみた。新しい機種、新しい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すればいいことなんだけど。