Compare commits
	
		
			No commits in common. "main" and "improve/remove_unused_fragment" have entirely different histories.
		
	
	
		
			main
			...
			improve/re
		
	
		
@ -8,7 +8,6 @@
 | 
			
		||||
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
 | 
			
		||||
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
 | 
			
		||||
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
 | 
			
		||||
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
 | 
			
		||||
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
 | 
			
		||||
    <uses-permission android:name="android.permission.VIBRATE" />
 | 
			
		||||
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
 | 
			
		||||
@ -36,7 +35,7 @@
 | 
			
		||||
                <category android:name="android.intent.category.LAUNCHER" />
 | 
			
		||||
            </intent-filter>
 | 
			
		||||
        </activity>
 | 
			
		||||
        <service android:name=".SurveillanceService" />
 | 
			
		||||
        <service android:name=".TestService" />
 | 
			
		||||
    </application>
 | 
			
		||||
 | 
			
		||||
</manifest>
 | 
			
		||||
@ -20,7 +20,7 @@ import androidx.fragment.app.FragmentTransaction;
 | 
			
		||||
 * Use the {@link HomeFragment#newInstance} factory method to
 | 
			
		||||
 * create an instance of this fragment.
 | 
			
		||||
 */
 | 
			
		||||
public class HomeFragment extends Fragment  {
 | 
			
		||||
public class HomeFragment extends Fragment implements OnEventListener {
 | 
			
		||||
 | 
			
		||||
    // TODO: Rename parameter arguments, choose names that match
 | 
			
		||||
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
 | 
			
		||||
@ -31,9 +31,6 @@ public class HomeFragment extends Fragment  {
 | 
			
		||||
    private String str_key;
 | 
			
		||||
    private String mParam2;
 | 
			
		||||
 | 
			
		||||
    final String GET_ON = "\n乗車状態";
 | 
			
		||||
    final String GET_OFF = "\n降車状態";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public HomeFragment() {
 | 
			
		||||
        // Required empty public constructor
 | 
			
		||||
@ -82,35 +79,36 @@ public class HomeFragment extends Fragment  {
 | 
			
		||||
    public void onResume() {
 | 
			
		||||
        super.onResume();
 | 
			
		||||
        Log.d("HomeFragment", "onResume: called");
 | 
			
		||||
        Log.d("isIncar", "onResume: " + getIsInCarLocal());
 | 
			
		||||
        this.updateUiState(getIsInCarLocal());
 | 
			
		||||
        this.updateBluetoothSituation(isBluetoothConnected());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private boolean isBluetoothConnected() {
 | 
			
		||||
        SharedPreferences pref = requireActivity().getSharedPreferences("Bluetooth_situation", requireActivity().MODE_PRIVATE);
 | 
			
		||||
        return pref.getBoolean("status", false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private boolean getIsInCarLocal() {
 | 
			
		||||
        SharedPreferences pref = requireActivity().getSharedPreferences("app_situation", requireActivity().MODE_PRIVATE);
 | 
			
		||||
        Boolean isInCar = pref.getBoolean("isInCarPref", false);
 | 
			
		||||
        Log.d("isInCarPref","isInCar"+ isInCar);
 | 
			
		||||
        return isInCar;
 | 
			
		||||
        return pref.getBoolean("isInCar", false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //画面遷移メソッド
 | 
			
		||||
    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();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 乗車状態の画面を切り替える
 | 
			
		||||
     */
 | 
			
		||||
    private boolean updateUiState(boolean isInCar) {
 | 
			
		||||
        Log.d("HomeFragment", "updateUiState: called");
 | 
			
		||||
        Log.d("HomeFragment", "updateUiState:"+isInCar);
 | 
			
		||||
        // Init
 | 
			
		||||
        TextView tv;
 | 
			
		||||
        FrameLayout fl;
 | 
			
		||||
        try {
 | 
			
		||||
            tv = requireView().findViewById(R.id.car_situation);
 | 
			
		||||
            fl = requireView().findViewById(R.id.car_situation_bg);
 | 
			
		||||
            tv = requireView().findViewById(R.id.situation);
 | 
			
		||||
            fl = requireView().findViewById(R.id.situation_bg);
 | 
			
		||||
        } catch (NullPointerException e) {
 | 
			
		||||
            Log.d("HomeFragment", "updateUiState: view is null");
 | 
			
		||||
            return false;
 | 
			
		||||
@ -120,31 +118,29 @@ public class HomeFragment extends Fragment  {
 | 
			
		||||
            updateUiState(isInCar);
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (isInCar) {
 | 
			
		||||
        String get_on = "\n乗車状態";
 | 
			
		||||
        String get_off = "\n降車状態";
 | 
			
		||||
        if (!isInCar) {
 | 
			
		||||
            //乗車状態にする
 | 
			
		||||
            fl.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.frame_style_orange, null));
 | 
			
		||||
            tv.setText(GET_ON);
 | 
			
		||||
            tv.setText(get_on);
 | 
			
		||||
        } else {
 | 
			
		||||
            //降車状態にする
 | 
			
		||||
            fl.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.frame_style, null));
 | 
			
		||||
            tv.setText(GET_OFF);
 | 
			
		||||
            tv.setText(get_off);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Bluetoothの接続状態の画面を切り替える
 | 
			
		||||
     */
 | 
			
		||||
    boolean updateBluetoothSituation(Boolean BluetoothConnect) {
 | 
			
		||||
    private boolean updateBluetoothSituation(Boolean BluetoothConnect) {
 | 
			
		||||
        FrameLayout frameLayout;
 | 
			
		||||
        TextView textView;
 | 
			
		||||
        ImageView imageView;
 | 
			
		||||
        try {
 | 
			
		||||
            frameLayout = requireView().findViewById(R.id.situation_bg_bluetooth);
 | 
			
		||||
            textView = requireView().findViewById(R.id.BluetoothSituation);
 | 
			
		||||
            imageView = requireView().findViewById(R.id.BluetoothSituationImage);
 | 
			
		||||
            frameLayout = requireView().findViewById(R.id.situation_bg2);
 | 
			
		||||
            textView = requireView().findViewById(R.id.Bluetoothsituation);
 | 
			
		||||
            imageView = requireView().findViewById(R.id.Bluetoothsituationimage);
 | 
			
		||||
        } catch (NullPointerException e) {
 | 
			
		||||
            Log.d("HomeFragment", "updateUiState: view is null");
 | 
			
		||||
            return false;
 | 
			
		||||
@ -154,22 +150,41 @@ public class HomeFragment extends Fragment  {
 | 
			
		||||
            updateBluetoothSituation(BluetoothConnect);
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        final String CONNECT = "接続中";
 | 
			
		||||
        final String DISCONNECT = "切断中";
 | 
			
		||||
        String connect = "接続中";
 | 
			
		||||
        String disconnect = "切断中";
 | 
			
		||||
        if (BluetoothConnect) {
 | 
			
		||||
            //接続状態にする
 | 
			
		||||
            frameLayout.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.frame_style_orange, null));
 | 
			
		||||
            textView.setText(CONNECT);
 | 
			
		||||
            textView.setText(connect);
 | 
			
		||||
            imageView.setVisibility(View.GONE);
 | 
			
		||||
        } else {
 | 
			
		||||
            //切断状態にする
 | 
			
		||||
            //降車状態にする
 | 
			
		||||
            frameLayout.setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.frame_style, null));
 | 
			
		||||
            textView.setText(DISCONNECT);
 | 
			
		||||
            textView.setText(disconnect);
 | 
			
		||||
            imageView.setVisibility(View.VISIBLE);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean onEvent(boolean isInCar) {//乗車状態と降車状態の変更を受け取ってupdateUiState()に渡す
 | 
			
		||||
        Log.d("HomeFragment", "onEvent: called");
 | 
			
		||||
 | 
			
		||||
        return updateUiState(isInCar);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onEvent2(boolean BluetoothConnect) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean onEvent2(Boolean BluetoothConnect) {//Bluetoothの接続切断を受け取ってupdateBluetoothSituation()に渡す
 | 
			
		||||
        updateBluetoothSituation(BluetoothConnect);
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -14,6 +14,7 @@ import android.content.pm.PackageManager;
 | 
			
		||||
import android.graphics.Color;
 | 
			
		||||
import android.os.Build;
 | 
			
		||||
import android.os.Bundle;
 | 
			
		||||
import android.os.Handler;
 | 
			
		||||
import android.os.Vibrator;
 | 
			
		||||
import android.preference.PreferenceManager;
 | 
			
		||||
import android.util.Log;
 | 
			
		||||
@ -25,6 +26,7 @@ import androidx.annotation.NonNull;
 | 
			
		||||
import androidx.appcompat.app.AppCompatActivity;
 | 
			
		||||
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;
 | 
			
		||||
@ -32,6 +34,7 @@ import com.google.firebase.firestore.FirebaseFirestore;
 | 
			
		||||
import com.journeyapps.barcodescanner.ScanContract;
 | 
			
		||||
import com.journeyapps.barcodescanner.ScanOptions;
 | 
			
		||||
 | 
			
		||||
// Manifest
 | 
			
		||||
import android.Manifest;
 | 
			
		||||
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
@ -40,12 +43,16 @@ import java.util.Map;
 | 
			
		||||
public class MainActivity extends AppCompatActivity {
 | 
			
		||||
 | 
			
		||||
    FirebaseFirestore db;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    DocumentReference mDocRef;
 | 
			
		||||
 | 
			
		||||
    private HomeFragment homeFragment = HomeFragment.newInstance("test", "test");
 | 
			
		||||
    private HomeFragment homeFragment;
 | 
			
		||||
 | 
			
		||||
    public static final String TAG = "InspirationQuote";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private final ActivityResultLauncher<ScanOptions> QrLauncher = registerForActivityResult(
 | 
			
		||||
            new ScanContract(),
 | 
			
		||||
            result -> {
 | 
			
		||||
@ -67,13 +74,14 @@ public class MainActivity extends AppCompatActivity {
 | 
			
		||||
    protected void onCreate(Bundle savedInstanceState) {
 | 
			
		||||
        super.onCreate(savedInstanceState);
 | 
			
		||||
        setContentView(R.layout.activity_main);
 | 
			
		||||
        Log.d(TAG, "onCreate: called");
 | 
			
		||||
        //Bluetooth接続判定用
 | 
			
		||||
        SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
 | 
			
		||||
        SharedPreferences.Editor e = pref.edit();
 | 
			
		||||
        e.putBoolean("connection_status", false);
 | 
			
		||||
 | 
			
		||||
        // Check permissions
 | 
			
		||||
        //Bluetooth接続判定用
 | 
			
		||||
        SharedPreferences pref=PreferenceManager.getDefaultSharedPreferences(this);
 | 
			
		||||
        SharedPreferences.Editor e=pref.edit();
 | 
			
		||||
        e.putBoolean("connection_status",false);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        if (!hasPermissions()) {
 | 
			
		||||
            requestPermissions();
 | 
			
		||||
        }
 | 
			
		||||
@ -81,23 +89,19 @@ public class MainActivity extends AppCompatActivity {
 | 
			
		||||
        BottomNavigationView bottomNavigationView = findViewById(R.id.nav_view);
 | 
			
		||||
 | 
			
		||||
        this.homeFragment = HomeFragment.newInstance("test", "test");
 | 
			
		||||
        if (savedInstanceState == null) {
 | 
			
		||||
            getSupportFragmentManager().beginTransaction()
 | 
			
		||||
                    .replace(findViewById(R.id.fragmentContainerView).getId(), this.homeFragment)
 | 
			
		||||
                    .addToBackStack(null)
 | 
			
		||||
                    .commit();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        bottomNavigationView.setOnNavigationItemSelectedListener(v -> {
 | 
			
		||||
        bottomNavigationView.setOnNavigationItemSelectedListener(v ->
 | 
			
		||||
 | 
			
		||||
        {
 | 
			
		||||
            if (v.getItemId() == findViewById(R.id.navigation_home).getId()) {
 | 
			
		||||
                Log.d("MainActivity", "navigation_home: called");
 | 
			
		||||
                findViewById(R.id.fab_scan_qr_code).setVisibility(FrameLayout.VISIBLE);
 | 
			
		||||
                getSupportFragmentManager().beginTransaction()
 | 
			
		||||
                        .replace(findViewById(R.id.fragmentContainerView).getId(), this.homeFragment)
 | 
			
		||||
                        .addToBackStack(null)
 | 
			
		||||
                        .commit();
 | 
			
		||||
                firebaseLink();
 | 
			
		||||
 | 
			
		||||
            } else if (v.getItemId() == findViewById(R.id.navigation_settings).getId()) {
 | 
			
		||||
                Log.d("MainActivity", "navigation_settings: called");
 | 
			
		||||
                findViewById(R.id.fab_scan_qr_code).setVisibility(FrameLayout.GONE);
 | 
			
		||||
                getSupportFragmentManager().beginTransaction()
 | 
			
		||||
                        .replace(findViewById(R.id.fragmentContainerView).getId(), SettingFragment.newInstance())
 | 
			
		||||
@ -115,6 +119,7 @@ public class MainActivity extends AppCompatActivity {
 | 
			
		||||
            ScanOptions options = new ScanOptions();
 | 
			
		||||
            options.setPrompt("QRコードを読み取ってください");
 | 
			
		||||
            QrLauncher.launch(options);
 | 
			
		||||
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        //Bluetooth検知機能
 | 
			
		||||
@ -123,149 +128,96 @@ public class MainActivity extends AppCompatActivity {
 | 
			
		||||
        intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
 | 
			
		||||
 | 
			
		||||
        db = FirebaseFirestore.getInstance();//Firebaseとの紐づけ
 | 
			
		||||
 | 
			
		||||
        String btPermission = getBluetoothConnectPermission();
 | 
			
		||||
        if (ActivityCompat.checkSelfPermission(this, btPermission) != PackageManager.PERMISSION_GRANTED) {
 | 
			
		||||
        if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
 | 
			
		||||
            Log.d("BT", "No permission to connect bluetooth devices");
 | 
			
		||||
            return;
 | 
			
		||||
        } else {
 | 
			
		||||
            Log.d("BT", "Permission to connect bluetooth devices granted");
 | 
			
		||||
 | 
			
		||||
            registerReceiver(receiver, intentFilter);
 | 
			
		||||
 | 
			
		||||
            startForegroundService(new Intent(this, SurveillanceService.class));
 | 
			
		||||
        }
 | 
			
		||||
        registerReceiver(receiver, intentFilter);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void onResume() {
 | 
			
		||||
        super.onResume();
 | 
			
		||||
        Log.d("MainActivity onResume", "called");
 | 
			
		||||
        Log.d("onResume", "called");
 | 
			
		||||
        Log.d("onResume", "mDocRef is null");
 | 
			
		||||
        firebaseLink();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 権限チェック用ヘルパーメソッドを追加
 | 
			
		||||
    private String getBluetoothConnectPermission() {
 | 
			
		||||
        return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) ?
 | 
			
		||||
                Manifest.permission.BLUETOOTH_CONNECT :
 | 
			
		||||
                Manifest.permission.BLUETOOTH;
 | 
			
		||||
        private void initNotification(DocumentReference mDocRef) {//サイト上で押されたボタンの管理
 | 
			
		||||
        // 共有プリファレンス全体の準備
 | 
			
		||||
        SharedPreferences sharedPreferences = getSharedPreferences("app_situation", MODE_PRIVATE);
 | 
			
		||||
 | 
			
		||||
        mDocRef.addSnapshotListener(this, (documentSnapshot, e) -> {
 | 
			
		||||
 | 
			
		||||
            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")) {//isReportedがfalseのとき=サイト上で保護者ボタンが押されたとき
 | 
			
		||||
                    if (fragment instanceof HomeFragment) {//fragmentがHomeFragmentのインスタンスかの判定
 | 
			
		||||
//                        changes-situation();//  changes-situation()メソッドを処理→アプリ側の乗降状態を変化
 | 
			
		||||
                        ((HomeFragment) fragment).onEvent(!isInCar);
 | 
			
		||||
                    }
 | 
			
		||||
                } 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", "何もなし");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 乗車状態の変更
 | 
			
		||||
     */
 | 
			
		||||
    public void changeIsInCar() {
 | 
			
		||||
        SharedPreferences sharedPreferences = MainActivity.this.getSharedPreferences("app_situation", MODE_PRIVATE);
 | 
			
		||||
        SharedPreferences.Editor E = sharedPreferences.edit();
 | 
			
		||||
        SharedPreferences.Editor E2 = sharedPreferences.edit();
 | 
			
		||||
        String IdPref = sharedPreferences.getString("ID", null);//アプリに記録されているIDの取得
 | 
			
		||||
        Log.d("MainActivity", "changeIsInCar: ID= " + IdPref);
 | 
			
		||||
        boolean change = sharedPreferences.getBoolean("change", false);
 | 
			
		||||
        Log.d("MainActivity", "changeIsInCar: " + change);
 | 
			
		||||
        db = FirebaseFirestore.getInstance();//Firebaseとの紐づけ
 | 
			
		||||
        DocumentReference isReported = db.collection("status").document(IdPref);//更新するドキュメントとの紐づけ
 | 
			
		||||
        Map<String, Boolean> DEFAULT_ITEM = new HashMap<>();//mapの宣言
 | 
			
		||||
        if (!change) {
 | 
			
		||||
            //isInCarをtrueに更新
 | 
			
		||||
            Log.d("MainActivity", "change:" + change);
 | 
			
		||||
            E.putBoolean("change", true);
 | 
			
		||||
            E.apply();
 | 
			
		||||
            Log.d("MainActivity", "change:" + sharedPreferences.getBoolean("change", false));
 | 
			
		||||
        } else {
 | 
			
		||||
            Log.d("MainActivity", "change:" + change);
 | 
			
		||||
            E.putBoolean("change", false);
 | 
			
		||||
            E.apply();
 | 
			
		||||
            Log.d("MainActivity", "change:" + sharedPreferences.getBoolean("change", false));
 | 
			
		||||
        }
 | 
			
		||||
        Log.d("MainActivity", "changeIsInCar: " + sharedPreferences.getBoolean("change", false));
 | 
			
		||||
        isReported.update("isInCar", sharedPreferences.getBoolean("change", false))
 | 
			
		||||
                .addOnSuccessListener(unused -> Log.d(TAG, "DocumentSnapshot successfully updated!!"))
 | 
			
		||||
                .addOnFailureListener(e -> Log.w(TAG, "Error updating document", e));
 | 
			
		||||
        E2.putBoolean("isInCarPref", sharedPreferences.getBoolean("change", false));
 | 
			
		||||
        E2.apply();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 権限の保有を確認する
 | 
			
		||||
     * @return
 | 
			
		||||
     */
 | 
			
		||||
    private boolean hasPermissions() {
 | 
			
		||||
        boolean allGranted = true;
 | 
			
		||||
 | 
			
		||||
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
 | 
			
		||||
            // <= Android 11 (API 30)
 | 
			
		||||
            allGranted &= (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH)
 | 
			
		||||
                    == PackageManager.PERMISSION_GRANTED);
 | 
			
		||||
            allGranted &= (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_ADMIN)
 | 
			
		||||
                    == PackageManager.PERMISSION_GRANTED);
 | 
			
		||||
        } else {
 | 
			
		||||
            // >= Android 12 (API 31)
 | 
			
		||||
            allGranted &= (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN)
 | 
			
		||||
                    == PackageManager.PERMISSION_GRANTED);
 | 
			
		||||
            allGranted &= (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT)
 | 
			
		||||
                    == PackageManager.PERMISSION_GRANTED);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Location
 | 
			
		||||
        allGranted &= (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
 | 
			
		||||
                == PackageManager.PERMISSION_GRANTED);
 | 
			
		||||
        allGranted &= (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
 | 
			
		||||
                == PackageManager.PERMISSION_GRANTED);
 | 
			
		||||
 | 
			
		||||
        // >= Android 13 (API 32)
 | 
			
		||||
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
 | 
			
		||||
            allGranted &= (ActivityCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS)
 | 
			
		||||
                    == PackageManager.PERMISSION_GRANTED);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Others
 | 
			
		||||
        allGranted &= (ActivityCompat.checkSelfPermission(this, Manifest.permission.VIBRATE)
 | 
			
		||||
                == PackageManager.PERMISSION_GRANTED);
 | 
			
		||||
        allGranted &= (ActivityCompat.checkSelfPermission(this, Manifest.permission.FOREGROUND_SERVICE)
 | 
			
		||||
                == PackageManager.PERMISSION_GRANTED);
 | 
			
		||||
 | 
			
		||||
        return allGranted;
 | 
			
		||||
        return ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH) == PackageManager.PERMISSION_GRANTED &&
 | 
			
		||||
                ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_ADMIN) == PackageManager.PERMISSION_GRANTED &&
 | 
			
		||||
                ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) == PackageManager.PERMISSION_GRANTED &&
 | 
			
		||||
                ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED &&
 | 
			
		||||
                ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED &&
 | 
			
		||||
                ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED &&
 | 
			
		||||
                ActivityCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED &&
 | 
			
		||||
                ActivityCompat.checkSelfPermission(this, Manifest.permission.VIBRATE) == PackageManager.PERMISSION_GRANTED &&
 | 
			
		||||
                ActivityCompat.checkSelfPermission(this, Manifest.permission.FOREGROUND_SERVICE) == PackageManager.PERMISSION_GRANTED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 権限のリクエストを行う
 | 
			
		||||
     */
 | 
			
		||||
    private void requestPermissions() {
 | 
			
		||||
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
 | 
			
		||||
            // <= Android 11 (API 30)
 | 
			
		||||
            ActivityCompat.requestPermissions(this,
 | 
			
		||||
                    new String[]{
 | 
			
		||||
                            Manifest.permission.BLUETOOTH,
 | 
			
		||||
                            Manifest.permission.BLUETOOTH_ADMIN,
 | 
			
		||||
                            Manifest.permission.ACCESS_FINE_LOCATION,
 | 
			
		||||
                            Manifest.permission.ACCESS_COARSE_LOCATION,
 | 
			
		||||
                            Manifest.permission.VIBRATE,
 | 
			
		||||
                            Manifest.permission.FOREGROUND_SERVICE,
 | 
			
		||||
                    },
 | 
			
		||||
                    2
 | 
			
		||||
            );
 | 
			
		||||
        } else {
 | 
			
		||||
            // >= Android 12 (API 31)
 | 
			
		||||
            ActivityCompat.requestPermissions(this,
 | 
			
		||||
                    new String[]{
 | 
			
		||||
                            Manifest.permission.BLUETOOTH_SCAN,
 | 
			
		||||
                            Manifest.permission.BLUETOOTH_CONNECT,
 | 
			
		||||
                            Manifest.permission.ACCESS_FINE_LOCATION,
 | 
			
		||||
                            Manifest.permission.ACCESS_COARSE_LOCATION,
 | 
			
		||||
                            Manifest.permission.POST_NOTIFICATIONS,
 | 
			
		||||
                            Manifest.permission.VIBRATE,
 | 
			
		||||
                            Manifest.permission.FOREGROUND_SERVICE
 | 
			
		||||
                    },
 | 
			
		||||
                    2
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
        ActivityCompat.requestPermissions(this,
 | 
			
		||||
                new String[]{
 | 
			
		||||
                        Manifest.permission.BLUETOOTH,
 | 
			
		||||
                        Manifest.permission.BLUETOOTH_ADMIN,
 | 
			
		||||
                        Manifest.permission.BLUETOOTH_SCAN,
 | 
			
		||||
                        Manifest.permission.BLUETOOTH_CONNECT,
 | 
			
		||||
                        Manifest.permission.ACCESS_FINE_LOCATION,
 | 
			
		||||
                        Manifest.permission.ACCESS_COARSE_LOCATION,
 | 
			
		||||
                        Manifest.permission.POST_NOTIFICATIONS,
 | 
			
		||||
                        Manifest.permission.VIBRATE,
 | 
			
		||||
                        Manifest.permission.FOREGROUND_SERVICE
 | 
			
		||||
                },
 | 
			
		||||
                2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onRequestPermissionsResult(int requestCode,
 | 
			
		||||
                                           @NonNull String[] permissions,
 | 
			
		||||
                                           @NonNull int[] grantResults) {
 | 
			
		||||
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
 | 
			
		||||
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
 | 
			
		||||
        if (requestCode == 2) {
 | 
			
		||||
            if (!hasPermissions()) {
 | 
			
		||||
@ -274,27 +226,175 @@ public class MainActivity extends AppCompatActivity {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * FireBaseのIDの取得
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public void firebaseLink() {//Firebaseのドキュメントの取得
 | 
			
		||||
        Log.d("MainActivity", "firebaseLink: called");
 | 
			
		||||
        //共有プリファレンス全体の準備
 | 
			
		||||
        SharedPreferences sharedPreferences = getSharedPreferences("app_situation", MODE_PRIVATE);
 | 
			
		||||
        String IdPref = sharedPreferences.getString("ID", null);//アプリに記録されているIDの取得
 | 
			
		||||
        if (IdPref == null) {
 | 
			
		||||
        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<String, Boolean> 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 changeIsInCar() {
 | 
			
		||||
        //共有プリファレンス全体の準備
 | 
			
		||||
        SharedPreferences sharedPreferences = MainActivity.this.getSharedPreferences("app_situation", MODE_PRIVATE);
 | 
			
		||||
        //共有プリファレンス 書き込みの準備
 | 
			
		||||
        SharedPreferences.Editor E = sharedPreferences.edit();
 | 
			
		||||
        String IdPref = sharedPreferences.getString("ID", null);//アプリに記録されているIDの取得
 | 
			
		||||
        Boolean change=sharedPreferences.getBoolean("change",false);
 | 
			
		||||
        db = FirebaseFirestore.getInstance();//Firebaseとの紐づけ
 | 
			
		||||
        DocumentReference isReported = db.collection("status").document(IdPref);//更新するドキュメントとの紐づけ
 | 
			
		||||
        Map<String, Boolean> DEFAULT_ITEM = new HashMap<>();//mapの宣言
 | 
			
		||||
        if (!change) {
 | 
			
		||||
            //isInCarをtrueに更新
 | 
			
		||||
            E.putBoolean("change",true);
 | 
			
		||||
        }else{
 | 
			
		||||
            E.putBoolean("change",false);
 | 
			
		||||
        }
 | 
			
		||||
        isReported.update("isInCar", change).addOnSuccessListener(unused -> Log.d(TAG, "DocumentSnapshot successfully updated!")).addOnFailureListener(e -> Log.w(TAG, "Error updating document", e));
 | 
			
		||||
        E.apply();
 | 
			
		||||
    }
 | 
			
		||||
    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("第三者からの通報が行われました。")//通知の本文
 | 
			
		||||
                .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());//通知の表示
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onStop() {//アプリをバックグラウンドにした時のメソッド
 | 
			
		||||
        super.onStop();
 | 
			
		||||
        Intent intent = new Intent(getApplication(), TestService.class);
 | 
			
		||||
        startService(intent);//TestServiceを起動
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void NotificationBluetooth(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("Bluetoothと車の切断から5分が経過しました")//通知の本文
 | 
			
		||||
                .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 void Bluetooth_status() {
 | 
			
		||||
        IntentFilter intentFilter = new IntentFilter();
 | 
			
		||||
        intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
 | 
			
		||||
        intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
 | 
			
		||||
 | 
			
		||||
        String btPermission = getBluetoothConnectPermission();
 | 
			
		||||
        if (ActivityCompat.checkSelfPermission(this, btPermission) != PackageManager.PERMISSION_GRANTED) {
 | 
			
		||||
        if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
 | 
			
		||||
            Log.d("BT", "No permission to connect bluetooth devices");
 | 
			
		||||
            return;
 | 
			
		||||
        } else {
 | 
			
		||||
@ -303,26 +403,33 @@ public class MainActivity extends AppCompatActivity {
 | 
			
		||||
        registerReceiver(receiver, intentFilter);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private final BroadcastReceiver receiver = new BroadcastReceiver() {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        //PreferenceManager.getDefaultSharedPreferences("myPreferences",Context.MODE_PRIVATE);
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public void onReceive(Context context, Intent intent) {
 | 
			
		||||
            SharedPreferences pref = getSharedPreferences("Bluetooth_situation", MODE_PRIVATE);
 | 
			
		||||
            SharedPreferences.Editor e = pref.edit();
 | 
			
		||||
            String action = intent.getAction();
 | 
			
		||||
            SharedPreferences pref=getSharedPreferences("Bluetooth_situation",MODE_PRIVATE);
 | 
			
		||||
            SharedPreferences.Editor e=pref.edit();
 | 
			
		||||
            String action = intent.getAction(); // may need to chain this to a recognizing function
 | 
			
		||||
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
 | 
			
		||||
            boolean isInCar = pref.getBoolean("isInCarPref", false);
 | 
			
		||||
            String btPermission = getBluetoothConnectPermission();
 | 
			
		||||
            if (ActivityCompat.checkSelfPermission(context, btPermission) != PackageManager.PERMISSION_GRANTED) {
 | 
			
		||||
            Boolean isInCar = pref.getBoolean("isInCarPref", false);
 | 
			
		||||
            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
 | 
			
		||||
 | 
			
		||||
            String registeredId = PreferenceManager.getDefaultSharedPreferences(getApplicationContext())
 | 
			
		||||
                    .getString("bluetooth_device_id", "none");
 | 
			
		||||
            String registeredId = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).getString("bluetooth_device_id", "none");
 | 
			
		||||
 | 
			
		||||
            if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
 | 
			
		||||
                //Do something if connected
 | 
			
		||||
                //Bluetoothデバイスが接続されたときの処理
 | 
			
		||||
                e.putBoolean("change", true);
 | 
			
		||||
                e.apply();
 | 
			
		||||
                changeBluetooth();//HomeFragmentの表示を接続にする
 | 
			
		||||
                Log.d("BT", "Device connected");
 | 
			
		||||
 | 
			
		||||
                Log.d("BT_Judge", "Registered: " + registeredId);
 | 
			
		||||
@ -330,35 +437,46 @@ public class MainActivity extends AppCompatActivity {
 | 
			
		||||
                if (deviceHardwareAddress.equals(registeredId)) {
 | 
			
		||||
                    //登録済みのデバイスだったときの処理
 | 
			
		||||
                    Log.d("BT_Judge", "登録済み");
 | 
			
		||||
                    changeBluetooth(true);
 | 
			
		||||
                    e.putBoolean("connection_status", true);
 | 
			
		||||
                    if (homeFragment != null && homeFragment.isVisible()) {
 | 
			
		||||
                        homeFragment.updateBluetoothSituation(true);
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    e.putBoolean("connection_status",true);
 | 
			
		||||
 | 
			
		||||
                } else{
 | 
			
		||||
                    //登録していないデバイスだったときの処理
 | 
			
		||||
                    Log.d("BT_Judge", "未登録");
 | 
			
		||||
                    e.putBoolean("connection_status", false);
 | 
			
		||||
                    e.putBoolean("connection_status",false);
 | 
			
		||||
                }
 | 
			
		||||
                e.apply();
 | 
			
		||||
 | 
			
		||||
            } else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
 | 
			
		||||
                //bluetoothデバイスが切断されたときの処理
 | 
			
		||||
                changeBluetooth(false);
 | 
			
		||||
                if (homeFragment != null && homeFragment.isVisible()) {
 | 
			
		||||
                    homeFragment.updateBluetoothSituation(false);
 | 
			
		||||
            } else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)&&!isInCar) {//bluetoothが切断されたときに乗車状態のとき
 | 
			
		||||
 | 
			
		||||
                //Do something if disconnected
 | 
			
		||||
                //デバイスが切断されたときの処理
 | 
			
		||||
                e.putBoolean("change", false);
 | 
			
		||||
                e.apply();
 | 
			
		||||
                changeBluetooth();//HomeFragmentの表示を切断にする
 | 
			
		||||
                if (deviceHardwareAddress.equals(registeredId)) {
 | 
			
		||||
                    // 5分待機する
 | 
			
		||||
                    Handler handler = new Handler();
 | 
			
		||||
                    handler.postDelayed(new Runnable() {
 | 
			
		||||
                        @Override
 | 
			
		||||
                        public void run() {
 | 
			
		||||
                            if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)&&!isInCar) {//その後bluetoothを再接続したり降車状態になったりしていない=置き去りが発生した可能性大
 | 
			
		||||
                                NotificationBluetooth(getApplicationContext());//通知を行うメソッド
 | 
			
		||||
                            }}
 | 
			
		||||
 | 
			
		||||
                    }, 5 *60*1000); // 5分をミリ秒に変換
 | 
			
		||||
                }
 | 
			
		||||
            }else {
 | 
			
		||||
                Log.d("BT", "Device disconnected");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Bluetoothの接続状態を変更するメソッド
 | 
			
		||||
     */
 | 
			
		||||
    public void changeBluetooth(boolean actual) {
 | 
			
		||||
        getSharedPreferences("Bluetooth_situation", MODE_PRIVATE)
 | 
			
		||||
                .edit()
 | 
			
		||||
                .putBoolean("status", actual)
 | 
			
		||||
                .apply();
 | 
			
		||||
    public void changeBluetooth(){
 | 
			
		||||
        SharedPreferences pref=getSharedPreferences("Bluetooth_situation",MODE_PRIVATE);
 | 
			
		||||
        SharedPreferences.Editor e=pref.edit();
 | 
			
		||||
        Boolean BluetoothConnect = pref.getBoolean("change", false);
 | 
			
		||||
        Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragmentContainerView);
 | 
			
		||||
        ((HomeFragment) fragment).onEvent2(BluetoothConnect);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -3,4 +3,8 @@ package com.example.childguard;
 | 
			
		||||
public interface OnEventListener {
 | 
			
		||||
 | 
			
		||||
    boolean onEvent(boolean state);
 | 
			
		||||
 | 
			
		||||
    void onEvent2(boolean BluetoothConnect);
 | 
			
		||||
 | 
			
		||||
    boolean onEvent2(Boolean BluetoothConnect);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -53,15 +53,15 @@ public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ItemVi
 | 
			
		||||
                    .setMessage("このデバイスを登録しますか?")
 | 
			
		||||
                    .setPositiveButton(android.R.string.ok, (dialog, which) -> {
 | 
			
		||||
                        // OK button pressed
 | 
			
		||||
//                        Toast.makeText(v.getContext(), "OK button clicked", Toast.LENGTH_SHORT).show();
 | 
			
		||||
                        Toast.makeText(v.getContext(), "OK button clicked", Toast.LENGTH_SHORT).show();
 | 
			
		||||
                        //共有プリファレンスに保存
 | 
			
		||||
                        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this.applicationContext);
 | 
			
		||||
                        sharedPreferences.edit().putString("bluetooth_device_id", deviceList.get(position)[1]).apply();
 | 
			
		||||
                        sharedPreferences.edit().putString("bluetooth_device_name", deviceList.get(position)[0]).apply();
 | 
			
		||||
//                        Toast.makeText(v.getContext(), PreferenceManager.getDefaultSharedPreferences(this.applicationContext).getString("bluetooth_device_id", "none"), Toast.LENGTH_SHORT).show();
 | 
			
		||||
                        Toast.makeText(v.getContext(), PreferenceManager.getDefaultSharedPreferences(this.applicationContext).getString("bluetooth_device_id", "none"), Toast.LENGTH_SHORT).show();
 | 
			
		||||
 | 
			
		||||
                        TextView textView = this.parentView.findViewById(R.id.registered_device);
 | 
			
		||||
                        textView.setText(PreferenceManager.getDefaultSharedPreferences(this.applicationContext).getString("bluetooth_device_name", "登録されていません"));
 | 
			
		||||
                        textView.setText(PreferenceManager.getDefaultSharedPreferences(this.applicationContext).getString("bluetooth_device_name", "none"));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                    })
 | 
			
		||||
 | 
			
		||||
@ -3,8 +3,6 @@ package com.example.childguard;
 | 
			
		||||
import static android.content.ContentValues.TAG;
 | 
			
		||||
import static android.content.Context.MODE_PRIVATE;
 | 
			
		||||
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.content.Intent;
 | 
			
		||||
import android.content.SharedPreferences;
 | 
			
		||||
import android.os.Bundle;
 | 
			
		||||
import android.util.Log;
 | 
			
		||||
@ -97,7 +95,6 @@ public class SettingFragment extends Fragment {
 | 
			
		||||
                            SharedPreferences.Editor editor = sharedPreferences1.edit();
 | 
			
		||||
                            editor.putString("ID", documentReference.getId());
 | 
			
		||||
                            editor.apply();
 | 
			
		||||
                            startTestService();
 | 
			
		||||
 | 
			
		||||
                            Toast.makeText(getActivity(), "初回登録", Toast.LENGTH_SHORT).show();
 | 
			
		||||
                            getParentFragmentManager().beginTransaction().addToBackStack(null).replace(R.id.fragmentContainerView, GenerateQrFragment.newInstance(documentReference.getId())).commit();
 | 
			
		||||
@ -109,11 +106,4 @@ public class SettingFragment extends Fragment {
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    private void startTestService() {
 | 
			
		||||
        Context context = getContext();
 | 
			
		||||
        if (context != null) {
 | 
			
		||||
            Intent serviceIntent = new Intent(context, SurveillanceService.class);
 | 
			
		||||
            context.startForegroundService(serviceIntent);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,376 +0,0 @@
 | 
			
		||||
package com.example.childguard;
 | 
			
		||||
 | 
			
		||||
import android.Manifest;
 | 
			
		||||
import android.app.Notification;
 | 
			
		||||
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.IntentFilter;
 | 
			
		||||
import android.content.SharedPreferences;
 | 
			
		||||
import android.content.pm.PackageManager;
 | 
			
		||||
import android.os.Build;
 | 
			
		||||
import android.os.Handler;
 | 
			
		||||
import android.os.IBinder;
 | 
			
		||||
import android.os.VibrationEffect;
 | 
			
		||||
import android.os.Vibrator;
 | 
			
		||||
import android.preference.PreferenceManager;
 | 
			
		||||
import android.util.Log;
 | 
			
		||||
 | 
			
		||||
import androidx.annotation.Nullable;
 | 
			
		||||
import androidx.core.app.ActivityCompat;
 | 
			
		||||
import androidx.core.app.NotificationCompat;
 | 
			
		||||
import androidx.core.app.NotificationManagerCompat;
 | 
			
		||||
 | 
			
		||||
import com.google.firebase.firestore.DocumentReference;
 | 
			
		||||
import com.google.firebase.firestore.FirebaseFirestore;
 | 
			
		||||
 | 
			
		||||
public class SurveillanceService extends Service {
 | 
			
		||||
 | 
			
		||||
    private final Handler handler = new Handler();
 | 
			
		||||
    private Runnable notificationRunnable;
 | 
			
		||||
 | 
			
		||||
    public static class NotificationContent {
 | 
			
		||||
        private final String title;
 | 
			
		||||
        private final String description;
 | 
			
		||||
        private final String channelId;
 | 
			
		||||
        private final int notificationId;
 | 
			
		||||
 | 
			
		||||
        public NotificationContent(String title, String description, String channelId, int notificationId) {
 | 
			
		||||
            this.title = title;
 | 
			
		||||
            this.description = description;
 | 
			
		||||
            this.channelId = channelId;
 | 
			
		||||
            this.notificationId = notificationId;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public String getTitle() {
 | 
			
		||||
            return title;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public String getDescription() {
 | 
			
		||||
            return description;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public String getChannelId() {
 | 
			
		||||
            return channelId;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public int getNotificationId() {
 | 
			
		||||
            return notificationId;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static final String TAG = "InspirationQuote";
 | 
			
		||||
    private static final String BT_ALERT_CHANNEL_ID = "child_guard_bt_alert";
 | 
			
		||||
    private static final String REPORTED_CHANNEL_ID = "child_guard_reported";
 | 
			
		||||
    private static final String BACKGROUND_CHANNEL_ID = "child_guard_background";
 | 
			
		||||
    private static final int REQUEST_CODE = 100;
 | 
			
		||||
    private static final int NOTIFICATION_DELAY = 5 * 60 * 1000; // 5 minutes
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private static final NotificationContent REPORTED_NOTIFICATION =
 | 
			
		||||
            new NotificationContent("子供の置き去りをしていませんか?", "第三者からの通報が行われました。", REPORTED_CHANNEL_ID, 2);
 | 
			
		||||
    private static final NotificationContent BLUETOOTH_NOTIFICATION =
 | 
			
		||||
            new NotificationContent("子供の置き去りをしていませんか?🐈", "Bluetoothと車の切断から5分が経過しました", BT_ALERT_CHANNEL_ID, 3);
 | 
			
		||||
 | 
			
		||||
    private String userId = null;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int onStartCommand(Intent intent, int flags, int startId) {
 | 
			
		||||
        Log.d(TAG, "onStartCommand: ");
 | 
			
		||||
        this.userId = getSharedPreferences("app_situation", MODE_PRIVATE).getString("ID", null);
 | 
			
		||||
        if (this.userId == null) {
 | 
			
		||||
            Log.d("onResume", "ID not initialized.");
 | 
			
		||||
            return flags; // IDが初期化されていない場合は何もしない
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (isNotificationChannelCreated(BACKGROUND_CHANNEL_ID)) {
 | 
			
		||||
            createRunningNotificationChannel();
 | 
			
		||||
        }
 | 
			
		||||
        Intent notificationIntent = new Intent(this, MainActivity.class);
 | 
			
		||||
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE);
 | 
			
		||||
        Notification notification = new NotificationCompat.Builder(this, BACKGROUND_CHANNEL_ID)
 | 
			
		||||
                .setContentTitle("ChildGuardバックグラウンドサービス")
 | 
			
		||||
                .setContentText("接続/通報監視サービスがバックグラウンドで実行されています")
 | 
			
		||||
                .setSmallIcon(android.R.drawable.ic_menu_info_details)
 | 
			
		||||
                .setContentIntent(pendingIntent)
 | 
			
		||||
                .build();
 | 
			
		||||
        startForeground(1, notification);
 | 
			
		||||
 | 
			
		||||
        setSnapshotListener(FirebaseFirestore.getInstance().document("status/" + this.userId));
 | 
			
		||||
 | 
			
		||||
        if (isNotBluetoothGranted()) return flags;
 | 
			
		||||
 | 
			
		||||
        registerReceiver(receiver);
 | 
			
		||||
        return START_STICKY;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onCreate() {
 | 
			
		||||
        super.onCreate();
 | 
			
		||||
        if (isNotificationChannelCreated(BT_ALERT_CHANNEL_ID)) createAlertNotificationChannel(BT_ALERT_CHANNEL_ID);
 | 
			
		||||
        if (isNotificationChannelCreated(REPORTED_CHANNEL_ID)) createAlertNotificationChannel(REPORTED_CHANNEL_ID);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 通知チャネルが作成されているか確認
 | 
			
		||||
     * @return 通知チャンネルの有無 true: 作成済み false: 未作成
 | 
			
		||||
     */
 | 
			
		||||
    private boolean isNotificationChannelCreated(String channelId) {
 | 
			
		||||
        NotificationManager notificationManager = getSystemService(NotificationManager.class);
 | 
			
		||||
        return notificationManager.getNotificationChannel(channelId) == null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 通知チャネルの作成
 | 
			
		||||
     */
 | 
			
		||||
    private void createAlertNotificationChannel(String channelId) {
 | 
			
		||||
        int importance = NotificationManager.IMPORTANCE_DEFAULT;
 | 
			
		||||
        NotificationChannel channel = new NotificationChannel(channelId, "通知", importance);
 | 
			
		||||
        channel.setDescription("第三者により置き去りの通報が行われたときに通知します。");
 | 
			
		||||
        NotificationManager notificationManager = getSystemService(NotificationManager.class);
 | 
			
		||||
        notificationManager.createNotificationChannel(channel);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * バックグラウンドで実行中の通知チャネルを作成
 | 
			
		||||
     */
 | 
			
		||||
    private void createRunningNotificationChannel() {
 | 
			
		||||
        NotificationChannel serviceChannel = new NotificationChannel(
 | 
			
		||||
                BACKGROUND_CHANNEL_ID,
 | 
			
		||||
                "Foreground Service Channel",
 | 
			
		||||
                NotificationManager.IMPORTANCE_NONE
 | 
			
		||||
        );
 | 
			
		||||
        NotificationManager manager = getSystemService(NotificationManager.class);
 | 
			
		||||
        if (manager != null) {
 | 
			
		||||
            manager.createNotificationChannel(serviceChannel);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 通知が許可がされているかどうかを確認
 | 
			
		||||
     * @return 通知の許可の有無 true: 許可されていない false: 許可されている
 | 
			
		||||
     */
 | 
			
		||||
    private boolean isNotNotificationEnabled() {
 | 
			
		||||
        NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(this);
 | 
			
		||||
        if (!notificationManagerCompat.areNotificationsEnabled()) {
 | 
			
		||||
            Log.d(TAG, "通知が許可されていません");
 | 
			
		||||
            return true;
 | 
			
		||||
        } else {
 | 
			
		||||
            Log.d(TAG, "通知が許可されています");
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Bluetoothの権限が許可されているかどうかを確認
 | 
			
		||||
     * @return Bluetoothの権限の有無 true: 許可されていない false: 許可されている
 | 
			
		||||
     */
 | 
			
		||||
    private boolean isNotBluetoothGranted() {
 | 
			
		||||
        String btPermission = getBluetoothConnectPermission();
 | 
			
		||||
        if (ActivityCompat.checkSelfPermission(this, btPermission) != PackageManager.PERMISSION_GRANTED) {
 | 
			
		||||
            Log.d(TAG, "Bluetoothの権限が許可されていません");
 | 
			
		||||
            return true;
 | 
			
		||||
        } else {
 | 
			
		||||
            Log.d(TAG, "Bluetoothの権限が許可されています");
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * ブロードキャストレシーバーを登録
 | 
			
		||||
     * @param receiver ブロードキャストレシーバー
 | 
			
		||||
     */
 | 
			
		||||
    private void registerReceiver(BroadcastReceiver receiver) {
 | 
			
		||||
        IntentFilter intentFilter = new IntentFilter();
 | 
			
		||||
        intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
 | 
			
		||||
        intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
 | 
			
		||||
 | 
			
		||||
        registerReceiver(receiver, intentFilter);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Bluetoothの接続権限を取得
 | 
			
		||||
     * @return Bluetoothの接続権限
 | 
			
		||||
     */
 | 
			
		||||
    private String getBluetoothConnectPermission() {
 | 
			
		||||
        return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) ?
 | 
			
		||||
                android.Manifest.permission.BLUETOOTH_CONNECT :
 | 
			
		||||
                Manifest.permission.BLUETOOTH;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Firestoreのスナップショットリスナーを設定
 | 
			
		||||
     * @param mDocRef Firestoreのドキュメントリファレンス
 | 
			
		||||
     */
 | 
			
		||||
    private void setSnapshotListener(DocumentReference mDocRef) {
 | 
			
		||||
        // Initialize the PeriodicTaskManager
 | 
			
		||||
        // (Assuming it's done elsewhere as it's not shown in the original code)
 | 
			
		||||
 | 
			
		||||
        // Prepare SharedPreferences
 | 
			
		||||
        SharedPreferences sharedPreferences = getSharedPreferences("app_situation", MODE_PRIVATE);
 | 
			
		||||
 | 
			
		||||
        // Add a snapshot listener to the document reference
 | 
			
		||||
        mDocRef.addSnapshotListener((documentSnapshot, e) -> {
 | 
			
		||||
            if (e != null) {
 | 
			
		||||
                Log.w("nt", "Listen failed.", e);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (documentSnapshot != null && documentSnapshot.exists()) {
 | 
			
		||||
                Log.d("nt", "イベント開始");
 | 
			
		||||
 | 
			
		||||
                // Handle document snapshot
 | 
			
		||||
                SharedPreferences.Editor editor = sharedPreferences.edit();
 | 
			
		||||
                boolean isInCar = sharedPreferences.getBoolean("isInCarPref", false);
 | 
			
		||||
                boolean newIsInCarState = Boolean.TRUE.equals(documentSnapshot.getBoolean("isInCar"));
 | 
			
		||||
 | 
			
		||||
                editor.putBoolean("isInCarPref", newIsInCarState);
 | 
			
		||||
                editor.apply();
 | 
			
		||||
 | 
			
		||||
                Log.d("nt", "レスポンスを検知しました1");
 | 
			
		||||
                Log.d("SurveillanceService", "Bluetooth: "+sharedPreferences.getBoolean("BluetoothStatusLocal", false));
 | 
			
		||||
 | 
			
		||||
                if (isInCar&&!sharedPreferences.getBoolean("BluetoothStatusLocal", false)) {
 | 
			
		||||
                    if (Boolean.TRUE.equals(documentSnapshot.getBoolean("isReported"))) {
 | 
			
		||||
                        resetReported();
 | 
			
		||||
                        sendNotification(getApplicationContext(), REPORTED_NOTIFICATION);
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    resetReported();
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                Log.d("nt", "Current data: null");
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 通報フラグをリセットする
 | 
			
		||||
     */
 | 
			
		||||
    private void resetReported() {
 | 
			
		||||
        FirebaseFirestore db = FirebaseFirestore.getInstance();//Firebaseとの紐づけ
 | 
			
		||||
        DocumentReference isReported = db.collection("status").document(this.userId);
 | 
			
		||||
        //isReportedをfalseに更新
 | 
			
		||||
        isReported.update("isReported", false).addOnSuccessListener(unused ->
 | 
			
		||||
                Log.d(TAG, "DocumentSnapshot successfully updated!")).addOnFailureListener(e -> Log.w(TAG, "Error updating document", e));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 通知をタップしたときにアプリを起動するPendingIntentを取得
 | 
			
		||||
     *
 | 
			
		||||
     * @param context コンテキスト
 | 
			
		||||
     * @return PendingIntent
 | 
			
		||||
     */
 | 
			
		||||
    private PendingIntent getPendingIntent(Context context) {
 | 
			
		||||
        Intent intent = new Intent(context, MainActivity.class);
 | 
			
		||||
        intent.setAction("OPEN_ACTIVITY");
 | 
			
		||||
        return PendingIntent.getActivity(context, SurveillanceService.REQUEST_CODE, intent, PendingIntent.FLAG_IMMUTABLE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * デバイスをバイブレーションさせる
 | 
			
		||||
     */
 | 
			
		||||
    private void vibrateDevice() {
 | 
			
		||||
        Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
 | 
			
		||||
        if (vibrator.hasVibrator()) {
 | 
			
		||||
            vibrator.vibrate(VibrationEffect.createOneShot(2000, VibrationEffect.DEFAULT_AMPLITUDE));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 通知を送信する
 | 
			
		||||
     * @param context コンテキスト
 | 
			
		||||
     * @param content NotificationContent 通知内容
 | 
			
		||||
     */
 | 
			
		||||
    private void sendNotification(Context context, NotificationContent content) {//通知を行うメソッド
 | 
			
		||||
        // 権限の保有を確認
 | 
			
		||||
        if (isNotNotificationEnabled()) return;
 | 
			
		||||
 | 
			
		||||
        vibrateDevice();
 | 
			
		||||
 | 
			
		||||
        NotificationCompat.Builder builder = new NotificationCompat.Builder(context, content.getChannelId())
 | 
			
		||||
                .setSmallIcon(android.R.drawable.ic_menu_info_details)
 | 
			
		||||
                .setContentTitle(content.getTitle())//通知のタイトル
 | 
			
		||||
                .setContentText(content.getDescription())//通知の内容
 | 
			
		||||
                .setContentIntent(getPendingIntent(context))//通知をタップするとActivityへ移動する
 | 
			
		||||
                .setAutoCancel(true)//通知をタップすると削除する
 | 
			
		||||
                .setPriority(NotificationCompat.PRIORITY_HIGH) // プライオリティを高く設定
 | 
			
		||||
                .setVisibility(NotificationCompat.VISIBILITY_PUBLIC); // ロック画面に表示する
 | 
			
		||||
 | 
			
		||||
        NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
 | 
			
		||||
 | 
			
		||||
        notificationManager.notify(content.getNotificationId(), builder.build());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private final BroadcastReceiver receiver = new BroadcastReceiver() {
 | 
			
		||||
        @Override
 | 
			
		||||
        public void onReceive(Context context, Intent intent) {
 | 
			
		||||
            // 処理対象か確認 ----------------------------------------
 | 
			
		||||
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
 | 
			
		||||
            if (device == null) {
 | 
			
		||||
                Log.d("BT", "No device found");
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            String deviceHardwareAddress = device.getAddress(); // MAC address
 | 
			
		||||
            if (deviceHardwareAddress == null) {
 | 
			
		||||
                Log.d("BT", "No device address found");
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            String registeredId = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).getString("bluetooth_device_id", null);
 | 
			
		||||
            if (registeredId == null) {
 | 
			
		||||
                Log.d("BT_Judge", "No registered device");
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            if (!registeredId.equals(deviceHardwareAddress)) {
 | 
			
		||||
                Log.d("BT_Judge", "Not registered device");
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            boolean isInCar = getSharedPreferences("app_situation", MODE_PRIVATE).getBoolean("change", false);
 | 
			
		||||
//            if (!isInCar) {
 | 
			
		||||
//                Log.d("BT_Judge", "Not in car");
 | 
			
		||||
//                return;
 | 
			
		||||
//            }
 | 
			
		||||
            // -----------------------------------------------------
 | 
			
		||||
 | 
			
		||||
            // debug log
 | 
			
		||||
            Log.d("BT", "Bluetooth device found: " + deviceHardwareAddress);
 | 
			
		||||
            Log.d("BT", "Registered device: " + registeredId);
 | 
			
		||||
            Log.d("BT", "Is in car: " + isInCar);
 | 
			
		||||
            SharedPreferences sharedPreferences = SurveillanceService.this.getSharedPreferences("app_situation", MODE_PRIVATE);
 | 
			
		||||
            SharedPreferences.Editor E = sharedPreferences.edit();
 | 
			
		||||
            String action = intent.getAction(); // may need to chain this to a recognizing function
 | 
			
		||||
            if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
 | 
			
		||||
                E.putBoolean("BluetoothStatusLocal", false);
 | 
			
		||||
                // bluetoothが切断されたときに乗車状態のとき
 | 
			
		||||
                if (isInCar) {
 | 
			
		||||
                    notificationRunnable = () -> {
 | 
			
		||||
                        // 5分経過した時点でも車に乗っていない場合
 | 
			
		||||
                        sendNotification(context, BLUETOOTH_NOTIFICATION);
 | 
			
		||||
                    };
 | 
			
		||||
                }
 | 
			
		||||
                handler.postDelayed(notificationRunnable, NOTIFICATION_DELAY);
 | 
			
		||||
            } else if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
 | 
			
		||||
                E.putBoolean("BluetoothStatusLocal", true);
 | 
			
		||||
                // 再接続された場合、通知をキャンセルする
 | 
			
		||||
                if (notificationRunnable != null) {
 | 
			
		||||
                    handler.removeCallbacks(notificationRunnable);
 | 
			
		||||
                    notificationRunnable = null;
 | 
			
		||||
                    Log.d("BT", "Notification canceled due to reconnection");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            E.apply();
 | 
			
		||||
            Log.d("SurveillanceService:BT", "Bluetooth status: " + sharedPreferences.getBoolean("BluetoothStatusLocal", false));
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    @Nullable
 | 
			
		||||
    @Override
 | 
			
		||||
    public IBinder onBind(Intent intent) {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										297
									
								
								app/src/main/java/com/example/childguard/TestService.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										297
									
								
								app/src/main/java/com/example/childguard/TestService.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,297 @@
 | 
			
		||||
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.IntentFilter;
 | 
			
		||||
import android.content.SharedPreferences;
 | 
			
		||||
import android.content.pm.PackageManager;
 | 
			
		||||
import android.graphics.Color;
 | 
			
		||||
import android.os.Build;
 | 
			
		||||
import android.os.Handler;
 | 
			
		||||
import android.os.IBinder;
 | 
			
		||||
import android.os.Vibrator;
 | 
			
		||||
import android.preference.PreferenceManager;
 | 
			
		||||
import android.util.Log;
 | 
			
		||||
 | 
			
		||||
import androidx.annotation.Nullable;
 | 
			
		||||
import androidx.core.app.ActivityCompat;
 | 
			
		||||
import androidx.core.app.NotificationCompat;
 | 
			
		||||
 | 
			
		||||
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";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int onStartCommand(Intent intent, int flags, int startId) {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        //共有プリファレンス全体の準備
 | 
			
		||||
        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()を処理
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Bluetooth_status();
 | 
			
		||||
        return flags;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void initNotification(DocumentReference mDocRef) {//サイト上で押されたボタンの管理
 | 
			
		||||
        // PeriodicTaskManagerのインスタンス化
 | 
			
		||||
 | 
			
		||||
        // 共有プリファレンス全体の準備
 | 
			
		||||
        SharedPreferences sharedPreferences = getSharedPreferences("app_situation", MODE_PRIVATE);
 | 
			
		||||
        //車の乗り降りを管理するtrue=乗車、false=降車
 | 
			
		||||
        //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");
 | 
			
		||||
                if (isInCar) {//isReportedがtrue=サイト上で乗車状態のとき
 | 
			
		||||
                    if (documentSnapshot.getBoolean("isReported")) {
 | 
			
		||||
                        //ここスタート(リサイクル)
 | 
			
		||||
                        ResetReported();// ResetReported();を処理→FireBaseのisReportedをfalseにする
 | 
			
		||||
                        NotificationSetting();//通知に関する設定のメソッド
 | 
			
		||||
                        Notification(getApplicationContext());//通知を行うメソッド
 | 
			
		||||
                    }
 | 
			
		||||
                } else {//isReportedがfalse=サイト上で降車状態のとき
 | 
			
		||||
                    ResetReported();//ResetReported();を処理→FireBaseのisReportedをfalseにする
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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<String, Boolean> 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);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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("第三者からの通報が行われました。")//通知の本文
 | 
			
		||||
                .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 void NotificationBluetooth(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("Bluetoothと車の切断から5分が経過しました")//通知の本文
 | 
			
		||||
                .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 void Bluetooth_status() {
 | 
			
		||||
        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");
 | 
			
		||||
            return;
 | 
			
		||||
        } else {
 | 
			
		||||
            Log.d("BT", "Permission to connect bluetooth devices granted");
 | 
			
		||||
        }
 | 
			
		||||
        registerReceiver(receiver, intentFilter);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private final BroadcastReceiver receiver = new BroadcastReceiver() {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        //PreferenceManager.getDefaultSharedPreferences("myPreferences",Context.MODE_PRIVATE);
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public void onReceive(Context context, Intent intent) {
 | 
			
		||||
            SharedPreferences pref = getSharedPreferences("Bluetooth_situation", MODE_PRIVATE);
 | 
			
		||||
            SharedPreferences.Editor e = pref.edit();
 | 
			
		||||
            String action = intent.getAction(); // may need to chain this to a recognizing function
 | 
			
		||||
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
 | 
			
		||||
            Boolean isInCar = pref.getBoolean("isInCarPref", false);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            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
 | 
			
		||||
 | 
			
		||||
            String registeredId = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).getString("bluetooth_device_id", "none");
 | 
			
		||||
 | 
			
		||||
            if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
 | 
			
		||||
                //Do something if connected
 | 
			
		||||
                //Bluetoothデバイスが接続されたときの処理
 | 
			
		||||
                Log.d("BT", "Device connected");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                Log.d("BT_Judge", "Registered: " + registeredId);
 | 
			
		||||
 | 
			
		||||
                if (deviceHardwareAddress.equals(registeredId)) {
 | 
			
		||||
                    //登録済みのデバイスだったときの処理
 | 
			
		||||
                    Log.d("BT_Judge", "登録済み");
 | 
			
		||||
                    e.putBoolean("connection_status", true);
 | 
			
		||||
 | 
			
		||||
                } else {
 | 
			
		||||
                    //登録していないデバイスだったときの処理
 | 
			
		||||
                    Log.d("BT_Judge", "未登録");
 | 
			
		||||
                    e.putBoolean("connection_status", false);
 | 
			
		||||
                }
 | 
			
		||||
                e.apply();
 | 
			
		||||
 | 
			
		||||
            } else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action) && !isInCar) {//bluetoothが切断されたときに乗車状態のとき
 | 
			
		||||
 | 
			
		||||
                //Do something if disconnected
 | 
			
		||||
                //デバイスが切断されたときの処理
 | 
			
		||||
                if (deviceHardwareAddress.equals(registeredId)) {
 | 
			
		||||
                    // 5分待機する
 | 
			
		||||
                    Handler handler = new Handler();
 | 
			
		||||
                    handler.postDelayed(new Runnable() {
 | 
			
		||||
                        @Override
 | 
			
		||||
                        public void run() {
 | 
			
		||||
                            if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action) && !isInCar) {//その後bluetoothを再接続したり降車状態になったりしていない=置き去りが発生した可能性大
 | 
			
		||||
                                NotificationBluetooth(getApplicationContext());//通知を行うメソッド
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                    }, 5 * 60 * 1000); // 5分をミリ秒に変換
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                Log.d("BT", "Device disconnected");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @Nullable
 | 
			
		||||
    @Override
 | 
			
		||||
    public IBinder onBind(Intent intent) {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -7,7 +7,6 @@ import android.bluetooth.BluetoothDevice;
 | 
			
		||||
import android.bluetooth.BluetoothManager;
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.content.pm.PackageManager;
 | 
			
		||||
import android.os.Build;
 | 
			
		||||
import android.os.Bundle;
 | 
			
		||||
 | 
			
		||||
import androidx.core.app.ActivityCompat;
 | 
			
		||||
@ -24,7 +23,6 @@ import android.view.MenuItem;
 | 
			
		||||
import android.view.View;
 | 
			
		||||
import android.view.ViewGroup;
 | 
			
		||||
import android.widget.TextView;
 | 
			
		||||
import android.widget.Toast;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.Objects;
 | 
			
		||||
@ -93,36 +91,15 @@ public class bluetooth_setupFragment extends Fragment {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//        if (ActivityCompat.checkSelfPermission(requireActivity().getApplicationContext(), android.Manifest.permission.BLUETOOTH_CONNECT) != 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 view;
 | 
			
		||||
//        }
 | 
			
		||||
 | 
			
		||||
        // >= Android 12
 | 
			
		||||
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
 | 
			
		||||
            if (ActivityCompat.checkSelfPermission(requireActivity().getApplicationContext(), android.Manifest.permission.BLUETOOTH) != PackageManager.PERMISSION_GRANTED) {
 | 
			
		||||
                Log.w("Bluetooth", "Permission not granted(Android 12-)");
 | 
			
		||||
                // show toast then force close the app (Workaround)
 | 
			
		||||
                Toast.makeText(requireActivity().getApplicationContext(), "Bluetoothの権限が必須です!", Toast.LENGTH_SHORT).show();
 | 
			
		||||
                requireActivity().finish();
 | 
			
		||||
            } else {
 | 
			
		||||
                Log.w("Bluetooth", "Permission granted(Android 12-)");
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            if (ActivityCompat.checkSelfPermission(requireActivity().getApplicationContext(), android.Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
 | 
			
		||||
                Log.w("Bluetooth", "Permission not granted(Android 12+)");
 | 
			
		||||
                // show toast then force close the app (Workaround)
 | 
			
		||||
                Toast.makeText(requireActivity().getApplicationContext(), "Bluetoothの権限が必須です!", Toast.LENGTH_SHORT).show();
 | 
			
		||||
                requireActivity().finish();
 | 
			
		||||
            } else {
 | 
			
		||||
                Log.w("Bluetooth", "Permission granted(Android 12+)");
 | 
			
		||||
            }
 | 
			
		||||
        if (ActivityCompat.checkSelfPermission(requireActivity().getApplicationContext(), android.Manifest.permission.BLUETOOTH_CONNECT) != 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 view;
 | 
			
		||||
        }
 | 
			
		||||
        Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -19,7 +19,7 @@
 | 
			
		||||
        app:layout_constraintTop_toTopOf="parent">
 | 
			
		||||
 | 
			
		||||
        <FrameLayout
 | 
			
		||||
            android:id="@+id/car_situation_bg"
 | 
			
		||||
            android:id="@+id/situation_bg"
 | 
			
		||||
            android:layout_width="match_parent"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:layout_marginLeft="20dp"
 | 
			
		||||
@ -37,7 +37,7 @@
 | 
			
		||||
                android:textSize="25dp" />
 | 
			
		||||
 | 
			
		||||
            <TextView
 | 
			
		||||
                android:id="@+id/car_situation"
 | 
			
		||||
                android:id="@+id/situation"
 | 
			
		||||
                android:layout_width="match_parent"
 | 
			
		||||
                android:layout_height="200dp"
 | 
			
		||||
                android:layout_marginTop="10dp"
 | 
			
		||||
@ -49,7 +49,7 @@
 | 
			
		||||
        </FrameLayout>
 | 
			
		||||
 | 
			
		||||
        <FrameLayout
 | 
			
		||||
            android:id="@+id/situation_bg_bluetooth"
 | 
			
		||||
            android:id="@+id/situation_bg2"
 | 
			
		||||
            android:layout_width="match_parent"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:layout_marginLeft="20dp"
 | 
			
		||||
@ -58,7 +58,7 @@
 | 
			
		||||
            android:background="@drawable/frame_style">
 | 
			
		||||
 | 
			
		||||
            <TextView
 | 
			
		||||
                android:id="@+id/BluetoothSituation"
 | 
			
		||||
                android:id="@+id/Bluetoothsituation"
 | 
			
		||||
                android:layout_width="match_parent"
 | 
			
		||||
                android:layout_height="wrap_content"
 | 
			
		||||
                android:layout_marginTop="5dp"
 | 
			
		||||
@ -75,7 +75,7 @@
 | 
			
		||||
                android:textAlignment="center" />
 | 
			
		||||
 | 
			
		||||
            <ImageView
 | 
			
		||||
                android:id="@+id/BluetoothSituationImage"
 | 
			
		||||
                android:id="@+id/Bluetoothsituationimage"
 | 
			
		||||
                android:layout_width="match_parent"
 | 
			
		||||
                android:layout_height="100dp"
 | 
			
		||||
                android:layout_marginTop="50dp"
 | 
			
		||||
 | 
			
		||||
@ -1,74 +1,56 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    xmlns:app="http://schemas.android.com/apk/res-auto"
 | 
			
		||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    xmlns:tools="http://schemas.android.com/tools"
 | 
			
		||||
    android:layout_width="match_parent"
 | 
			
		||||
    android:layout_height="match_parent"
 | 
			
		||||
    android:orientation="vertical"
 | 
			
		||||
    android:padding="16dp"
 | 
			
		||||
    tools:context=".SettingFragment">
 | 
			
		||||
    tools:context=".SettingFragment"
 | 
			
		||||
    android:padding="16dp">
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    <ImageView
 | 
			
		||||
        android:src="@drawable/bluetooth_and_qr2"
 | 
			
		||||
        android:layout_gravity="center_horizontal"
 | 
			
		||||
        android:layout_width="wrap_content"
 | 
			
		||||
        android:layout_height="200dp"
 | 
			
		||||
        android:layout_marginTop="150dp"
 | 
			
		||||
        />
 | 
			
		||||
    <TextView
 | 
			
		||||
        android:layout_width="wrap_content"
 | 
			
		||||
        android:layout_height="wrap_content"
 | 
			
		||||
        android:textColor="@color/black"
 | 
			
		||||
        android:text="QRコード印刷とBluetooth設定"
 | 
			
		||||
        android:layout_gravity="center_horizontal"
 | 
			
		||||
        android:textStyle="bold"
 | 
			
		||||
        android:textSize="18dp"
 | 
			
		||||
        android:layout_marginTop="20dp"
 | 
			
		||||
        />
 | 
			
		||||
 | 
			
		||||
    <Button
 | 
			
		||||
        android:id="@+id/button_bluetooth_setting"
 | 
			
		||||
        android:layout_width="match_parent"
 | 
			
		||||
        android:layout_height="wrap_content"
 | 
			
		||||
        android:text="Bluetooth設定"
 | 
			
		||||
        android:layout_marginTop="120dp"
 | 
			
		||||
        android:layout_marginBottom="20dp"/>
 | 
			
		||||
 | 
			
		||||
    <Button
 | 
			
		||||
        android:id="@+id/button_print_qr"
 | 
			
		||||
        android:layout_width="match_parent"
 | 
			
		||||
        android:layout_height="wrap_content"
 | 
			
		||||
        android:text="QRコード印刷"/>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    <LinearLayout
 | 
			
		||||
        android:id="@+id/linearLayout"
 | 
			
		||||
        android:layout_width="match_parent"
 | 
			
		||||
        android:layout_height="wrap_content"
 | 
			
		||||
        android:orientation="vertical"
 | 
			
		||||
        app:layout_constraintBottom_toBottomOf="parent"
 | 
			
		||||
        app:layout_constraintEnd_toEndOf="parent"
 | 
			
		||||
        app:layout_constraintStart_toStartOf="parent"
 | 
			
		||||
        app:layout_constraintTop_toTopOf="parent">
 | 
			
		||||
 | 
			
		||||
        <ImageView
 | 
			
		||||
            android:layout_width="wrap_content"
 | 
			
		||||
            android:layout_height="200dp"
 | 
			
		||||
            android:layout_gravity="center_horizontal"
 | 
			
		||||
            android:src="@drawable/bluetooth_and_qr2" />
 | 
			
		||||
        android:layout_height="match_parent"
 | 
			
		||||
        android:gravity="bottom">
 | 
			
		||||
 | 
			
		||||
        <TextView
 | 
			
		||||
            android:layout_width="wrap_content"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:layout_gravity="center_horizontal"
 | 
			
		||||
            android:layout_marginTop="20dp"
 | 
			
		||||
            android:text="QRコード印刷とBluetooth設定"
 | 
			
		||||
            android:textColor="@color/black"
 | 
			
		||||
            android:textSize="18dp"
 | 
			
		||||
            android:textStyle="bold" />
 | 
			
		||||
 | 
			
		||||
        <Button
 | 
			
		||||
            android:id="@+id/button_bluetooth_setting"
 | 
			
		||||
            android:layout_width="match_parent"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:layout_marginTop="120dp"
 | 
			
		||||
            android:layout_marginBottom="20dp"
 | 
			
		||||
            android:text="Bluetooth設定" />
 | 
			
		||||
 | 
			
		||||
        <Button
 | 
			
		||||
            android:id="@+id/button_print_qr"
 | 
			
		||||
            android:layout_width="match_parent"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:text="QRコード印刷" />
 | 
			
		||||
 | 
			
		||||
            android:text="QRコードは株式会社デンソーウェーブの登録商標です"
 | 
			
		||||
            android:textColor="@color/black" />
 | 
			
		||||
    </LinearLayout>
 | 
			
		||||
 | 
			
		||||
    <LinearLayout
 | 
			
		||||
        android:layout_width="match_parent"
 | 
			
		||||
        android:layout_height="wrap_content"
 | 
			
		||||
        android:gravity="bottom"
 | 
			
		||||
        app:layout_constraintBottom_toTopOf="@+id/linearLayout"
 | 
			
		||||
        tools:layout_editor_absoluteX="16dp">
 | 
			
		||||
 | 
			
		||||
    </LinearLayout>
 | 
			
		||||
 | 
			
		||||
    <TextView
 | 
			
		||||
        android:layout_width="match_parent"
 | 
			
		||||
        android:layout_height="wrap_content"
 | 
			
		||||
        android:text="QRコードは株式会社デンソーウェーブの登録商標です"
 | 
			
		||||
        android:textColor="@color/black"
 | 
			
		||||
        android:textSize="12sp"
 | 
			
		||||
        app:layout_constraintBottom_toBottomOf="parent"
 | 
			
		||||
        app:layout_constraintEnd_toEndOf="parent"
 | 
			
		||||
        app:layout_constraintStart_toStartOf="parent" />
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
</androidx.constraintlayout.widget.ConstraintLayout>
 | 
			
		||||
</LinearLayout>
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user