I am currently struggling to find why my alarm sometimes works as intended and other times does not. It normally works when i set the alarm for a few minutes but when i set the alarm from say 10pm to 6am that's when it normally starts going off within about 10 seconds. Whenever i set the alarm from pm to am or vice versa the error occurs and the alarm just goes off.
I know its a lot of code but I'm pretty much desperate at this point. Any help will be appreciated.
Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.insomniafinal">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".Register" android:label="@string/app_name" android:theme="@style/AppTheme.NoActionBar"></activity>
<activity android:name=".MainActivity" android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data
android:name="preloaded_fonts"
android:resource="@array/preloaded_fonts" />
<receiver android:name=".Alarm_Receiver" />
<service android:name=".RingtonePlayingService"
android:enabled="true">
</service>
</application>
</manifest>
Alarm Receiver
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class Alarm_Receiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// fetch extra strings from the intent
// tells the app whether the user pressed the alarm on button or the alarm off button
String get_your_string = intent.getExtras().getString("extra");
// fetch the extra longs from the intent
// tells the app which value the user picked from the drop down menu/spinner
Integer get_your_whale_choice = intent.getExtras().getInt("whale_choice");
// create an intent to the ringtone service
Intent service_intent = new Intent(context, RingtonePlayingService.class);
// pass the extra string from Receiver to the Ringtone Playing Service
service_intent.putExtra("extra", get_your_string);
// pass the extra integer from the Receiver to the Ringtone Playing Service
service_intent.putExtra("whale_choice", get_your_whale_choice);
// start the ringtone service
context.startService(service_intent);
}
}
RingtonePlayingService
import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Build;
import android.os.IBinder;
import android.util.Log;
import java.util.Random;
public class RingtonePlayingService extends Service {
MediaPlayer media_song;
int startId;
boolean isRunning;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// fetch the extra string from the alarm on/alarm off values
String state = intent.getExtras().getString("extra");
// fetch the whale choice integer values
Integer whale_sound_choice = intent.getExtras().getInt("whale_choice");
// notification
// set up the notification service
NotificationManager notify_manager = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
// set up an intent that goes to the Main Activity
Intent intent_main_activity = new Intent(this.getApplicationContext(), MainActivity.class);
// set up a pending intent
PendingIntent pending_intent_main_activity = PendingIntent.getActivity(this, 0,
intent_main_activity, 0);
// make the notification parameters
Notification notification_popup = new Notification.Builder(this)
.setContentTitle("An alarm is going off!")
.setContentText("Click me!")
.setSmallIcon(R.drawable.ic_action_call)
.setContentIntent(pending_intent_main_activity)
.setAutoCancel(true)
.build();
// this converts the extra strings from the intent
// to start IDs, values 0 or 1
assert state != null;
switch (state) {
case "alarm on":
startId = 1;
break;
case "alarm off":
startId = 0;
Log.e("Start ID is ", state);
break;
default:
startId = 0;
break;
}
// if else statements
// if there is no music playing, and the user pressed "alarm on"
// music should start playing
if (!this.isRunning && startId == 1) {
Log.e("there is no music, ", "and you want start");
this.isRunning = true;
this.startId = 0;
// set up the start command for the notification
notify_manager.notify(0, notification_popup);
else if (this.isRunning && startId == 0) {
Log.e("there is music, ", "and you want end");
// stop the ringtone
media_song.stop();
media_song.reset();
this.isRunning = false;
this.startId = 0;
}
// these are if the user presses random buttons
// just to bug-proof the app
// if there is no music playing, and the user pressed "alarm off"
// do nothing
else if (!this.isRunning && startId == 0) {
Log.e("there is no music, ", "and you want end");
this.isRunning = false;
this.startId = 0;
}
// if there is music playing and the user pressed "alarm on"
// do nothing
else if (this.isRunning && startId == 1) {
Log.e("there is music, ", "and you want start");
this.isRunning = true;
this.startId = 1;
}
// can't think of anything else, just to catch the odd event
else {
Log.e("else ", "somehow you reached this");
}
return START_NOT_STICKY;
}
@Override
public void onDestroy() {
// Tell the user we stopped.
Log.e("on Destroy called", "ta da");
super.onDestroy();
this.isRunning = false;
}
Main Activity
public class MainActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener {
AlarmManager alarm_manager;
TimePicker alarm_timepicker;
TextView update_text;
Context context;
PendingIntent pending_intent;
int choose_whale_sound;
long startTime = 0;
long start = 0;
float numberOfHours = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
this.context = this;
}alarm_manager = (AlarmManager) getSystemService(ALARM_SERVICE);
//initialize our timepicker
alarm_timepicker = (TimePicker) findViewById(R.id.timePicker);
//initialize our text update box
update_text = (TextView) findViewById(R.id.update_text);
// create an instance of a calendar
final Calendar calendar = Calendar.getInstance();
// create an intent to the Alarm Receiver class
final Intent my_intent = new Intent(this.context, Alarm_Receiver.class);
// create the spinner in the main UI
Spinner spinner = (Spinner) findViewById(R.id.richard_spinner);
// Create an ArrayAdapter using the string array and a default spinner layout
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
R.array.whale_array, android.R.layout.simple_spinner_item);
// Specify the layout to use when the list of choices appears
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// Apply the adapter to the spinner
spinner.setAdapter(adapter);
// Set an onclick listener to the onItemSelected method
spinner.setOnItemSelectedListener(this);
// initialize start button
Button alarm_on = (Button) findViewById(R.id.alarm_on);
// create an onClick listener to start the alarm
alarm_on.setOnClickListener(new View.OnClickListener() {
//@TargetApi(Build.VERSION_CODES.M)
@Override
public void onClick(View v) {
// setting calendar instance with the hour and minute that we picked
// on the time picker
calendar.set(Calendar.HOUR_OF_DAY, alarm_timepicker.getHour());
calendar.set(Calendar.MINUTE, alarm_timepicker.getMinute());
// get the int values of the hour and minute
int hour = alarm_timepicker.getHour();
int minute = alarm_timepicker.getMinute();
// convert the int values to strings
String hour_string = String.valueOf(hour);
String minute_string = String.valueOf(minute);
// convert 24-hour time to 12-hour time
if (hour > 12) {
hour_string = String.valueOf(hour - 12);
}
if (minute < 10) {
//10:7 --> 10:07
minute_string = "0" + String.valueOf(minute);
}
// method that changes the update text Textbox
set_alarm_text("Alarm set to: " + hour_string + ":" + minute_string);
// put in extra string into my_intent
// tells the clock that you pressed the "alarm on" button
my_intent.putExtra("extra", "alarm on");
// put in an extra int into my_intent
// tells the clock that you want a certain value from the drop-down menu/spinner
my_intent.putExtra("whale_choice", choose_whale_sound);
Log.e("The whale id is" , String.valueOf(choose_whale_sound));
// create a pending intent that delays the intent
// until the specified calendar time
pending_intent = PendingIntent.getBroadcast(MainActivity.this, 0,
my_intent, PendingIntent.FLAG_UPDATE_CURRENT);
// set the alarm manager
alarm_manager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
pending_intent);
start = System.currentTimeMillis();
}
});
// initialize the stop button
Button alarm_off = (Button) findViewById(R.id.alarm_off);
// create an onClick listener to stop the alarm or undo an alarm set
alarm_off.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// method that changes the update text Textbox
set_alarm_text("Alarm off!");
// cancel the alarm
alarm_manager.cancel(pending_intent);
// put extra string into my_intent
// tells the clock that you pressed the "alarm off" button
my_intent.putExtra("extra", "alarm off");
// also put an extra int into the alarm off section
// to prevent crashes in a Null Pointer Exception
my_intent.putExtra("whale_choice", choose_whale_sound);
//Get duration of the alarm.
long end = System.currentTimeMillis();
long delta = end - start;
int elapsedSeconds = (int)delta / 1000;
int mins = elapsedSeconds/60;
float hours = mins/60;
documentReference.update("sleep", FieldValue.arrayUnion(hours));
// stop the ringtone
sendBroadcast(my_intent);
}
});
}
private void set_alarm_text(String output) {
update_text.setText(output);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
// An item was selected. You can retrieve the selected item using
// parent.getItemAtPosition(pos)
// outputting whatever id the user has selected
//Toast.makeText(parent.getContext(), "the spinner item is "
// + id, Toast.LENGTH_SHORT).show();
choose_whale_sound = (int) id;
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
// Another interface callback
}