-1

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) 

fadden
  • 51,356
  • 5
  • 116
  • 166
user904542
  • 6,965
  • 5
  • 20
  • 28
  • Use LogCat to examine the Java stack trace associated with your crash: https://stackoverflow.com/questions/23353173/unfortunately-myapp-has-stopped-how-can-i-solve-this – CommonsWare May 01 '16 at 17:02
  • *Program has stopped working* and *App has stopped working* is the display that is seen by end user. See stacktrace ! – Shree Krishna May 01 '16 at 17:06
  • Please paste the stacktrace so we examine what causes the crash – ishmaelMakitla May 01 '16 at 17:14
  • Thanks for the comments above, but I would like to point out a few things. I've managed to isolate stacktrace now, but before it's not like I hadn't tried to look at that, but it was hard, because I'm fairly new with AndroidStudio, and the thing just kept on down scrolling when I plugged my phone in. Plus, I put this code together by looking at samples and trying to figure it out. I have no experience with Services, so I didn't know how to handle it, so I wouldn't have figured it out even if I had looked at logcat. This being said, I suspect I was downvoted because of misunderstanding. – user904542 May 07 '16 at 15:12

1 Answers1

1
YourService ys = new YourService();
Intent in = new Intent(this, YourService.class);
ys.onStart(in, 1);

Never instantiate Android components with a lifecycle such as a Service or an Activity with new. Such instances won't get correctly initialized for example to be used as a Context.

Don't call lifecycle methods such as onStart() yourself. Let the framework call them for you.

To correctly start a Service, use startService() with an Intent.

laalto
  • 150,114
  • 66
  • 286
  • 303
  • Thank you. However, I used services like this because I am completely new to Android Development using the Android API, so I am certainly completely new to Services, so I didn't know how to use them properly. But I'm going to check out some tutorials on how to use Services now. So your answer seems to be pointing me in a good direction to achieving what I am trying to accomplish in my app. – user904542 May 09 '16 at 21:11