ともちゃんのアプリ開発日記

組込みC言語プログラマだったともちゃんが、四苦八苦しながら、AndroidのJAVA/Kotlin、iOSのSwiftUIを習得して行きます。ともちゃんの備忘録も兼ねています。

Android 11 AsyncTask 非推奨 (Java)

Android 11でAsyncTaskが非推奨になりました。

なので、java.util.concurrentのExecutorを使って書き換えました。

 

Asyncタスクを使った例:

public static class AsyncExportProgress extends AsyncTask<Void, Void, String> {

ProgressBar progressBar;
Snackbar snackbar;

@Override
protected void onPreExecute() {
// ここに前処理を記述します
// 例) プログレスダイアログ表示
}

@Override
protected String doInBackground(Void... arg0) {
// バックグラウンド処理
}

@Override
protected void onPostExecute(String result) {
// バックグランド処理終了後の処理をここに記述します
// 例) プログレスダイアログ終了
}
}

 

呼び出し側:

AsyncExportProgress asyncExportProgress = new AsyncExportProgress();
asyncExportProgress.execute();

 

Executorを使用した例:

private static class AsyncExportProgress {

ProgressBar
progressBar;
Snackbar
snackbar;

private class AsyncRunnable implements Runnable {

private String strResult;

Handler
handler = new Handler(Looper.getMainLooper());
@Override
public void run() {
// ここにバックグラウンド処理を書く

handler.post(new Runnable() {
@Override
public void run() {
onPostExecute(
strResult);
}
});
}
}

void onPreExecute() {
 
// ここに前処理を記述します
// 例) プログレスダイアログ表示
}

void execute() {
onPreExecute();
ExecutorService executorService = Executors.
newSingleThreadExecutor();
executorService.submit(
new AsyncRunnable());
}

void onPostExecute(String result) {
// バックグランド処理終了後の処理をここに記述します
// 例) プログレスダイアログ終了
}
}

呼び出し側:

AsyncExportProgress asyncExportProgress = new AsyncExportProgress();
asyncExportProgress.execute();

Android 11 AsyncTask 非推奨 (Kotlin)

Android 11でAsyncTaskが非推奨になりました。

なので、java.util.concurrentのExecutorを使って書き換えました。

 

Asyncタスクを使った例:

private class TestAsyncTask : AsyncTask<Void, Void, Int>() {

    override fun onPreExecute() {
        super.onPreExecute()
        // 前処理
    }

    override fun doInBackground(vararg p0: Void): Int {
        // バックグラウンド処理
        return 0
    }

    override fun onPostExecute(response: Int) {
        super.onPostExecute(response)
        // 後処理
    }
}

 呼び出し側:

val testAsyncTask = TestAsyncTask()
testAsyncTask.execute()

 

Executorを使用した例:

private class TestRunnable(val onPostExecute:(Int) -> Unit) : Runnable {
    val handler = Handler(Looper.getMainLooper())

    override fun run() {
        // メイン処理

        // 後処理実行
        handler.post(Runnable {
            onPostExecute(1001)
        })
    }
}

private class TestAsyncTask {

    fun onPreExecute() {
        // 前処理

    }

    fun execute() {
        onPreExecute()
        val executorService : ExecutorService = Executors.newSingleThreadExecutor()
        executorService.submit(TestRunnable(context, ::onPostExecute)) }

    fun onPostExecute(response: Int) {
        // 後処理
    }

}

 呼び出し側:

val testAsyncTask = TestAsyncTask()
testAsyncTask.execute()

 

Android 11 IntentService 非推奨

Android 11でIntentServiceが非推奨になりました。

JobIntentServiceを使って書き換えました。

 

IntentServiceの例:

class TestService : IntentService("TestService") {
    override fun onHandleIntent(intent: Intent?) {
        // ここに処理を書く

    }

 呼び出し側:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    context.startForegroundService(intent)
} else {
    context.startService(intent)
}

 AndoidMenifest.xml

<service
    android:name=".TestService "
    android:enabled="true"
    android:exported="false" />

 

JobIntentServiceの例:

class TestService : JobIntentService() {

    private val JOB_ID = 1000;

    fun enqueueWork(context: Context, work: Intent) {
        enqueueWork(context, TestService::class.java, JOB_ID, work)
    }

    override fun onHandleWork(intent: Intent) {
        // ここに処理を書く
    }

 呼び出し側:

TestService().enqueueWork(context, intent)

AndoidMenifest.xml

<uses-permission android:name="android.permission.WAKE_LOCK"/>

 

<service
    android:name=".TestService "
    android:permission="android.permission.BIND_JOB_SERVICE"
    android:enabled="true"
    android:exported="false" />

 

ツータッチメール2で、Intentを使用してGmailアプリに、CC, BCC, 件名, 本文が渡せない。

ツータッチメール2では、Intentという内部処理を使用して、Gmailアプリに、CC, BCC, 件名, 本文を渡しています。

ある日突然、Gmailアプリが、CC, BCC, 件名, 本文を受け付けてくれなくなりました。

その時のソースコードはこうです。

// メールアドレス設定
val uri = Uri.parse("mailto:" + mailAddressTO)

// 件名、本文をメールツールに渡す
val intent = Intent(Intent.ACTION_SENDTO, uri)
intent.putExtra(Intent.EXTRA_CC, mailAddressCC)
intent.putExtra(Intent.EXTRA_BCC, mailAddressBCC)
intent.putExtra(Intent.EXTRA_SUBJECT, subject)
intent.putExtra(Intent.EXTRA_TEXT, mailText)
startActivity(context, intent, null)

 

 そして、改善後

val intent = Intent(Intent.ACTION_SEND)
intent.type= "message/rfc822"
intent.putExtra(Intent.EXTRA_EMAIL, mailAddressTO)
intent.putExtra(Intent.EXTRA_CC, mailAddressCC)
intent.putExtra(Intent.EXTRA_BCC, mailAddressBCC)
intent.putExtra(Intent.EXTRA_SUBJECT, subject)
intent.putExtra(Intent.EXTRA_TEXT, mailText)
context.startActivity(intent)

 

 です。

【参考】

https://stackoverflow.com/questions/8701634/send-email-intent

https://qiita.com/kitagry/items/e3b77061c31e388d152f

 

 

GoogleのCloud Pub/SubをREST APIを使って試使用してみた

GoogleのCloud Pub/SubをREST APIを使って試使用してみました。

f:id:uchida001tmhr:20191126192615p:plain

 

なぜ、REST APIか?

それは、Googleが推奨するClient Libraryは、Androidで動作しないためです。

Client Library(Java)はWindows環境変数を使用するように書いてあるのですが、ライブラリの中でSystem.getenv()を使用していて、実行するとWindows環境変数ではなく、Android環境変数が読めるんですよね…。当たり前といえば当たり前ですが…。

なので、REST APIとOkHttp3を使ってスクラッチでサンプルプログラム(Kotlin)を組みました。

 

ここからダウンロードできます。

 

  1. Assetsフォルダに、Google API Consoleからダウンロードしたjsonファイルを入れてください。
  2. また、MainActivity.ktの変数googleAccountに自分のGoogleアカウントを入れてください。
  3. Proxyの内側に端末がある場合には、PubSubHttps.ktでコメントアウトしてある"clientBuilder.proxy(Proxy(Proxy.Type.HTTP, InetSocketAddress("10.96.241.14", 9515)))"を有効にしてください。 

それだけ動くと思います。

 

MPAndroidChartでLineChartを描く

MPAndroidChartでLineChartを描くのに苦労しましたので、サンプルコードを載せておきます。

private class GraphManager {

private LinearLayout chartLayout;
private final Context context;

public GraphManager(Context context) {
this.context = context;
}

@SuppressWarnings("ConstantConditions")
public void displayGraph(
String legend,
int dataCount,
Date[] dateValue,
boolean[] flagActual,
double[] yActualValue,
boolean[] flagActualNight,
double[] yActualValueNight,
boolean[] flagTarget,
double[] yTargetValue) {

Resources resources = getResources();

DataCenter dataCenter = new DataCenter();
View view = dataCenter.getGraphView();
LineChart lineChart = view.findViewById(R.id.chartArea);

lineChart.getAxisRight().setEnabled(false);
lineChart.getAxisLeft().setEnabled(true);
lineChart.setDrawGridBackground(true);

lineChart.setTouchEnabled(false);
lineChart.setPinchZoom(false);
lineChart.setDoubleTapToZoomEnabled(false);

lineChart.setScaleEnabled(true);

lineChart.getLegend().setEnabled(true);

lineChart.getDescription().setText("");

//X軸周り
XAxis xAxis = lineChart.getXAxis();
xAxis.setDrawLabels(true);
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setDrawGridLines(true);

YAxis yAxis = lineChart.getAxisLeft();
yAxis.setLabelCount(10);

lineChart.setData(createLineChartData(
legend,
xAxis,
dataCount,
dateValue,
flagActual,
yActualValue,
flagActualNight,
yActualValueNight,
flagTarget,
yTargetValue
));
lineChart.invalidate();
}

private LineData createLineChartData(
String legend,
XAxis xAxis,
int dataCount,
Date[] dateValue,
boolean[] existFlagActual,
double[] yActualValue,
boolean[] existFlagActualNight,
double[] yActualValueNight,
boolean[] existFlagTarget,
double[] yTargetValue) {

xAxis.setValueFormatter(new XAxisValueFormatter(dateValue));

Point point = getDisplaySize(getActivity());

reverseOrderDate(dateValue);
reverseOrder(yActualValue, existFlagActual);
reverseOrder(yActualValueNight, existFlagActualNight);
reverseOrder(yTargetValue, existFlagTarget);

ArrayList<Entry> actualValues = new ArrayList<>();
for (int i=0; i<existFlagActual.length; i++) {
if (existFlagActual[i]) {
actualValues.add(new Entry((float)i, (float)yActualValue[i]));
}
}

ArrayList<Entry> actualValuesNight = new ArrayList<>();
for (int i=0; i<existFlagActualNight.length; i++) {
if (existFlagActualNight[i]) {
actualValuesNight.add(new Entry((float)i, (float)yActualValueNight[i]));
}
}

ArrayList<Entry> targetValues = new ArrayList<>();
for (int i=0; i<existFlagTarget.length; i++) {
if (existFlagTarget[i]) {
targetValues.add(new Entry((float)i, (float)yTargetValue[i]));
}
}

List<ILineDataSet> dataSets = new ArrayList<>();


LineDataSet actualTargetDataSet = new LineDataSet(targetValues, legend + "(" + getString(R.string.graph_target) + ")");
actualTargetDataSet.setColor(Color.rgb(180, 0, 180));
actualTargetDataSet.setCircleColor(Color.rgb(180, 0, 180));
actualTargetDataSet.setLineWidth(2f);
actualTargetDataSet.setDrawValues(false);
dataSets.add(actualTargetDataSet);

LineDataSet actualDataSet = new LineDataSet(actualValues, legend + "(" + getString(R.string.graph_legend_morning) + ")");
actualDataSet.setColor(Color.rgb(0x4d, 0xb6, 0xac));
actualDataSet.setCircleColor(Color.rgb(0x4d, 0xb6, 0xac));
actualDataSet.setLineWidth(2f);
if (DISPLAY_PERIOD_DAY == DISPLAY_PERIOD_14DAYS && RICH_INFO) {
actualDataSet.setDrawValues(true);
actualDataSet.setValueTextSize(point.x/(120.0f));
actualDataSet.setValueTextColor(Color.rgb(0x4d, 0xb6, 0xac));
} else {
actualDataSet.setDrawValues(false);
}
dataSets.add(actualDataSet);

LineDataSet actualNightDataSet = new LineDataSet(actualValuesNight, legend + "(" + getString(R.string.graph_legend_night) + ")");
actualNightDataSet.setColor(Color.rgb(255, 166, 0));
actualNightDataSet.setCircleColor(Color.rgb(255, 166, 0));
actualNightDataSet.setLineWidth(2f);
if (DISPLAY_PERIOD_DAY == DISPLAY_PERIOD_14DAYS && RICH_INFO) {
actualNightDataSet.setDrawValues(true);
actualNightDataSet.setValueTextSize(point.x / (120.0f));
actualNightDataSet.setValueTextColor(Color.rgb(255, 166, 0));
} else {
actualNightDataSet.setDrawValues(false);
}
dataSets.add(actualNightDataSet);

return new LineData(dataSets);

}

}


public class XAxisValueFormatter extends ValueFormatter {

Date[] mDateValues;

public XAxisValueFormatter(Date[] dateValues) {
mDateValues = dateValues;
}

@Override
public String getFormattedValue(float value) {
// write your logic here

int val = (int) value;

SimpleDateFormat sdf = new SimpleDateFormat("MM/dd",Locale.getDefault());
if (mDateValues[val] != null) {
return sdf.format(mDateValues[val]);
} else {
return String.valueOf(value);
}

}
}

private void reverseOrderDate(Date[] date) {
int size = date.length;

for (int i=0; i<size/2; i++) {
Date temp1 = date[i];
date[i] = date[size-1-i];
date[size-1-i] = temp1;

}
}

private void reverseOrder(double[] values, boolean[] existFlag) {
int size = values.length;

for (int i=0; i<size/2; i++) {
double temp1 = values[i];
values[i] = values[size-1-i];
values[size-1-i] = temp1;

boolean temp2 = existFlag[i];
existFlag[i] = existFlag[size-1-i];
existFlag[size-1-i] = temp2;

}
}

@SuppressWarnings("ConstantConditions")
private class MakeAndDisplayGraph {

public MakeAndDisplayGraph() {
}

//日付時刻文字列を Date型に変換
private Date String2date(String strDate) {
Date dateDate = null;
// 日付文字列→date型変換フォーマットを指定して
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy/M/d", Locale.JAPAN);

try {
dateDate = sdf1.parse(strDate);
} catch (ParseException e) {
Resources resources = getResources();
Toast.makeText(getActivity(), resources.getString(R.string.graph_message_input_correct_date), Toast.LENGTH_SHORT).show();
}
return dateDate;
}


public void makeAndDisplayGraph(CalendarAction action, int checkedId) {

Resources resources = getResources();

final String strDateMin = "2200/12/31";
final String strDateMax = "1970/1/1";

DatabaseManager databaseManager = new DatabaseManager();
Cursor cursor = databaseManager.queryDatabaseAll();

Date dateMin = String2date(strDateMin);
Date dateMax = String2date(strDateMax);

if (cursor.moveToFirst()) {
do {
Date date = String2date(cursor.getString(cursor.getColumnIndex("date")));
if (date.getTime() < dateMin.getTime()) {
dateMin = date;
}
if (dateMax.getTime() < date.getTime()) {
dateMax = date;
}
} while (cursor.moveToNext());
}

cursor.close();

DataCenter dataCenter = new DataCenter();
Calendar cal_start = dataCenter.getCalendarGraph();
Calendar cal_now = Calendar.getInstance();
switch (action) {
case NEXT:
cal_start.add(Calendar.DATE, DISPLAY_PERIOD_DAY);
if (cal_now.getTime().getTime() <= cal_start.getTime().getTime()) {
dataCenter.newCalendarGraph();
cal_start = dataCenter.getCalendarGraph();
Toast.makeText(getActivity(),resources.getString(R.string.graph_message_display_latest_data),Toast.LENGTH_SHORT).show();
}
break;
case PREVIOUS:
cal_start.add(Calendar.DATE, -(DISPLAY_PERIOD_DAY));
break;
case TODAY:
cal_start = dataCenter.newCalendarGraph();
break;
}

switch (checkedId) {
case R.id.radioButtonWeight: {

Date[] dateValue = new Date[DISPLAY_PERIOD_DAY];
double[] yActualValue = new double[DISPLAY_PERIOD_DAY];
double[] yActualValueNight = new double[DISPLAY_PERIOD_DAY];
double[] yTargetValue = new double[DISPLAY_PERIOD_DAY];
boolean[] existFlagActual = new boolean[DISPLAY_PERIOD_DAY];
boolean[] existFlagActualNight = new boolean[DISPLAY_PERIOD_DAY];
boolean[] existFlagTarget = new boolean[DISPLAY_PERIOD_DAY];

int year = cal_start.get(Calendar.YEAR);
int month = cal_start.get(Calendar.MONTH) + 1;
int date = cal_start.get(Calendar.DATE);

Calendar cal_index = Calendar.getInstance();
cal_index.set(Calendar.YEAR, year);
cal_index.set(Calendar.MONTH, month - 1);
cal_index.set(Calendar.DATE, date);

boolean exist_flag = false;
int dataCount = 0;
for (int i = 0; i < DISPLAY_PERIOD_DAY; i++) {

String strYearMonthDate = String.valueOf(year) + "/" + String.valueOf(month) + "/" + String.valueOf(date);

cursor = databaseManager.queryDatabase(strYearMonthDate);

dateValue[dataCount] = String2date(strYearMonthDate);

if (cursor.moveToFirst()) {
do {
double actualValue = cursor.getDouble(cursor.getColumnIndex("actual_weight"));
double actualValueNight = cursor.getDouble(cursor.getColumnIndex("actual_weight_night"));
double targetValue = cursor.getDouble(cursor.getColumnIndex("target_weight"));

yActualValue[dataCount] = actualValue;
if (actualValue != 0f) {
existFlagActual[dataCount] = true;
exist_flag = true;
} else {
existFlagActual[dataCount] = false;
}

yActualValueNight[dataCount] = actualValueNight;
if (actualValueNight != 0f) {
existFlagActualNight[dataCount] = true;
exist_flag = true;
} else {
existFlagActualNight[dataCount] = false;
}

yTargetValue[dataCount] = targetValue;
if (targetValue != 0f) {
existFlagTarget[dataCount] = true;
exist_flag = true;
} else {
existFlagTarget[dataCount] = false;
}

} while (cursor.moveToNext());
}

cursor.close();

cal_index.add(Calendar.DATE, -1);
year = cal_index.get(Calendar.YEAR);
month = cal_index.get(Calendar.MONTH) + 1;
date = cal_index.get(Calendar.DATE);
dataCount++;
}

Calendar cal_end = Calendar.getInstance();
cal_end.set(Calendar.YEAR, year);
cal_end.set(Calendar.MONTH, month - 1);
cal_end.set(Calendar.DATE, date);
cal_end.add(Calendar.DATE, 1);

if (exist_flag) {
GraphManager graphManager = new GraphManager(getActivity());
graphManager.displayGraph(
resources.getString(R.string.graph_weight),
dataCount,
dateValue,
existFlagActual,
yActualValue,
existFlagActualNight,
yActualValueNight,
existFlagTarget,
yTargetValue);
} else {
Toast.makeText(getActivity(), resources.getString(R.string.graph_message_no_data), Toast.LENGTH_SHORT).show();
switch (action) {
case NEXT:
if (dateMax.getTime() <= cal_start.getTime().getTime()) {
cal_start.add(Calendar.DATE, -(DISPLAY_PERIOD_DAY));
}
break;
case PREVIOUS:
if (cal_end.getTime().getTime() <= dateMin.getTime()) {
cal_start.add(Calendar.DATE, DISPLAY_PERIOD_DAY);
}
break;
}
}
}
break;
case R.id.radioButtonBodyFatPercentage: {

Date[] dateValue = new Date[DISPLAY_PERIOD_DAY];
double[] yActualValue = new double[DISPLAY_PERIOD_DAY];
double[] yActualValueNight = new double[DISPLAY_PERIOD_DAY];
double[] yTargetValue = new double[DISPLAY_PERIOD_DAY];
boolean[] existFlagActual = new boolean[DISPLAY_PERIOD_DAY];
boolean[] existFlagActualNight = new boolean[DISPLAY_PERIOD_DAY];
boolean[] existFlagTarget = new boolean[DISPLAY_PERIOD_DAY];

int year = cal_start.get(Calendar.YEAR);
int month = cal_start.get(Calendar.MONTH) + 1;
int date = cal_start.get(Calendar.DATE);

Calendar cal_index = Calendar.getInstance();
cal_index.set(Calendar.YEAR, year);
cal_index.set(Calendar.MONTH, month - 1);
cal_index.set(Calendar.DATE, date);

boolean exist_flag = false;
int dataCount = 0;
for (int i = 0; i < DISPLAY_PERIOD_DAY; i++) {

String strYearMonthDate = String.valueOf(year) + "/" + String.valueOf(month) + "/" + String.valueOf(date);

cursor = databaseManager.queryDatabase(strYearMonthDate);

dateValue[dataCount] = String2date(strYearMonthDate);

if (cursor.moveToFirst()) {
do {
double actualValue = cursor.getDouble(cursor.getColumnIndex("actual_body_fat_percentage"));
double actualValueNight = cursor.getDouble(cursor.getColumnIndex("actual_body_fat_percentage_night"));
double targetValue = cursor.getDouble(cursor.getColumnIndex("target_body_fat_percentage"));

yActualValue[dataCount] = actualValue;
if (actualValue != 0f) {
existFlagActual[dataCount] = true;
exist_flag = true;
} else {
existFlagActual[dataCount] = false;
}

yActualValueNight[dataCount] = actualValueNight;
if (actualValueNight != 0f) {
existFlagActualNight[dataCount] = true;
exist_flag = true;
} else {
existFlagActualNight[dataCount] = false;
}

yTargetValue[dataCount] = targetValue;
if (targetValue != 0f) {
existFlagTarget[dataCount] = true;
exist_flag = true;
} else {
existFlagTarget[dataCount] = false;
}

} while (cursor.moveToNext());
}

cursor.close();

cal_index.add(Calendar.DATE, -1);
year = cal_index.get(Calendar.YEAR);
month = cal_index.get(Calendar.MONTH) + 1;
date = cal_index.get(Calendar.DATE);
dataCount++;
}

Calendar cal_end = Calendar.getInstance();
cal_end.set(Calendar.YEAR, year);
cal_end.set(Calendar.MONTH, month - 1);
cal_end.set(Calendar.DATE, date);
cal_end.add(Calendar.DATE, 1);

if (exist_flag) {
GraphManager graphManager = new GraphManager(getActivity());
graphManager.displayGraph(
resources.getString(R.string.graph_body_fat_percentage),
dataCount,
dateValue,
existFlagActual,
yActualValue,
existFlagActualNight,
yActualValueNight,
existFlagTarget,
yTargetValue);
} else {
Toast.makeText(getActivity(), resources.getString(R.string.graph_message_no_data), Toast.LENGTH_SHORT).show();
switch (action) {
case NEXT:
if (dateMax.getTime() <= cal_start.getTime().getTime()) {
cal_start.add(Calendar.DATE, -(DISPLAY_PERIOD_DAY));
}
break;
case PREVIOUS:
if (cal_end.getTime().getTime() <= dateMin.getTime()) {
cal_start.add(Calendar.DATE, DISPLAY_PERIOD_DAY);
}
break;
}
}
}
break;
case R.id.radioButtonBMI: {

Date[] dateValue = new Date[DISPLAY_PERIOD_DAY];
double[] yActualValue = new double[DISPLAY_PERIOD_DAY];
double[] yActualValueNight = new double[DISPLAY_PERIOD_DAY];
double[] yTargetValue = new double[DISPLAY_PERIOD_DAY];
boolean[] existFlagActual = new boolean[DISPLAY_PERIOD_DAY];
boolean[] existFlagActualNight = new boolean[DISPLAY_PERIOD_DAY];
boolean[] existFlagTarget = new boolean[DISPLAY_PERIOD_DAY];

int year = cal_start.get(Calendar.YEAR);
int month = cal_start.get(Calendar.MONTH) + 1;
int date = cal_start.get(Calendar.DATE);

Calendar cal_index = Calendar.getInstance();
cal_index.set(Calendar.YEAR, year);
cal_index.set(Calendar.MONTH, month - 1);
cal_index.set(Calendar.DATE, date);

boolean exist_flag = false;
int dataCount = 0;
for (int i = 0; i < DISPLAY_PERIOD_DAY; i++) {

String strYearMonthDate = String.valueOf(year) + "/" + String.valueOf(month) + "/" + String.valueOf(date);

cursor = databaseManager.queryDatabase(strYearMonthDate);

dateValue[dataCount] = String2date(strYearMonthDate);

if (cursor.moveToFirst()) {
do {
double actualValue = cursor.getDouble(cursor.getColumnIndex("actual_BMI"));
double actualValueNight = cursor.getDouble(cursor.getColumnIndex("actual_BMI_night"));
double targetValue = cursor.getDouble(cursor.getColumnIndex("target_BMI"));

yActualValue[dataCount] = actualValue;
if (actualValue != 0f) {
existFlagActual[dataCount] = true;
exist_flag = true;
} else {
existFlagActual[dataCount] = false;
}

yActualValueNight[dataCount] = actualValueNight;
if (actualValueNight != 0f) {
existFlagActualNight[dataCount] = true;
exist_flag = true;
} else {
existFlagActualNight[dataCount] = false;
}

yTargetValue[dataCount] = targetValue;
if (targetValue != 0f) {
existFlagTarget[dataCount] = true;
exist_flag = true;
} else {
existFlagTarget[dataCount] = false;
}

} while (cursor.moveToNext());
}

cursor.close();

cal_index.add(Calendar.DATE, -1);
year = cal_index.get(Calendar.YEAR);
month = cal_index.get(Calendar.MONTH) + 1;
date = cal_index.get(Calendar.DATE);
dataCount++;

}

Calendar cal_end = Calendar.getInstance();
cal_end.set(Calendar.YEAR, year);
cal_end.set(Calendar.MONTH, month - 1);
cal_end.set(Calendar.DATE, date);
cal_end.add(Calendar.DATE, 1);

if (exist_flag) {
GraphManager graphManager = new GraphManager(getActivity());
graphManager.displayGraph(
resources.getString(R.string.graph_BMI),
dataCount,
dateValue,
existFlagActual,
yActualValue,
existFlagActualNight,
yActualValueNight,
existFlagTarget,
yTargetValue);
} else {
Toast.makeText(getActivity(), resources.getString(R.string.graph_message_no_data), Toast.LENGTH_SHORT).show();
switch (action) {
case NEXT:
if (dateMax.getTime() <= cal_start.getTime().getTime()) {
cal_start.add(Calendar.DATE, -(DISPLAY_PERIOD_DAY));
}
break;
case PREVIOUS:
if (cal_end.getTime().getTime() <= dateMin.getTime()) {
cal_start.add(Calendar.DATE, DISPLAY_PERIOD_DAY);
}
break;
}
}
}
break;
}
}
}

 

 実行結果はこんな感じです。

f:id:uchida001tmhr:20190518120344p:plain

Deit Recorderのグラフ

 

Android 8.0の通知ドット(通知バッジ)を削除する。

Android 8.0の通知ドット(通知バッジ)が邪魔な時があるので、削除する設定です。

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val channel = NotificationChannel(MAIN_CHANNEL, getString(R.string.main_channel), NotificationManager.IMPORTANCE_LOW)
/** 指定できる値は以下7種類。
NotificationManager.IMPORTANCE_UNSPECIFIED (-1000);
NotificationManager.IMPORTANCE_NONE (0);
NotificationManager.IMPORTANCE_MIN (1);
NotificationManager.IMPORTANCE_LOW (2);
NotificationManager.IMPORTANCE_DEFAULT (3);
NotificationManager.IMPORTANCE_HIGH (4);
NotificationManager.IMPORTANCE_MAX (5);
**/
channel.setShowBadge(false)
notificationManager.createNotificationChannel(channel)

}

val intent = Intent(applicationContext, MainActivity::class.java)
val intents = arrayOf(intent)
val pendingIntent = PendingIntent.getActivities(applicationContext, 0, intents, PendingIntent.FLAG_UPDATE_CURRENT)
val builder = NotificationCompat.Builder(applicationContext, MAIN_CHANNEL)
builder.setContentIntent(pendingIntent)
builder.setContentTitle(resources.getString(R.string.app_name))
builder.setContentText(resources.getString(R.string.please_tap_here))
builder.setWhen(System.currentTimeMillis())
builder.setAutoCancel(false)
builder.setSmallIcon(R.drawable.notification_main_small)
builder.setLargeIcon(BitmapFactory.decodeResource(resources, R.drawable.notification_main_large))
builder.setBadgeIconType(NotificationCompat.BADGE_ICON_NONE)

val notification = builder.build()

startForeground(NOTIFICATION_ID, notification)

 上記の

channel.setShowBadge(false)

 と

builder.setBadgeIconType(NotificationCompat.BADGE_ICON_NONE

 で、通知ドット(通知バッジ)を消しています。