2024-01-17 08:43:54 +00:00
|
|
|
|
package com.example.childguard;
|
|
|
|
|
|
2024-01-18 19:28:17 +00:00
|
|
|
|
import android.annotation.SuppressLint;
|
2024-01-17 08:43:54 +00:00
|
|
|
|
import android.app.NotificationChannel;
|
|
|
|
|
import android.app.NotificationManager;
|
2024-01-18 19:28:17 +00:00
|
|
|
|
import android.app.PendingIntent;
|
2024-01-17 08:43:54 +00:00
|
|
|
|
import android.app.Service;
|
2024-01-19 00:45:26 +00:00
|
|
|
|
import android.bluetooth.BluetoothDevice;
|
|
|
|
|
import android.content.BroadcastReceiver;
|
2024-01-17 08:43:54 +00:00
|
|
|
|
import android.content.Context;
|
|
|
|
|
import android.content.Intent;
|
2024-01-19 00:45:26 +00:00
|
|
|
|
import android.content.IntentFilter;
|
2024-01-22 17:57:28 +00:00
|
|
|
|
import android.content.SharedPreferences;
|
2024-01-17 08:43:54 +00:00
|
|
|
|
import android.content.pm.PackageManager;
|
2024-01-18 20:35:11 +00:00
|
|
|
|
import android.os.Handler;
|
2024-01-17 08:43:54 +00:00
|
|
|
|
import android.os.IBinder;
|
2024-07-11 05:27:52 +00:00
|
|
|
|
import android.os.VibrationEffect;
|
2024-01-17 08:43:54 +00:00
|
|
|
|
import android.os.Vibrator;
|
2024-01-19 00:45:26 +00:00
|
|
|
|
import android.preference.PreferenceManager;
|
2024-01-17 08:43:54 +00:00
|
|
|
|
import android.util.Log;
|
2024-01-18 20:35:11 +00:00
|
|
|
|
|
2024-01-17 08:43:54 +00:00
|
|
|
|
import androidx.annotation.Nullable;
|
|
|
|
|
import androidx.core.app.ActivityCompat;
|
|
|
|
|
import androidx.core.app.NotificationCompat;
|
2024-07-11 06:03:13 +00:00
|
|
|
|
import androidx.core.app.NotificationManagerCompat;
|
2024-01-17 08:43:54 +00:00
|
|
|
|
|
2024-01-18 15:57:33 +00:00
|
|
|
|
import com.google.firebase.firestore.DocumentReference;
|
|
|
|
|
import com.google.firebase.firestore.FirebaseFirestore;
|
2024-01-17 08:43:54 +00:00
|
|
|
|
|
2024-01-18 19:28:17 +00:00
|
|
|
|
public class TestService extends Service {
|
2024-07-11 06:24:02 +00:00
|
|
|
|
|
|
|
|
|
public static class NotificationContent {
|
|
|
|
|
private final String title;
|
|
|
|
|
private final String description;
|
|
|
|
|
|
|
|
|
|
public NotificationContent(String title, String description) {
|
|
|
|
|
this.title = title;
|
|
|
|
|
this.description = description;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public String getTitle() {
|
|
|
|
|
return title;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public String getDescription() {
|
|
|
|
|
return description;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-18 15:57:33 +00:00
|
|
|
|
FirebaseFirestore db;
|
|
|
|
|
DocumentReference mDocRef;
|
2024-01-17 08:43:54 +00:00
|
|
|
|
|
2024-01-18 15:57:33 +00:00
|
|
|
|
public static final String TAG = "InspirationQuote";
|
2024-07-11 05:40:34 +00:00
|
|
|
|
private static final String CHANNEL_ID = "child_guard_emergency";
|
2024-07-11 05:51:59 +00:00
|
|
|
|
private static final int REQUEST_CODE = 100;
|
2024-07-11 06:24:02 +00:00
|
|
|
|
private static final NotificationContent REPORTED_NOTIFICATION =
|
|
|
|
|
new NotificationContent("子供の置き去りをしていませんか?", "第三者からの通報が行われました。");
|
|
|
|
|
private static final NotificationContent BLUETOOTH_NOTIFICATION =
|
|
|
|
|
new NotificationContent("子供の置き去りをしていませんか?", "Bluetoothと車の切断から5分が経過しました");
|
2024-07-11 05:51:59 +00:00
|
|
|
|
|
2024-07-11 05:45:42 +00:00
|
|
|
|
// ユーザーID
|
|
|
|
|
private String userId = null;
|
2024-01-17 08:43:54 +00:00
|
|
|
|
|
2024-01-18 15:57:33 +00:00
|
|
|
|
@Override
|
|
|
|
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
2024-01-18 17:33:56 +00:00
|
|
|
|
//共有プリファレンス全体の準備
|
2024-01-18 15:57:33 +00:00
|
|
|
|
SharedPreferences sharedPreferences = getSharedPreferences("app_situation", MODE_PRIVATE);
|
2024-07-11 05:45:42 +00:00
|
|
|
|
this.userId = sharedPreferences.getString("ID", null);//アプリに記録されているIDの取得
|
|
|
|
|
if (this.userId == null) {
|
2024-01-18 15:57:33 +00:00
|
|
|
|
Log.d("onResume", "ID not initialized.");
|
2024-07-11 05:45:42 +00:00
|
|
|
|
return flags; // IDが初期化されていない場合は何もしない
|
2024-01-18 15:57:33 +00:00
|
|
|
|
} else {
|
2024-07-11 05:45:42 +00:00
|
|
|
|
mDocRef = FirebaseFirestore.getInstance().document("status/" + this.userId);//現在の位置を取得
|
2024-01-18 17:33:56 +00:00
|
|
|
|
initNotification(mDocRef);//現在の位置を引数に initNotification()を処理
|
2024-01-18 15:57:33 +00:00
|
|
|
|
}
|
2024-01-22 16:11:21 +00:00
|
|
|
|
|
2024-07-11 06:12:06 +00:00
|
|
|
|
if (isNotBluetoothGranted()) return flags;
|
|
|
|
|
|
|
|
|
|
registerReceiver(receiver);
|
2024-01-18 15:57:33 +00:00
|
|
|
|
return flags;
|
2024-01-17 08:43:54 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-07-11 05:40:34 +00:00
|
|
|
|
@Override
|
|
|
|
|
public void onCreate() {
|
|
|
|
|
super.onCreate();
|
|
|
|
|
if (!isNotificationChannelCreated()) {
|
|
|
|
|
createNotificationChannel();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-11 05:41:17 +00:00
|
|
|
|
/**
|
|
|
|
|
* 通知チャネルが作成されているか確認
|
|
|
|
|
* @return 通知チャンネルの有無 true: 作成済み false: 未作成
|
|
|
|
|
*/
|
2024-07-11 05:40:34 +00:00
|
|
|
|
private boolean isNotificationChannelCreated() {
|
|
|
|
|
NotificationManager notificationManager = getSystemService(NotificationManager.class);
|
|
|
|
|
return notificationManager.getNotificationChannel(CHANNEL_ID) != null;
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-11 05:41:17 +00:00
|
|
|
|
/**
|
|
|
|
|
* 通知チャネルの作成
|
|
|
|
|
*/
|
2024-07-11 05:40:34 +00:00
|
|
|
|
private void createNotificationChannel() {
|
|
|
|
|
int importance = NotificationManager.IMPORTANCE_DEFAULT;
|
|
|
|
|
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "通知", importance);
|
|
|
|
|
channel.setDescription("第三者により置き去りの通報が行われたときに通知します。");
|
|
|
|
|
NotificationManager notificationManager = getSystemService(NotificationManager.class);
|
|
|
|
|
notificationManager.createNotificationChannel(channel);
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-11 06:03:13 +00:00
|
|
|
|
/**
|
|
|
|
|
* 通知が許可がされているかどうかを確認
|
2024-07-11 06:05:56 +00:00
|
|
|
|
* @return 通知の許可の有無 true: 許可されていない false: 許可されている
|
2024-07-11 06:03:13 +00:00
|
|
|
|
*/
|
2024-07-11 06:05:46 +00:00
|
|
|
|
private boolean isNotNotificationEnabled() {
|
2024-07-11 06:03:13 +00:00
|
|
|
|
NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(this);
|
2024-07-11 06:05:46 +00:00
|
|
|
|
if (!notificationManagerCompat.areNotificationsEnabled()) {
|
|
|
|
|
Log.d(TAG, "通知が許可されていません");
|
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
Log.d(TAG, "通知が許可されています");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2024-07-11 06:03:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-07-11 06:12:06 +00:00
|
|
|
|
/**
|
|
|
|
|
* Bluetoothの権限が許可されているかどうかを確認
|
|
|
|
|
* @return Bluetoothの権限の有無 true: 許可されていない false: 許可されている
|
|
|
|
|
*/
|
|
|
|
|
private boolean isNotBluetoothGranted() {
|
|
|
|
|
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
|
|
|
|
|
Log.d(TAG, "Bluetoothの権限が許可されていません");
|
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
Log.d(TAG, "Bluetoothの権限が許可されています");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* ブロードキャストレシーバーを登録
|
|
|
|
|
* @param receiver ブロードキャストレシーバー
|
|
|
|
|
*/
|
|
|
|
|
public void registerReceiver(BroadcastReceiver receiver) {
|
|
|
|
|
IntentFilter intentFilter = new IntentFilter();
|
|
|
|
|
intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
|
|
|
|
|
intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
|
|
|
|
|
|
|
|
|
|
registerReceiver(receiver, intentFilter);
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-18 17:33:56 +00:00
|
|
|
|
private void initNotification(DocumentReference mDocRef) {//サイト上で押されたボタンの管理
|
2024-01-18 20:35:11 +00:00
|
|
|
|
// PeriodicTaskManagerのインスタンス化
|
2024-01-22 17:08:40 +00:00
|
|
|
|
|
2024-01-18 17:33:56 +00:00
|
|
|
|
// 共有プリファレンス全体の準備
|
2024-01-18 19:28:17 +00:00
|
|
|
|
SharedPreferences sharedPreferences = getSharedPreferences("app_situation", MODE_PRIVATE);
|
2024-01-18 17:33:56 +00:00
|
|
|
|
//車の乗り降りを管理するtrue=乗車、false=降車
|
2024-01-19 01:24:05 +00:00
|
|
|
|
//exists()でdocumentSnapshotの中のファイルの存在の確認
|
|
|
|
|
mDocRef.addSnapshotListener((documentSnapshot, e) -> {
|
|
|
|
|
|
|
|
|
|
Log.d("nt", "イベント開始");
|
|
|
|
|
//共有プリファレンス 書き込みの準備
|
|
|
|
|
SharedPreferences.Editor E = sharedPreferences.edit();
|
|
|
|
|
//車の乗り降りを管理するtrue=乗車、false=降車
|
|
|
|
|
if (documentSnapshot.exists()) {//exists()でdocumentSnapshotの中のファイルの存在の確認
|
|
|
|
|
Boolean isInCar = sharedPreferences.getBoolean("isInCarPref", false);//現在の乗降状態を保存する共有プリファレンス
|
|
|
|
|
E.putBoolean("isInCarPref", documentSnapshot.getBoolean("isInCar"));//乗降状態の判定
|
|
|
|
|
E.apply();//確定処理
|
|
|
|
|
Log.d("nt", "レスポンスを検知しました1");
|
2024-01-20 05:31:16 +00:00
|
|
|
|
if (isInCar) {//isReportedがtrue=サイト上で乗車状態のとき
|
|
|
|
|
if (documentSnapshot.getBoolean("isReported")) {
|
2024-02-01 06:30:39 +00:00
|
|
|
|
//ここスタート(リサイクル)
|
2024-01-20 05:31:16 +00:00
|
|
|
|
ResetReported();// ResetReported();を処理→FireBaseのisReportedをfalseにする
|
2024-07-11 06:26:19 +00:00
|
|
|
|
Notification(getApplicationContext(), REPORTED_NOTIFICATION);//通知を行うメソッド
|
2024-01-20 05:31:16 +00:00
|
|
|
|
}
|
2024-01-22 17:57:28 +00:00
|
|
|
|
} else {//isReportedがfalse=サイト上で降車状態のとき
|
2024-01-19 01:24:05 +00:00
|
|
|
|
ResetReported();//ResetReported();を処理→FireBaseのisReportedをfalseにする
|
2024-01-18 15:57:33 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
}
|
2024-01-17 08:43:54 +00:00
|
|
|
|
|
2024-01-18 19:28:17 +00:00
|
|
|
|
public void ResetReported() {//FireBaseのisReportedをfalseに初期化するメソッド
|
2024-01-18 15:57:33 +00:00
|
|
|
|
db = FirebaseFirestore.getInstance();//Firebaseとの紐づけ
|
2024-07-11 05:45:42 +00:00
|
|
|
|
DocumentReference isReported = db.collection("status").document(this.userId);
|
2024-01-19 01:24:05 +00:00
|
|
|
|
//isReportedをfalseに更新
|
2024-07-11 05:46:12 +00:00
|
|
|
|
isReported.update("isReported", false).addOnSuccessListener(unused ->
|
|
|
|
|
Log.d(TAG, "DocumentSnapshot successfully updated!")).addOnFailureListener(e -> Log.w(TAG, "Error updating document", e));
|
2024-01-18 15:57:33 +00:00
|
|
|
|
}
|
2024-01-18 19:28:17 +00:00
|
|
|
|
|
2024-07-11 06:06:24 +00:00
|
|
|
|
/**
|
|
|
|
|
* 通知をタップしたときにアプリを起動するPendingIntentを取得
|
|
|
|
|
* @param context コンテキスト
|
|
|
|
|
* @param requestCode リクエストコード
|
|
|
|
|
* @param flags フラグ
|
|
|
|
|
* @return PendingIntent
|
|
|
|
|
*/
|
2024-07-11 05:51:59 +00:00
|
|
|
|
private PendingIntent getPendingIntent(Context context, int requestCode, int flags) {
|
2024-01-18 19:28:17 +00:00
|
|
|
|
Intent intent = new Intent(context, MainActivity.class);
|
|
|
|
|
intent.setAction("OPEN_ACTIVITY");
|
2024-07-11 05:51:59 +00:00
|
|
|
|
return PendingIntent.getActivity(context, requestCode, intent, flags | PendingIntent.FLAG_IMMUTABLE);
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-11 06:06:30 +00:00
|
|
|
|
/**
|
|
|
|
|
* デバイスをバイブレーションさせる
|
|
|
|
|
*/
|
2024-07-11 05:53:03 +00:00
|
|
|
|
private void vibrateDevice() {
|
|
|
|
|
Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
|
|
|
|
|
if (vibrator.hasVibrator()) {
|
|
|
|
|
vibrator.vibrate(VibrationEffect.createOneShot(2000, VibrationEffect.DEFAULT_AMPLITUDE));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-11 06:24:02 +00:00
|
|
|
|
public void Notification(Context context, NotificationContent content) {//通知を行うメソッド
|
2024-07-11 05:25:05 +00:00
|
|
|
|
|
|
|
|
|
// 権限の保有を確認
|
2024-07-11 06:05:46 +00:00
|
|
|
|
if (isNotNotificationEnabled()) return;
|
2024-07-11 05:25:05 +00:00
|
|
|
|
|
2024-07-11 05:53:03 +00:00
|
|
|
|
vibrateDevice();
|
2024-01-18 20:35:11 +00:00
|
|
|
|
|
2024-07-11 05:40:34 +00:00
|
|
|
|
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID)
|
2024-01-18 20:35:11 +00:00
|
|
|
|
.setSmallIcon(android.R.drawable.ic_menu_info_details)
|
2024-07-11 06:24:02 +00:00
|
|
|
|
.setContentTitle(content.getTitle())//通知のタイトル
|
|
|
|
|
.setContentText(content.getDescription())//通知の内容
|
2024-07-11 05:51:59 +00:00
|
|
|
|
.setContentIntent(getPendingIntent(context, REQUEST_CODE, 0))//通知をタップするとActivityへ移動する
|
2024-01-18 20:35:11 +00:00
|
|
|
|
.setAutoCancel(true)//通知をタップすると削除する
|
|
|
|
|
.setPriority(NotificationCompat.PRIORITY_HIGH) // プライオリティを高く設定
|
|
|
|
|
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC); // ロック画面に表示する
|
|
|
|
|
|
2024-07-11 05:22:28 +00:00
|
|
|
|
NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
|
2024-07-11 05:40:34 +00:00
|
|
|
|
|
2024-01-18 20:35:11 +00:00
|
|
|
|
notificationManager.notify(R.string.app_name, builder.build());//通知の表示
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-22 16:11:21 +00:00
|
|
|
|
private final BroadcastReceiver receiver = new BroadcastReceiver() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//PreferenceManager.getDefaultSharedPreferences("myPreferences",Context.MODE_PRIVATE);
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onReceive(Context context, Intent intent) {
|
2024-01-23 00:29:42 +00:00
|
|
|
|
SharedPreferences pref = getSharedPreferences("Bluetooth_situation", MODE_PRIVATE);
|
|
|
|
|
SharedPreferences.Editor e = pref.edit();
|
2024-01-22 16:11:21 +00:00
|
|
|
|
String action = intent.getAction(); // may need to chain this to a recognizing function
|
|
|
|
|
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
|
2024-01-22 17:57:28 +00:00
|
|
|
|
Boolean isInCar = pref.getBoolean("isInCarPref", false);
|
2024-01-22 16:11:21 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (ActivityCompat.checkSelfPermission(context, android.Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
|
|
|
|
|
Log.d("BT", "No permission to connect bluetooth devices");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
String deviceHardwareAddress = device.getAddress(); // MAC address
|
|
|
|
|
|
2024-01-22 17:08:38 +00:00
|
|
|
|
String registeredId = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).getString("bluetooth_device_id", "none");
|
|
|
|
|
|
2024-01-22 16:11:21 +00:00
|
|
|
|
if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
|
|
|
|
|
//Do something if connected
|
2024-01-22 17:59:54 +00:00
|
|
|
|
//Bluetoothデバイスが接続されたときの処理
|
2024-01-22 16:11:21 +00:00
|
|
|
|
Log.d("BT", "Device connected");
|
|
|
|
|
|
2024-01-22 17:08:38 +00:00
|
|
|
|
|
2024-01-22 16:11:21 +00:00
|
|
|
|
Log.d("BT_Judge", "Registered: " + registeredId);
|
|
|
|
|
|
|
|
|
|
if (deviceHardwareAddress.equals(registeredId)) {
|
2024-01-22 17:59:54 +00:00
|
|
|
|
//登録済みのデバイスだったときの処理
|
2024-01-22 16:11:21 +00:00
|
|
|
|
Log.d("BT_Judge", "登録済み");
|
2024-01-23 00:29:42 +00:00
|
|
|
|
e.putBoolean("connection_status", true);
|
2024-01-22 16:11:21 +00:00
|
|
|
|
|
2024-01-23 00:29:42 +00:00
|
|
|
|
} else {
|
2024-01-22 17:59:54 +00:00
|
|
|
|
//登録していないデバイスだったときの処理
|
2024-01-22 16:11:21 +00:00
|
|
|
|
Log.d("BT_Judge", "未登録");
|
2024-01-23 00:29:42 +00:00
|
|
|
|
e.putBoolean("connection_status", false);
|
2024-01-22 16:11:21 +00:00
|
|
|
|
}
|
|
|
|
|
e.apply();
|
|
|
|
|
|
2024-01-23 00:29:42 +00:00
|
|
|
|
} else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action) && !isInCar) {//bluetoothが切断されたときに乗車状態のとき
|
2024-01-22 17:57:28 +00:00
|
|
|
|
|
2024-01-22 16:11:21 +00:00
|
|
|
|
//Do something if disconnected
|
2024-01-22 17:59:54 +00:00
|
|
|
|
//デバイスが切断されたときの処理
|
2024-01-22 17:08:38 +00:00
|
|
|
|
if (deviceHardwareAddress.equals(registeredId)) {
|
2024-01-22 17:57:28 +00:00
|
|
|
|
// 5分待機する
|
|
|
|
|
Handler handler = new Handler();
|
|
|
|
|
handler.postDelayed(new Runnable() {
|
|
|
|
|
@Override
|
|
|
|
|
public void run() {
|
2024-01-23 00:29:42 +00:00
|
|
|
|
if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action) && !isInCar) {//その後bluetoothを再接続したり降車状態になったりしていない=置き去りが発生した可能性大
|
2024-07-11 06:26:19 +00:00
|
|
|
|
Notification(context, BLUETOOTH_NOTIFICATION);
|
2024-01-23 00:29:42 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-01-22 17:57:28 +00:00
|
|
|
|
|
2024-01-23 00:29:42 +00:00
|
|
|
|
}, 5 * 60 * 1000); // 5分をミリ秒に変換
|
2024-01-22 17:08:38 +00:00
|
|
|
|
}
|
2024-01-23 00:29:42 +00:00
|
|
|
|
} else {
|
2024-01-22 16:11:21 +00:00
|
|
|
|
Log.d("BT", "Device disconnected");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2024-01-17 08:43:54 +00:00
|
|
|
|
@Nullable
|
|
|
|
|
@Override
|
|
|
|
|
public IBinder onBind(Intent intent) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|