I am attempting to create an AndroidStudio app that is able to schedule and send specific text messages to specific people at specific frequencies. I am completely new to the Android API, and after some research, it seemed that the AlarmManager is the best way to do that. For I need to be able to specify the dates and times for the messages to be sent, and it needs to restart automatically on reboot, but it doesn't matter if the phone is connected to the internet or not. I went through some different example's to try to work out how to do this, and I right now I have created an app that has two buttons. One is "Start Messages", and the other is "Stop Messages". When you press "Start Messages", it sends a message to myself every few seconds (just for testing the concept). The problem is right now, as soon as I click "Start Messages", the program crashes and says "Program has stopped working". Below is the sample code, along with an indication of where it crashes:
// MainActivity.java:
package com.example.me.alarmmanagerexample;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import java.util.GregorianCalendar;
import java.util.Timer;
import java.util.TimerTask;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
public void onBtnAlarmOnClick(View v) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.SEND_SMS) !=
PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.SEND_SMS},
10
);
} else {
startAlarm();
}
}
public void onBtnAlarmOffClick(View v) {
stopAlarm();
}
public void startAlarm() {
YourService ys = new YourService();
Intent in = new Intent(this, YourService.class);
ys.onStart(in, 1);
//startService(intent);
//Log.i("MyService", "Start Alarm");
}
public void stopAlarm() {
Intent intent = new Intent(this, YourService.class);
stopService(intent);
Log.i("MyService", "Stop Alarm");
}
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case 10: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
startAlarm();
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
@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);
}
}
// YourService.java:
package com.example.me.alarmmanagerexample;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;
public class YourService extends Service {
Alarm alarm = new Alarm();
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("MyService", "Your Service command started");
alarm.SetAlarm(this);
return START_STICKY;
}
@Override
public void onStart(Intent intent, int startId) {
Log.i("MyService", "Your Service started");
alarm.SetAlarm(this);
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.i("MyService", "Your Service binded");
return null;
}
}
// Alarm.java
package com.example.me.alarmmanagerexample;
import android.Manifest;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
import android.support.v4.app.ActivityCompat;
import android.telephony.SmsManager;
import android.util.Log;
import android.widget.Toast;
import java.util.Calendar;
public class Alarm extends BroadcastReceiver {
Integer times = new Integer(0);
@Override
public void onReceive(Context context, Intent intent) {
/*
PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
wl.acquire();
*/
Log.i("MyService", "send message");
SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage("555-123-4567", null, "Hello You!" + times.toString(), null, null);
Log.i("MyService", "Sending Message");
++times;
//wl.release();
}
public void SetAlarm(Context context) {
Log.i("MyService", "flag 1");
// Crashes at this line, as "flag 1" is logged, but not "flag 2"
AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Log.i("MyService", "flag 2");
Intent i = new Intent(context, Alarm.class);
Log.i("MyService", "flag 3");
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
Log.i("MyService", "flag 4");
Calendar cal = Calendar.getInstance();
Log.i("MyService", "flag 5");
cal.setTimeInMillis(System.currentTimeMillis());
Log.i("MyService", "flag 6");
cal.set(Calendar.HOUR_OF_DAY, 10);
Log.i("MyService", "flag 7");
cal.set(Calendar.MINUTE, 38);
Log.i("MyService", "flag 8");
am.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 10000, pi);
Log.i("MySerivce", "flag 9");
}
public void CancelAlarm(Context context) {
Intent intent = new Intent(context, Alarm.class);
PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(sender);
}
}
// AutoStart.java
package com.example.me.alarmmanagerexample;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class AutoStart extends BroadcastReceiver {
Alarm alarm = new Alarm();
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
alarm.SetAlarm(context);
}
}
}
// content_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="com.example.me.alarmmanagerexample.MainActivity"
tools:showIn="@layout/activity_main">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Alarm On"
android:id="@+id/btnAlarmOn"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:onClick="onBtnAlarmOnClick"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Alarm Off"
android:id="@+id/btnAlarmOff"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:onClick="onBtnAlarmOffClick"/>
</RelativeLayout
// AndroidManifest.xml
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="com.android.alarm.permission.set_alarm" />
<receiver android:name=".AutoStart">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service
android:name="com.example.me.alarmmanagerexample.YourService"
android:enabled="true"
android:process=":your_service" />
<uses-permission android:name="com.example.me.alarmmanagerexample.YourService" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
The stack trace:
05-01 13:34:30.357 8342-8342/? I/art: Late-enabling -Xcheck:jni 05-01 13:34:31.182 8342-8342/com.example.me.alarmmanagerexample W/System: ClassLoader referenced unknown path: /data/app/com.example.me.alarmmanagerexample-2/lib/arm 05-01 13:34:33.098 8342-8378/com.example.me.alarmmanagerexample W/art: Suspending all threads took: 76.091ms 05-01 13:34:33.105 8342-8378/com.example.me.alarmmanagerexample I/art: Background sticky concurrent mark sweep GC freed 7151(386KB) AllocSpace objects, 0(0B) LOS objects, 20% free, 7MB/9MB, paused 76.748ms total 268.671ms 05-01 13:34:33.476 8342-8374/com.example.me.alarmmanagerexample W/art: Suspending all threads took: 152.637ms 05-01 13:34:33.857 8342-8374/com.example.me.alarmmanagerexample W/art: Suspending all threads took: 32.790ms 05-01 13:34:35.340 8342-8463/com.example.me.alarmmanagerexample I/Adreno-EGL: : EGL 1.4 QUALCOMM build: (I8a1ccf9ecb) OpenGL ES Shader Compiler Version: XE031.06.00.01 Build Date: 11/02/15 Mon Local Branch: workspace Remote Branch: Local Patches: Reconstruct Branch: 05-01 13:34:35.353 8342-8463/com.example.me.alarmmanagerexample I/OpenGLRenderer: Initialized EGL, version 1.4 05-01 13:34:35.760 8342-8342/com.example.me.alarmmanagerexample I/Choreographer: Skipped 79 frames! The application may be doing too much work on its main thread. 05-01 13:34:36.016 8342-8374/com.example.me.alarmmanagerexample W/art: Suspending all threads took: 189.200ms 05-01 13:34:36.436 8342-8374/com.example.me.alarmmanagerexample W/art: Suspending all threads took: 109.066ms 05-01 13:34:37.237 8342-8342/com.example.me.alarmmanagerexample I/Choreographer: Skipped 87 frames! The application may be doing too much work on its main thread. 05-01 13:34:50.398 8342-8374/com.example.me.alarmmanagerexample W/art: Suspending all threads took: 49.095ms 05-01 13:34:56.375 8342-8374/com.example.me.alarmmanagerexample W/art: Suspending all threads took: 17.639ms
05-01 13:38:46.454 8342-8342/com.example.me.alarmmanagerexample I/MyService: flag 1 05-01 13:38:46.499 8342-8342/com.example.me.alarmmanagerexample E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.me.alarmmanagerexample, PID: 8342 java.lang.IllegalStateException: Could not execute method for android:onClick at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:275) at android.view.View.performClick(View.java:5201) at android.view.View$PerformClick.run(View.java:21163) at android.os.Handler.handleCallback(Handler.java:746) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5443) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) Caused by: java.lang.reflect.InvocationTargetException at java.lang.reflect.Method.invoke(Native Method) at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:270) at android.view.View.performClick(View.java:5201) at android.view.View$PerformClick.run(View.java:21163) at android.os.Handler.handleCallback(Handler.java:746) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5443) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object android.content.Context.getSystemService(java.lang.String)' on a null object reference at android.content.ContextWrapper.getSystemService(ContextWrapper.java:627) at com.example.me.alarmmanagerexample.Alarm.SetAlarm(Alarm.java:43) at com.example.me.alarmmanagerexample.YourService.onStart(YourService.java:28) at com.example.me.alarmmanagerexample.MainActivity.startAlarm(MainActivity.java:61) at com.example.me.alarmmanagerexample.MainActivity.onBtnAlarmOnClick(MainActivity.java:50) at java.lang.reflect.Method.invoke(Native Method) at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:270) at android.view.View.performClick(View.java:5201) at android.view.View$PerformClick.run(View.java:21163) at android.os.Handler.handleCallback(Handler.java:746) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5443) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)