diff --git a/app/src/main/java/com/example/childguard/HomeFragment.java b/app/src/main/java/com/example/childguard/HomeFragment.java index a9358b0..5e852ba 100644 --- a/app/src/main/java/com/example/childguard/HomeFragment.java +++ b/app/src/main/java/com/example/childguard/HomeFragment.java @@ -1,37 +1,17 @@ package com.example.childguard; -import static android.content.ContentValues.TAG; -import static android.content.Context.MODE_PRIVATE; - -import android.content.SharedPreferences; import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.TextView; import androidx.core.content.res.ResourcesCompat; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; -import androidx.print.PrintHelper; - -import android.preference.PreferenceManager; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.FrameLayout; -import android.widget.TextView; -import android.widget.Toast; - -import androidx.annotation.NonNull; - -import com.google.android.gms.tasks.OnFailureListener; -import com.google.android.gms.tasks.OnSuccessListener; -import com.google.firebase.firestore.DocumentReference; -import com.google.firebase.firestore.FirebaseFirestore; - -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; /** * A simple {@link Fragment} subclass. @@ -75,10 +55,12 @@ public class HomeFragment extends Fragment implements OnEventListener{ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + if (getArguments() != null) { // mParam1 = getArguments().getString(ARG_PARAM1); mParam2 = getArguments().getString(ARG_PARAM2); } + } @Override @@ -110,7 +92,7 @@ public class HomeFragment extends Fragment implements OnEventListener{ transaction.commit(); } - private boolean updateUiState(boolean state) { + private boolean updateUiState(boolean isInCar) { Log.d("HomeFragment", "updateUiState: called"); // Init TextView tv; @@ -123,13 +105,13 @@ public class HomeFragment extends Fragment implements OnEventListener{ return false; } catch (IllegalStateException e) { Log.d("HomeFragment", "updateUiState: view is not attached"); -// getParentFragmentManager().beginTransaction().replace(R.id.fragmentContainerView, HomeFragment.newInstance("test", "test")).commit(); -// updateUiState(state); + getParentFragmentManager().beginTransaction().replace(R.id.fragmentContainerView, HomeFragment.newInstance("test", "test")).commit(); + updateUiState(isInCar); return false; } String get_on = "\n乗車状態"; String get_off = "\n降車状態"; - if (state) { + if (!isInCar) { //乗車状態にする fl.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.frame_style_orange, null)); tv.setText(get_on); @@ -143,9 +125,10 @@ public class HomeFragment extends Fragment implements OnEventListener{ } @Override - public boolean onEvent(boolean state) { + public boolean onEvent(boolean isInCar) { Log.d("HomeFragment", "onEvent: called"); - return updateUiState(state); + + return updateUiState(isInCar); } } diff --git a/app/src/main/java/com/example/childguard/MainActivity.java b/app/src/main/java/com/example/childguard/MainActivity.java index e89413c..fb3c249 100644 --- a/app/src/main/java/com/example/childguard/MainActivity.java +++ b/app/src/main/java/com/example/childguard/MainActivity.java @@ -1,67 +1,47 @@ package com.example.childguard; -import static java.security.AccessController.getContext; - -import androidx.activity.result.ActivityResultLauncher; -import androidx.appcompat.app.ActionBar; -import androidx.appcompat.app.AppCompatActivity; -import androidx.browser.customtabs.CustomTabsIntent; -import androidx.core.app.ActivityCompat; -import androidx.core.app.NotificationCompat; -import androidx.core.app.NotificationManagerCompat; - import android.annotation.SuppressLint; import android.app.NotificationChannel; import android.app.NotificationManager; +import android.app.PendingIntent; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothManager; import android.content.BroadcastReceiver; import android.content.Context; -import android.content.SharedPreferences; import android.content.Intent; import android.content.IntentFilter; +import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.graphics.Color; -import android.graphics.Paint; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.os.Vibrator; - -import com.google.android.material.bottomnavigation.BottomNavigationView; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Random; -import java.util.UUID; - import android.preference.PreferenceManager; import android.util.Log; import android.widget.FrameLayout; -import android.widget.TextView; import android.widget.Toast; -import androidx.annotation.Nullable; -import androidx.appcompat.app.AppCompatActivity; -import androidx.core.content.res.ResourcesCompat; -import androidx.core.graphics.Insets; -import androidx.core.view.ViewCompat; -import androidx.core.view.WindowInsetsCompat; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentManager; +import androidx.activity.result.ActivityResultLauncher; +import androidx.appcompat.app.AppCompatActivity; +import androidx.browser.customtabs.CustomTabsIntent; +import androidx.core.app.ActivityCompat; +import androidx.core.app.NotificationCompat; +import androidx.fragment.app.Fragment; + +import com.google.android.material.bottomnavigation.BottomNavigationView; import com.google.firebase.firestore.DocumentReference; -import com.google.firebase.firestore.DocumentSnapshot; -import com.google.firebase.firestore.EventListener; import com.google.firebase.firestore.FirebaseFirestore; -import com.google.firebase.firestore.FirebaseFirestoreException; -import com.google.zxing.integration.android.IntentIntegrator; -import com.google.zxing.integration.android.IntentResult; import com.journeyapps.barcodescanner.ScanContract; import com.journeyapps.barcodescanner.ScanOptions; +import java.util.HashMap; +import java.util.Map; + public class MainActivity extends AppCompatActivity { + FirebaseFirestore db; BluetoothManager bluetoothManager; BluetoothAdapter bluetoothAdapter; @@ -71,14 +51,6 @@ public class MainActivity extends AppCompatActivity { public static final String TAG = "InspirationQuote"; - boolean flg = false; - - //↓日付を取得するやつ - public static String getNowDate() { - @SuppressLint("SimpleDateFormat") final DateFormat df = new SimpleDateFormat("yyy/MM/dd HH:mm:ss"); - final Date date = new Date(System.currentTimeMillis()); - return df.format(date); - } private final ActivityResultLauncher QrLauncher = registerForActivityResult( new ScanContract(), @@ -105,7 +77,7 @@ public class MainActivity extends AppCompatActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); -// super.onStart(); + db = FirebaseFirestore.getInstance();//Firebaseとの紐づけ BottomNavigationView bottomNavigationView = findViewById(R.id.nav_view); @@ -120,6 +92,8 @@ public class MainActivity extends AppCompatActivity { .replace(findViewById(R.id.fragmentContainerView).getId(), this.homeFragment) .addToBackStack(null) .commit(); + firebaselink(); + } else if (v.getItemId() == findViewById(R.id.navigation_notification).getId()) { findViewById(R.id.fab_scan_qr_code).setVisibility(FrameLayout.VISIBLE); getSupportFragmentManager().beginTransaction() @@ -142,6 +116,7 @@ public class MainActivity extends AppCompatActivity { ScanOptions options = new ScanOptions(); options.setPrompt("QRコードを読み取ってください"); QrLauncher.launch(options); + }); //Bluetooth検知機能 @@ -152,74 +127,57 @@ public class MainActivity extends AppCompatActivity { if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) { Log.d("BT", "No permission to connect bluetooth devices"); return; - } - else { + } else { Log.d("BT", "Permission to connect bluetooth devices granted"); } registerReceiver(receiver, intentFilter); - + changessituation(); } @Override protected void onResume() { super.onResume(); + changessituation(); Log.d("onResume", "called"); Log.d("onResume", "mDocRef is null"); - SharedPreferences sharedPreferences = getSharedPreferences("app_situation", MODE_PRIVATE); - String IdPref = sharedPreferences.getString("ID", null); - if (IdPref == null) { - Log.d("onResume", "ID not initialized."); - } else { - mDocRef = FirebaseFirestore.getInstance().document("users/" + IdPref);//現在の位置を取得 - this.flg = false; - initNotification(mDocRef); - } - - + firebaselink(); } - private void initNotification(DocumentReference mDocRef) { + private void initNotification(DocumentReference mDocRef) {//サイト上で押されたボタンの管理 + // 共有プリファレンス全体の準備 + SharedPreferences sharedPreferences = getSharedPreferences("app_situation", MODE_PRIVATE); - // Init pref - SharedPreferences sharedPreferences = getSharedPreferences("app_situation",MODE_PRIVATE); + mDocRef.addSnapshotListener(this, (documentSnapshot, e) -> { - mDocRef.addSnapshotListener(this, new EventListener() { - @Override - public void onEvent(@Nullable DocumentSnapshot documentSnapshot, @Nullable FirebaseFirestoreException e) { - Log.d("nt", "イベント開始"); - //共有プリファレンス 書き込みの準備 - SharedPreferences.Editor E=sharedPreferences.edit(); - //車の乗り降りを管理するtrue=乗車、false=降車 - boolean isInCar = sharedPreferences.getBoolean("car", false); - if (flg && documentSnapshot != null && documentSnapshot.exists()) { - - String parent = documentSnapshot.getString("parent"); - Log.d("nt", "レスポンスを検知しました1"); - - assert parent != null; - if (parent.equals("s")) {//FireBaseの更新情報が"S"のとき=サイト上で第三者ボタンが押されたとき - if (isInCar) { - int importance = NotificationManager.IMPORTANCE_DEFAULT; - NotificationChannel channel = new NotificationChannel("CHANNEL_ID", "通報通知", importance); - channel.setDescription("第3者からの通報を検知しました"); - NotificationManager notificationManager = getSystemService(NotificationManager.class); - notificationManager.createNotificationChannel(channel); - Log.d("nt", "レスポンスを検知しました2"); - notifyMain(); - } - } else { - E.putBoolean("car", !isInCar); - E.apply(); - // SupportFragmentManagerが現在表示しているFragmentを取得 - Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragmentContainerView); - if (fragment instanceof HomeFragment) { - ((HomeFragment) fragment).onEvent(!isInCar); - } else { - Log.d("nt", "HomeFragment is not visible"); - } + Log.d("nt", "イベント開始"); + //共有プリファレンス 書き込みの準備 + SharedPreferences.Editor E = sharedPreferences.edit(); + //車の乗り降りを管理するtrue=乗車、false=降車 + if (documentSnapshot.exists()) {//exists()でdocumentSnapshotの中のファイルの存在の確認 + Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragmentContainerView); + Boolean isInCar = sharedPreferences.getBoolean("isInCarPref", false);//現在の乗降状態を保存する共有プリファレンス + E.putBoolean("isInCarPref", documentSnapshot.getBoolean("isInCar"));//乗降状態の判定 + E.apply();//確定処理 + Log.d("nt", "レスポンスを検知しました1"); + //FireBaseで更新された情報の判定 + if (documentSnapshot.getBoolean("isReported") == false) {//isReportedがfalseのとき=サイト上で保護者ボタンが押されたとき + if (fragment instanceof HomeFragment) {//fragementがHomeFragmentのインスタンスかの判定 + changessituation();// changessituation()メソッドを処理→アプリ側の乗降状態を変化 } + } else if (isInCar) {//第三者ボタンが押されたときにisInCarがtrueのとき=乗車状態のとき→いたずら防止 + int importance = NotificationManager.IMPORTANCE_DEFAULT; + NotificationChannel channel = new NotificationChannel("CHANNEL_ID", "通報通知", importance); + channel.setDescription("第3者からの通報を検知しました"); + NotificationManager notificationManager = getSystemService(NotificationManager.class); + notificationManager.createNotificationChannel(channel); + Log.d("nt", "レスポンスを検知しました2"); + NotificationSetting();//通知に関する設定のメソッド + Notification(getApplicationContext());//通知を行うメソッド + ResetReported();// ResetReported();メソッドを処理→FireBaseのisReportedをfalseにする + } else {//第三者ボタンが押されたときにisInCarがfalseのとき=降車状態のとき + ResetReported();// ResetReported();を処理→FireBaseのisReportedをfalseにする + Log.d("nt", "何もなし"); } - flg = true; } }); @@ -233,13 +191,12 @@ public class MainActivity extends AppCompatActivity { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); // may need to chain this to a recognizing function BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); - HomeFragment homeFragment=new HomeFragment(); +// HomeFragment homeFragment=new HomeFragment(); if (ActivityCompat.checkSelfPermission(context, android.Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) { Log.d("BT", "No permission to connect bluetooth devices"); return; } - String deviceName = device.getName(); String deviceHardwareAddress = device.getAddress(); // MAC address if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) { @@ -262,46 +219,105 @@ public class MainActivity extends AppCompatActivity { } }; - //↓通知のやつ - public void notifyMain() { - //↓通知をする際に起動するバイブレーション - ((Vibrator) getSystemService(Context.VIBRATOR_SERVICE)).vibrate(1000); - //↓通知の詳細設定的な奴 - NotificationCompat.Builder builder = new NotificationCompat - .Builder(this, "CHANNEL_ID") + + public void firebaselink() {//Firebaseのドキュメントの取得 + //共有プリファレンス全体の準備 + SharedPreferences sharedPreferences = getSharedPreferences("app_situation", MODE_PRIVATE); + String IdPref = sharedPreferences.getString("ID", null);////アプリに記録されているIDの取得 + if (IdPref == null) {//FireBaseのIDがアプリに登録されているとき + Log.d("onResume", "ID not initialized."); + } else { + mDocRef = FirebaseFirestore.getInstance().document("status/" + IdPref);//現在の位置を取得 + initNotification(mDocRef);//現在の位置を引数に initNotification()を処理 + + } + } + + public void ResetReported() {//FireBaseのisReportedをfalseに初期化するメソッド + //共有プリファレンス全体の準備 + SharedPreferences sharedPreferences = MainActivity.this.getSharedPreferences("app_situation", MODE_PRIVATE); + String IdPref = sharedPreferences.getString("ID", null);//アプリに記録されているIDの取得 + db = FirebaseFirestore.getInstance();//Firebaseとの紐づけ + DocumentReference isReported = db.collection("status").document(IdPref);//更新するドキュメントとの紐づけ + Map DEFAULT_ITEM = new HashMap<>();//mapの宣言 + //isReportedをfalseに更新 + isReported.update("isReported", false).addOnSuccessListener(unused -> Log.d(TAG, "DocumentSnapshot successfully updated!")).addOnFailureListener(e -> Log.w(TAG, "Error updating document", e)); + } + + public void NotificationSetting() {//通知に関する設定の処理を行うメソッド + int importance = NotificationManager.IMPORTANCE_DEFAULT; + //通知チャネルの実装 + NotificationChannel channel = new NotificationChannel("CHANNEL_ID", "通知", importance); + channel.setDescription("第三者により置き去りの通報が行われたときに通知します。"); + + NotificationManager notificationManager = getSystemService(NotificationManager.class); + notificationManager.createNotificationChannel(channel); + + } + + public void Notification(Context context) {//実際に通知を行うメソッド + final String CHANNEL_ID = "my_channel_id"; + // 通知がクリックされたときに送信されるIntent + Intent intent = new Intent(context, MainActivity.class); + intent.setAction("OPEN_ACTIVITY"); + // PendingIntentの作成 + int requestCode = 100; + int flags = 0; + PendingIntent pendingIntent = PendingIntent.getActivity(context, requestCode, intent, flags | PendingIntent.FLAG_IMMUTABLE); + + ((Vibrator) getSystemService(Context.VIBRATOR_SERVICE)).vibrate(2000);//バイブレーション + + @SuppressLint("NotificationTrampoline") NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "CHANNEL_ID") .setSmallIcon(android.R.drawable.ic_menu_info_details) - .setContentTitle("通報検知") - .setContentText("子供の置き去りを検知しました。") - .setPriority(NotificationCompat.PRIORITY_DEFAULT); + .setContentTitle("子供の置き去りをしていませんか?")//通知のタイトル + .setContentText("第三者からの通報が行われました。")//通知の本文 + .setContentIntent(pendingIntent)//通知をタップするとActivityへ移動する + .setAutoCancel(true)//通知をタップすると削除する + .setPriority(NotificationCompat.PRIORITY_HIGH) // プライオリティを高く設定 + .setVisibility(NotificationCompat.VISIBILITY_PUBLIC); // ロック画面に表示する - NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this); + // NotificationChannelの作成(Android 8.0以降) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + NotificationManager notificationManager = context.getSystemService(NotificationManager.class); + if (notificationManager != null) { + NotificationChannel channel = new NotificationChannel( + CHANNEL_ID, + "Channel Name", + NotificationManager.IMPORTANCE_HIGH + ); + channel.setDescription("Channel Description"); + channel.enableLights(true); + channel.setLightColor(Color.RED); + channel.enableVibration(true); + notificationManager.createNotificationChannel(channel); + } + } + + + NotificationManager notificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE); if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { - // TODO: Consider calling - // ActivityCompat#requestPermissions - // here to request the missing permissions, and then overriding - // public void onRequestPermissionsResult(int requestCode, String[] permissions, - // int[] grantResults) - // to handle the case where the user grants the permission. See the documentation - // for ActivityCompat#requestPermissions for more details. return; } - notificationManager.notify(R.string.app_name, builder.build()); + notificationManager.notify(R.string.app_name, builder.build());//通知の表示 + } + public void changessituation() {//乗降状態の管理をするためにHomeFramgentを呼び出すメソッド + + SharedPreferences sharedPreferences = getSharedPreferences("app_situation", MODE_PRIVATE); + //共有プリファレンス 書き込みの準備 + SharedPreferences.Editor E = sharedPreferences.edit(); + Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragmentContainerView); + Boolean isInCar = sharedPreferences.getBoolean("isInCarPref", false);//現在の乗降状態を保存する共有プリファレンス + ((HomeFragment) fragment).onEvent(!isInCar); } @Override - public void onStop() { + public void onStop() {//アプリをバックグラウンドにした時のメソッド super.onStop(); Intent intent = new Intent(getApplication(), TestService.class); - startService(intent); - } - - //Bluetooth_setupの戻るボタン - public void setupBackButton(boolean enableBackButton) { - ActionBar actionBar = getSupportActionBar(); - actionBar.setDisplayHomeAsUpEnabled(enableBackButton); + startService(intent);//TestServiceを起動 } } diff --git a/app/src/main/java/com/example/childguard/NotificationReceiver.java b/app/src/main/java/com/example/childguard/NotificationReceiver.java new file mode 100644 index 0000000..4fb3f5f --- /dev/null +++ b/app/src/main/java/com/example/childguard/NotificationReceiver.java @@ -0,0 +1,16 @@ +package com.example.childguard; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +public class NotificationReceiver extends BroadcastReceiver {//通知をタップしたときにアプリを起動する処理 + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getAction() != null && intent.getAction().equals("OPEN_ACTIVITY")) {// 通知がタップされたときの処理 + Intent openIntent = new Intent(context, MainActivity.class); // MainActivityを起動 + openIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(openIntent); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/childguard/QR.java b/app/src/main/java/com/example/childguard/QR.java deleted file mode 100644 index 1c9c094..0000000 --- a/app/src/main/java/com/example/childguard/QR.java +++ /dev/null @@ -1,33 +0,0 @@ -//package com.example.childguard; -// -//import android.graphics.Color; -//import android.graphics.drawable.Drawable; -//import android.os.Bundle; -//import android.widget.TextView; -// -//import androidx.appcompat.app.AppCompatActivity; -// -//public class QR extends AppCompatActivity { -// String get_on="乗車状態"; -// String get_off ="降車状態"; -// TextView tv=findViewById(R.id.situation); -// @Override -// protected void onCreate(Bundle savedInstanceState){ -// super.onCreate(savedInstanceState); -// setContentView(R.layout.fragment_qr); -// //多分いらないコード -// findViewById(R.id.camera).setOnClickListener( -// v -> { -// if(get_on.equals(tv.getText().toString())){ -// tv.setText(get_off); -// findViewById(R.id.situation_bg).setBackgroundColor(Color.parseColor("#dcdcdc")); -// } -// else { -// tv.setText(get_on); -// findViewById(R.id.situation_bg).setBackgroundColor(Color.parseColor("#ff4500")); -// } -// } -// ); -// } -// -//} diff --git a/app/src/main/java/com/example/childguard/QRFragment.java b/app/src/main/java/com/example/childguard/QRFragment.java deleted file mode 100644 index 5870462..0000000 --- a/app/src/main/java/com/example/childguard/QRFragment.java +++ /dev/null @@ -1,125 +0,0 @@ -package com.example.childguard; - -import android.content.Intent; -import android.content.SharedPreferences; -import android.net.Uri; -import android.os.Bundle; - -import androidx.activity.result.ActivityResultLauncher; -import androidx.activity.result.contract.ActivityResultContracts; -import androidx.browser.customtabs.CustomTabsIntent; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentManager; -import androidx.fragment.app.FragmentTransaction; - -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.Toast; - -import com.google.zxing.integration.android.IntentIntegrator; -import com.google.zxing.integration.android.IntentResult; -import com.journeyapps.barcodescanner.ScanContract; -import com.journeyapps.barcodescanner.ScanOptions; - -import java.util.Objects; - -/** - * A simple {@link Fragment} subclass. - * Use the {@link QRFragment#newInstance} factory method to - * create an instance of this fragment. - */ -public class QRFragment extends Fragment { - //QRコードから受け取ったURLの受け渡しの宣言 -// OnDataPass dataPass; - // TODO: Rename parameter arguments, choose names that match - // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER - private static final String ARG_PARAM1 = "param1"; - private static final String ARG_PARAM2 = "param2"; - - // TODO: Rename and change types of parameters - private String mParam1; - private String mParam2; - - public QRFragment() { - // Required empty public constructor - } - - /** - * Use this factory method to create a new instance of - * this fragment using the provided parameters. - * - * @param param1 Parameter 1. - * @param param2 Parameter 2. - * @return A new instance of fragment QRFragment. - */ - // TODO: Rename and change types and number of parameters - public static QRFragment newInstance(String param1, String param2) { - QRFragment fragment = new QRFragment(); - Bundle args = new Bundle(); - args.putString(ARG_PARAM1, param1); - args.putString(ARG_PARAM2, param2); - fragment.setArguments(args); - return fragment; - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (getArguments() != null) { - mParam1 = getArguments().getString(ARG_PARAM1); - mParam2 = getArguments().getString(ARG_PARAM2); - } - - - } - - private final ActivityResultLauncher fragmentLauncher = registerForActivityResult(new ScanContract(), - result -> { - String contents = result.getContents(); - if (contents == null) { - Toast.makeText(getContext(), "QRコードが読み取れませんでした", Toast.LENGTH_LONG).show(); - } else if (!contents.contains("https://practicefirestore1-8808c.web.app/")) { - Toast.makeText(getContext(), "Chiled Guardに対応するQRコードではありません", Toast.LENGTH_LONG).show(); - } else { - //URLの表示 - Toast.makeText(getContext(), contents, Toast.LENGTH_SHORT).show(); - //ブラウザを起動し、URL先のサイトを開く - CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(); - CustomTabsIntent customTabsIntent = builder.build(); - customTabsIntent.launchUrl(requireContext(), Uri.parse(contents)); - } - - getParentFragmentManager().popBackStack(); - }); - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - // Inflate the layout for this fragment - View view = inflater.inflate(R.layout.fragment_qr, container, false); - - - Log.d("QRFragment", "onClick: called"); - //QRリーダ起動 - fragmentLauncher.launch(new ScanOptions()); - - return view; - } - //画面遷移メソッド - private void replaceFragment(Fragment fragment) { - // フラグメントマネージャーの取得 - FragmentManager manager = getParentFragmentManager(); // アクティビティではgetSupportFragmentManager()? - // フラグメントトランザクションの開始 - FragmentTransaction transaction = manager.beginTransaction(); - // レイアウトをfragmentに置き換え(追加) - transaction.replace(R.id.fragmentContainerView, fragment); - // 置き換えのトランザクションをバックスタックに保存する - transaction.addToBackStack(null); - // フラグメントトランザクションをコミット - transaction.commit(); - } -} - diff --git a/app/src/main/java/com/example/childguard/QrPrintFragment.java b/app/src/main/java/com/example/childguard/QrPrintFragment.java deleted file mode 100644 index 88ac807..0000000 --- a/app/src/main/java/com/example/childguard/QrPrintFragment.java +++ /dev/null @@ -1,156 +0,0 @@ -package com.example.childguard; - -import static android.content.Context.MODE_PRIVATE; - -import android.content.SharedPreferences; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.drawable.BitmapDrawable; -import android.os.Bundle; - -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentManager; -import androidx.fragment.app.FragmentTransaction; -import androidx.print.PrintHelper; - -import android.preference.PreferenceManager; -import android.util.AndroidRuntimeException; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.WriterException; -import com.journeyapps.barcodescanner.BarcodeEncoder; - -/** - * A simple {@link Fragment} subclass. - * Use the {@link QrPrintFragment#newInstance} factory method to - * create an instance of this fragment. - */ -public class QrPrintFragment extends Fragment { - - // TODO: Rename parameter arguments, choose names that match - // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER - private static final String ARG_PARAM1 = "param1"; - private static final String ARG_PARAM2 = "param2"; - - // TODO: Rename and change types of parameters - private String mParam1; - private String mParam2; - - public QrPrintFragment() { - // Required empty public constructor - } - - /** - * Use this factory method to create a new instance of - * this fragment using the provided parameters. - * - * @param param1 Parameter 1. - * @param param2 Parameter 2. - * @return A new instance of fragment QrPrintFragment. - */ - // TODO: Rename and change types and number of parameters - public static QrPrintFragment newInstance(String param1, String param2) { - QrPrintFragment fragment = new QrPrintFragment(); - Bundle args = new Bundle(); - args.putString(ARG_PARAM1, param1); - args.putString(ARG_PARAM2, param2); - fragment.setArguments(args); - return fragment; - } - - @Override - public void onCreate (Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (getArguments() != null) { - mParam1 = getArguments().getString(ARG_PARAM1); - mParam2 = getArguments().getString(ARG_PARAM2); - - } - } - - // @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - //共有プリファレンス全体の準備 - SharedPreferences sharedPreferences = getActivity().getSharedPreferences("app_situation", MODE_PRIVATE); - //User毎のドメインを保存する - String IdPref=sharedPreferences.getString("ID",null); - // Inflate the layout for this fragment - View view=inflater.inflate(R.layout.fragment_qr_print, container, false);; - //固定のドメイン - String KoteiURL = "https://practicefirestore1-8808c.web.app/?id="; - //すべてのドメイン - String AllURL; - //IdPrefにの値が初期値の場合 - if(IdPref==null) { - //User毎のドメイン - String userURL = getArguments().getString("STR_KEY"); - //キー"ID"の値をuserURLの値にする - SharedPreferences.Editor e = sharedPreferences.edit(); - e.putString("ID", userURL); - //確定処理 - e.apply(); - //二つのドメインを合成する - AllURL=KoteiURL+userURL; - }else{ - //二つのドメインを合成する - AllURL=KoteiURL+IdPref; - } - - int size = 2500; - ImageView imageViewQrCode; - Bitmap QRGazou; - try { - //QRコード生成 - BarcodeEncoder barcodeEncoder = new BarcodeEncoder(); - Bitmap bitmapqr = barcodeEncoder.encodeBitmap(AllURL, BarcodeFormat.QR_CODE, size, size); - imageViewQrCode = (ImageView) view.findViewById(R.id.qr_view); - imageViewQrCode.setTranslationX(1000); - imageViewQrCode.setTranslationY(1000); - imageViewQrCode.setImageBitmap(bitmapqr); - } catch (WriterException e) { - throw new AndroidRuntimeException("Barcode Error.", e); - } - // 画像合成の準備 - // ここのエラーは直すと何故か動かなくなる。このままで動くので放置 - Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.a_group_qr_sos); - Bitmap bitmap1 = ((BitmapDrawable) imageViewQrCode.getDrawable()).getBitmap(); - int width = bitmap.getWidth(); // 元ファイルの幅取得 - int height = bitmap.getHeight(); // 元ファイルの高さ取得 - QRGazou = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - //Canvasの準備 - Canvas canvas = new Canvas(QRGazou); - //画像のサイズの調整 - int disWidth = (width - bitmap1.getWidth()) / 2; - int disHeight = (int) ((height - bitmap1.getHeight()) / 1.3); - canvas.drawBitmap(bitmap, 0, 0, (Paint) null); // image, x座標, y座標, Paintインスタンス - canvas.drawBitmap(bitmap1, disWidth, disHeight, (Paint) null); // 画像合成 - //Androidからプリンターへ印刷指示を出すサポートライブラリ - PrintHelper printHelper = new PrintHelper(getActivity()); - printHelper.setColorMode(PrintHelper.COLOR_MODE_COLOR); - printHelper.setScaleMode(PrintHelper.SCALE_MODE_FIT); - printHelper.printBitmap("job_name", QRGazou); - HomeFragment homeFragment=new HomeFragment(); -// replaceFragment(homeFragment); - return view; - } - //画面遷移メソッド - private void replaceFragment(Fragment fragment) { - // フラグメントマネージャーの取得 - FragmentManager manager = getParentFragmentManager(); // アクティビティではgetSupportFragmentManager()? - // フラグメントトランザクションの開始 - FragmentTransaction transaction = manager.beginTransaction(); - // レイアウトをfragmentに置き換え(追加) - transaction.replace(R.id.fragmentContainerView, fragment); - // 置き換えのトランザクションをバックスタックに保存する - transaction.addToBackStack(null); - // フラグメントトランザクションをコミット - transaction.commit(); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/example/childguard/QrUtils.java b/app/src/main/java/com/example/childguard/QrUtils.java index dc4f493..48b6460 100644 --- a/app/src/main/java/com/example/childguard/QrUtils.java +++ b/app/src/main/java/com/example/childguard/QrUtils.java @@ -8,7 +8,9 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.drawable.BitmapDrawable; import android.util.AndroidRuntimeException; +import android.util.DisplayMetrics; import android.util.Log; +import android.view.WindowManager; import android.widget.ImageView; import androidx.print.PrintHelper; @@ -35,6 +37,7 @@ public class QrUtils { AllURL=KoteiURL+key; int size = 1500; + int qrCodeSize = calculateQRCodeSize(); // 画面密度に応じてサイズを計算 Bitmap QRGazou; Bitmap bitmapqr; try { @@ -55,10 +58,21 @@ public class QrUtils { // 画像のサイズの調整 int disWidth = (width - bitmapqr.getWidth()) / 2; - int disHeight = (int) ((height - bitmapqr.getHeight()) / 1.3); + int disHeight = (int) ((height - bitmapqr.getHeight()) / 1.4); canvas.drawBitmap(bitmap, 0, 0, (Paint) null); canvas.drawBitmap(bitmapqr, disWidth, disHeight, (Paint) null); // 画像合成 //Androidからプリンターへ印刷指示を出すサポートライブラリ return QRGazou; } + private int calculateQRCodeSize() { + // 画面解像度を取得 + DisplayMetrics metrics = new DisplayMetrics(); + WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + windowManager.getDefaultDisplay().getMetrics(metrics); + + // 画面密度に基づいてQRコードのサイズを計算 + float density = context.getResources().getDisplayMetrics().density; + return (int) (1500 * density); + } + } diff --git a/app/src/main/java/com/example/childguard/RecyclerAdapter.java b/app/src/main/java/com/example/childguard/RecyclerAdapter.java index 3aeb1fc..2a184f5 100644 --- a/app/src/main/java/com/example/childguard/RecyclerAdapter.java +++ b/app/src/main/java/com/example/childguard/RecyclerAdapter.java @@ -1,6 +1,5 @@ package com.example.childguard; -import android.bluetooth.BluetoothAdapter; import android.content.Context; import android.content.SharedPreferences; import android.preference.PreferenceManager; @@ -16,7 +15,6 @@ import androidx.appcompat.app.AlertDialog; import androidx.recyclerview.widget.RecyclerView; import java.util.ArrayList; -import java.util.function.Predicate; public class RecyclerAdapter extends RecyclerView.Adapter { diff --git a/app/src/main/java/com/example/childguard/SettingFragment.java b/app/src/main/java/com/example/childguard/SettingFragment.java index 6fd9aa9..46e7b79 100644 --- a/app/src/main/java/com/example/childguard/SettingFragment.java +++ b/app/src/main/java/com/example/childguard/SettingFragment.java @@ -5,21 +5,14 @@ import static android.content.Context.MODE_PRIVATE; import android.content.SharedPreferences; import android.os.Bundle; - -import androidx.annotation.NonNull; -import androidx.fragment.app.Fragment; -import androidx.print.PrintHelper; - import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.Button; import android.widget.Toast; -import com.google.android.gms.tasks.OnFailureListener; -import com.google.android.gms.tasks.OnSuccessListener; -import com.google.firebase.firestore.DocumentReference; +import androidx.fragment.app.Fragment; + import com.google.firebase.firestore.FirebaseFirestore; import java.util.HashMap; @@ -76,18 +69,16 @@ public class SettingFragment extends Fragment { Toast.makeText(getActivity(), "再印刷", Toast.LENGTH_SHORT).show(); getParentFragmentManager().beginTransaction().addToBackStack(null).replace(R.id.fragmentContainerView, GenerateQrFragment.newInstance(sharedPreferences.getString("ID", "none"))).commit(); } else { - String valueParent = "placeholder"; - String valueBorn = "placeholder"; - Map user = new HashMap<>();//mapの宣言 + Map DEFAULT_ITEM = new HashMap<>();//mapの宣言 Log.d("HomeFragment", "onClick is called"); //mapに入れる - user.put("parent", valueParent); - user.put("born", valueBorn); + DEFAULT_ITEM.put("isInCar", false); + DEFAULT_ITEM.put("isReported", false); //新しいドキュメントにIDを作って追加 - db.collection("users") - .add(user) + db.collection("status") + .add(DEFAULT_ITEM) .addOnSuccessListener(documentReference -> { //成功したら //documentReference.getId()でID取得 @@ -95,6 +86,7 @@ public class SettingFragment extends Fragment { SharedPreferences.Editor e = sharedPreferences.edit(); // キー"alreadySaved"の値をtrueにする e.putBoolean("alreadySaved", true); + //確定処理 e.apply(); //画面遷移&ID受け渡し diff --git a/app/src/main/java/com/example/childguard/TestService.java b/app/src/main/java/com/example/childguard/TestService.java index 4547978..247f708 100644 --- a/app/src/main/java/com/example/childguard/TestService.java +++ b/app/src/main/java/com/example/childguard/TestService.java @@ -1,15 +1,22 @@ package com.example.childguard; +import android.annotation.SuppressLint; import android.app.NotificationChannel; import android.app.NotificationManager; +import android.app.PendingIntent; import android.app.Service; import android.bluetooth.BluetoothDevice; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.content.IntentFilter; import android.content.pm.PackageManager; +import android.graphics.Color; +import android.os.Build; +import android.os.Handler; import android.os.IBinder; +import android.os.Looper; import android.os.Vibrator; import android.preference.PreferenceManager; import android.util.Log; @@ -17,112 +24,240 @@ import android.util.Log; import androidx.annotation.Nullable; import androidx.core.app.ActivityCompat; import androidx.core.app.NotificationCompat; -import androidx.core.app.NotificationManagerCompat; -public class TestService extends Service { +import com.google.firebase.firestore.DocumentReference; +import com.google.firebase.firestore.FirebaseFirestore; +import java.util.HashMap; +import java.util.Map; + +public class TestService extends Service { + FirebaseFirestore db; + DocumentReference mDocRef; + + public static final String TAG = "InspirationQuote"; + + public PeriodicTaskManager periodicTaskManager; + + + @Override public int onStartCommand(Intent intent, int flags, int startId) { - - //Bluetooth検知機能 - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED); - intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED); - - if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) { - Log.d("BT", "No permission to connect bluetooth devices"); - - } - else { - Log.d("BT", "Permission to connect bluetooth devices granted"); + //共有プリファレンス全体の準備 + SharedPreferences sharedPreferences = getSharedPreferences("app_situation", MODE_PRIVATE); + String IdPref = sharedPreferences.getString("ID", null);//アプリに記録されているIDの取得 + if (IdPref == null) {//FireBaseのIDがアプリに登録されているとき + Log.d("onResume", "ID not initialized."); + } else { + mDocRef = FirebaseFirestore.getInstance().document("status/" + IdPref);//現在の位置を取得 + initNotification(mDocRef);//現在の位置を引数に initNotification()を処理 } + return flags; + } + private void initNotification(DocumentReference mDocRef) {//サイト上で押されたボタンの管理 + // PeriodicTaskManagerのインスタンス化 + periodicTaskManager = new PeriodicTaskManager(); + // 共有プリファレンス全体の準備 + SharedPreferences sharedPreferences = getSharedPreferences("app_situation", MODE_PRIVATE); + //車の乗り降りを管理するtrue=乗車、false=降車 + //exists()でdocumentSnapshotの中のファイルの存在の確認 + mDocRef.addSnapshotListener((documentSnapshot, e) -> { - registerReceiver(receiver, intentFilter); - //audioStart(); + 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"); + if (documentSnapshot.getBoolean("isReported") == true && isInCar) {//isReportedがtrueかつisInCarがtrueのとき=サイト上で第三者ボタンが押されたときに乗車状態のとき + ResetReported();// ResetReported();を処理→FireBaseのisReportedをfalseにする + int importance = NotificationManager.IMPORTANCE_DEFAULT; + NotificationChannel channel = new NotificationChannel("CHANNEL_ID", "通報通知", importance); + channel.setDescription("第3者からの通報を検知しました"); + NotificationManager notificationManager = getSystemService(NotificationManager.class); + notificationManager.createNotificationChannel(channel); + Log.d("nt", "レスポンスを検知しました2"); + NotificationSetting();//通知に関する設定のメソッド + Notification(getApplicationContext());//通知を行うメソッド + } else if(isInCar){//Bluetoothの切断後5分以上乗車状態のままのとき→QRコード読み取りを忘れているとき→置き去り発生 + ResetReported();//ResetReported();を処理→FireBaseのisReportedをfalseにする + periodicTaskManager.startPeriodicTask();//通知のループをストップする + }else { + ResetReported();//ResetReported();を処理→FireBaseのisReportedをfalseにする + periodicTaskManager.stopPeriodicTask();//5分毎に通知を行う + } + } - return START_NOT_STICKY; + }); + } + public void ResetReported() {//FireBaseのisReportedをfalseに初期化するメソッド + //共有プリファレンス全体の準備 + SharedPreferences sharedPreferences = getSharedPreferences("app_situation", MODE_PRIVATE); + String IdPref = sharedPreferences.getString("ID", null);//アプリに記録されているIDの取得 + db = FirebaseFirestore.getInstance();//Firebaseとの紐づけ + DocumentReference isReported = db.collection("status").document(IdPref);//更新するドキュメントとの紐づけ + Map DEFAULT_ITEM = new HashMap<>();//mapの宣言 + DEFAULT_ITEM.put("isReported", false); + //isReportedをfalseに更新 + isReported.update("isReported", false).addOnSuccessListener(unused -> Log.d(TAG, "DocumentSnapshot successfully updated!")).addOnFailureListener(e -> Log.w(TAG, "Error updating document", e)); + } + + public void NotificationSetting() {//通知に関する設定の処理を行うメソッド + int importance = NotificationManager.IMPORTANCE_DEFAULT; + //通知チャネルの実装 + NotificationChannel channel = new NotificationChannel("CHANNEL_ID", "通知", importance); + channel.setDescription("第三者により置き去りの通報が行われたときに通知します。"); + + NotificationManager notificationManager = getSystemService(NotificationManager.class); + notificationManager.createNotificationChannel(channel); } - private final BroadcastReceiver receiver = new BroadcastReceiver() { + public void Notification(Context context) {//実際に通知を行うメソッド + final String CHANNEL_ID = "my_channel_id"; + // 通知がクリックされたときに送信されるIntent + Intent intent = new Intent(context, MainActivity.class); + intent.setAction("OPEN_ACTIVITY"); + // PendingIntentの作成 + int requestCode = 100; + int flags = 0; + PendingIntent pendingIntent = PendingIntent.getActivity(context, requestCode, intent, flags | PendingIntent.FLAG_IMMUTABLE); - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); // may need to chain this to a recognizing function - BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); - HomeFragment homeFragment=new HomeFragment(); + ((Vibrator) getSystemService(Context.VIBRATOR_SERVICE)).vibrate(2000);//バイブレーション - if (ActivityCompat.checkSelfPermission(context, android.Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) { - Log.d("BT", "No permission to connect bluetooth devices"); - return; - } - String deviceName = device.getName(); - String deviceHardwareAddress = device.getAddress(); // MAC address + @SuppressLint("NotificationTrampoline") NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "CHANNEL_ID") + .setSmallIcon(android.R.drawable.ic_menu_info_details) + .setContentTitle("子供の置き去りをしていませんか?")//通知のタイトル + .setContentText("第三者からの通報が行われました。")//通知の本文 + .setContentIntent(pendingIntent)//通知をタップするとActivityへ移動する + .setAutoCancel(true)//通知をタップすると削除する + .setPriority(NotificationCompat.PRIORITY_HIGH) // プライオリティを高く設定 + .setVisibility(NotificationCompat.VISIBILITY_PUBLIC); // ロック画面に表示する - if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) { - //Do something if connected - Log.d("BT", "Device connected"); - - String registeredId = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).getString("bluetooth_device_id", "none"); - - Log.d("BT_Judge", "Registered: " + registeredId); - - if (deviceHardwareAddress.equals(registeredId)) { - Log.d("BT_Judge", "登録済み"); - } else Log.d("BT_Judge", "未登録"); - - } else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) { - //Do something if disconnected - Log.d("BT", "Device disconnected"); + // NotificationChannelの作成(Android 8.0以降) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + NotificationManager notificationManager = context.getSystemService(NotificationManager.class); + if (notificationManager != null) { + NotificationChannel channel = new NotificationChannel( + CHANNEL_ID, + "Channel Name", + NotificationManager.IMPORTANCE_HIGH + ); + channel.setDescription("Channel Description"); + channel.enableLights(true); + channel.setLightColor(Color.RED); + channel.enableVibration(true); + notificationManager.createNotificationChannel(channel); } } - }; - - private void audioStart(){ - //↓通知をする際に起動するバイブレーション - ((Vibrator) getSystemService(Context.VIBRATOR_SERVICE)).vibrate(1000); - //通知のやつ↓ - int importance = NotificationManager.IMPORTANCE_DEFAULT; - - NotificationChannel channel = new NotificationChannel("CHANNEL_ID", "通報通知", importance); - //説明・説明 ここに通知の説明を書くことができる↓ - channel.setDescription("第3者からの通報を検知しました"); - - NotificationManager notificationManager = getSystemService(NotificationManager.class); - notificationManager.createNotificationChannel(channel); - //通知のやつ↑ - Log.d("nt","レスポンスを検知しました2"); - //↓通知の詳細設定的な奴 - NotificationCompat.Builder builder = new NotificationCompat - - .Builder(this, "CHANNEL_ID") - .setSmallIcon(android.R.drawable.ic_menu_info_details) - .setContentTitle("通報検知") - .setContentText("子供の置き去りを検知しました。") - .setPriority(NotificationCompat.PRIORITY_DEFAULT); + NotificationManager notificationManager = (NotificationManager)context.getSystemService(context.NOTIFICATION_SERVICE); if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { - // TODO: Consider calling - // ActivityCompat#requestPermissions - // here to request the missing permissions, and then overriding - // public void onRequestPermissionsResult(int requestCode, String[] permissions, - // int[] grantResults) - // to handle the case where the user grants the permission. See the documentation - // for ActivityCompat#requestPermissions for more details. return; } - notificationManager.notify(R.string.app_name, builder.build()); - + notificationManager.notify(R.string.app_name, builder.build());//通知の表示 } + public void NotificationBluetooth(Context context, int time) {//実際に通知を行うメソッド + final String CHANNEL_ID = "my_channel_id"; + // 通知がクリックされたときに送信されるIntent + Intent intent = new Intent(context, MainActivity.class); + intent.setAction("OPEN_ACTIVITY"); + // PendingIntentの作成 + int requestCode = 100; + int flags = 0; + PendingIntent pendingIntent = PendingIntent.getActivity(context, requestCode, intent, flags | PendingIntent.FLAG_IMMUTABLE); + ((Vibrator) getSystemService(Context.VIBRATOR_SERVICE)).vibrate(2000);//バイブレーション + + @SuppressLint("NotificationTrampoline") NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "CHANNEL_ID") + .setSmallIcon(android.R.drawable.ic_menu_info_details) + .setContentTitle("子供の置き去りをしていませんか?")//通知のタイトル + .setContentText("Bluetootと車の切断から"+time+"分が経過しました")//通知の本文 + .setContentIntent(pendingIntent)//通知をタップするとActivityへ移動する + .setAutoCancel(true)//通知をタップすると削除する + .setPriority(NotificationCompat.PRIORITY_HIGH) // プライオリティを高く設定 + .setVisibility(NotificationCompat.VISIBILITY_PUBLIC); // ロック画面に表示する + + // NotificationChannelの作成(Android 8.0以降) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + NotificationManager notificationManager = context.getSystemService(NotificationManager.class); + if (notificationManager != null) { + NotificationChannel channel = new NotificationChannel( + CHANNEL_ID, + "Channel Name", + NotificationManager.IMPORTANCE_HIGH + ); + + channel.setDescription("Channel Description"); + channel.enableLights(true); + channel.setLightColor(Color.RED); + channel.enableVibration(true); + notificationManager.createNotificationChannel(channel); + } + } + + + NotificationManager notificationManager = (NotificationManager)context.getSystemService(context.NOTIFICATION_SERVICE); + if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { + return; + } + notificationManager.notify(R.string.app_name, builder.build());//通知の表示 + } + public class PeriodicTaskManager {//Bluetoothの切断後に乗車状態にならなかった場合に5分毎に通知を送るメソッド + + private static final long INTERVAL = 5 *60* 1000; //300秒 + private final Handler handler; + private final Runnable periodicTask; + + public PeriodicTaskManager() { + + handler = new Handler(Looper.getMainLooper()); + periodicTask = new Runnable() { + + public void run() { + + //共有プリファレンス全体の準備 + SharedPreferences sharedPreferences = getSharedPreferences("app_situation", MODE_PRIVATE); + + int time=sharedPreferences.getInt("time",0); + //共有プリファレンス 書き込みの準備 + SharedPreferences.Editor E = sharedPreferences.edit(); + if(time==0) {//Bluetoot切断からの時間経過(5分刻み) + E.putInt("time",5); + E.apply();; + }else { + E.putInt("time",time*2); + E.apply(); + } + + // 5分毎に実行される処理 + NotificationBluetooth(getApplicationContext(),time); + Log.d("PeriodicTask", "5分後に処理を実行します"); + + handler.postDelayed(this, INTERVAL); + } + }; + } + + public void startPeriodicTask() { + // 最初の実行 + handler.postDelayed(periodicTask,INTERVAL);//一回目は5分後に行う + } + + public void stopPeriodicTask() { + // 定期的な処理の停止 + handler.removeCallbacks(periodicTask); + } + } @Nullable @Override public IBinder onBind(Intent intent) { - - return null; } } \ No newline at end of file