Bluetooth Leash Pro

Platform: Android

Code Editor: Android Studio

Bluetooth Leash Pro is an alarm that goes off when it looses connection with your Bluetooth Devices, such as when one an earbud falls out and you walk away from it. Events are tagged on a Google map with a pin to indicate where you were when the event happened. It’s very helpful in preventing the lose of expensive Bluetooth devices.

History:

I bought an expensive Bluetooth device and didn’t want to loose it. When I searched the Google Play Store for a Bluetooth alarm I couldn’t find exactly what I was looking for so I decided to make my own.

I preceded to learn Android Studio, Kotlin, and, Android app development. I had my first working version in about three months.

Challenge:
Solution:
Challenge:

I ran into another issue when setting up in-app purchases. I was logging into Google from the Main Menu scene but when I debug I would run the Level scene and so the store was not being initialized.

Solution:

I solved this issue by creating a singleton game manager and adding it to each scene I may want to start from:

				
					using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using GooglePlayGames;
using GooglePlayGames.BasicApi;
using TMPro;


public class GameManager : MonoBehaviour
{
	private static GameManager					_instance;
	[SerializeField] private GameObject			messageLogScrollView;
	[SerializeField] private TextMeshProUGUI	message;

	private Toggle debugModeToggle;
	public static GameManager Instance
	{
		get
		{
			if(_instance==null)
			{
				Debug.Log("GameManager.Instance is NULL");
			}
			return _instance;
		}
	}


	void OnEnable()
	{
		Application.logMessageReceived += LogCallback;
		SetShowMessageLogActive(GamePlayerPrefs.debugFlag);
	}


	private void Awake()
	{
		if(_instance == null)
		{
			_instance = this;
		}
		else
		{
			DestroyImmediate(gameObject);
		}

		PlayGamesPlatform.DebugLogEnabled = true;
		PlayGamesPlatform.Activate();
	}

	//Called when there is an exception
	void LogCallback(string condition, string stackTrace, LogType type)
	{
		if(type!=LogType.Log)
		{
			message.text += $"Type: {type}\n\n\nCondition: {condition}\n\n\nStack Trace: {stackTrace}\n\n\n";
			if(debugModeToggle)
			{
				debugModeToggle.isOn = true;
			}
			else
			{
				GamePlayerPrefs.debugFlag = false;
			}
		}
	}

	void OnDisable()
	{
		Application.logMessageReceived -= LogCallback;
	}

	private void Start()
	{
		var debugPanelGO = GameObject.FindObjectOfType<DebugModeToggle>();

		if(debugPanelGO)
		{
			debugModeToggle = debugPanelGO.gameObject.GetComponent<Toggle>();

			LoginToGoogle();
			if(gameObject.transform.parent==null)
			{
				DontDestroyOnLoad(gameObject);
			}
		}
	}


	static public void SetShowMessageLogActive(bool flag)
	{
		Instance?.messageLogScrollView.SetActive(flag);
	}

	private void LoginToGoogle()
	{
		PlayGamesPlatform.Instance.Authenticate(ProcessAuthentification);
	}


	private void ProcessAuthentification(SignInStatus status)
	{
		if(SignInStatus.Success == status)
		{
			message.text = $"Authentification: {status}\n\n\n";
		}
		else
		{
			message.text = $"Authentification: {status}\n\n\n";
		}

		if(false)
		{
			StartCoroutine(ExecuteAfterTime(2.0f, () =>

			 {
				ClearAutentificationMessage();
			}));
		}
	}

	private bool isCoroutineExecuting = false;
	IEnumerator ExecuteAfterTime(float time, Action task)
	{
		if(isCoroutineExecuting)
			yield break;
		isCoroutineExecuting = true;
		yield return new WaitForSeconds(time);
		task();
		isCoroutineExecuting = false;
	}




	void ClearAutentificationMessage()
	{
		message.text = "";
	}
}