2016-05-01 125 views
-1

我正在尝试创建一个AndroidStudio应用程序,它能够按特定频率安排并向特定人员发送特定文本消息。我对Android API完全陌生,经过一番研究,似乎AlarmManager是最好的方法。因为我需要能够指定要发送的消息的日期和时间,并且需要在重新启动时自动重新启动,但电话是否连接到互联网并不重要。我经历了一些不同的例子,试图找出如何做到这一点,现在我创建了一个有两个按钮的应用程序。一个是“开始消息”,另一个是“停止消息”。当你按下“开始消息”时,它每隔几秒就会向我发送一条消息(仅用于测试概念)。现在的问题是,只要我点击“开始消息”,程序崩溃,并说“程序已停止工作”。下面是示例代码,与在那里它崩溃的指示一起:Android应用程序在尝试使用Context.ALARM_SERVICE时崩溃

// 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> 

堆栈跟踪:

05-01 13:34:30.357 8342-8342 /? I/art:延迟启用-Xcheck:jni 05-01 13:34:31.182 8342-8342/com.example.me.alarmmanagerexample W/System:ClassLoader引用的未知路径:/data/app/com.example.me .alarmmanagerexample-2/lib/arm 05-01 13:34:33.098 8342-8378/com.example.me.alarmmanagerexample W/art:挂起所有线程花费:76.091ms 05-01 13:34:33.105 8342- 8378/com.example.me.alarmmanagerexample I/art:背景粘性并发标记扫描GC已释放7151(386KB)AllocSpace对象,0(0B)LOS对象,20%空闲,7MB/9MB,暂停76.748ms,总计268.671ms 05 -01 13:34:33.476 8342-8374/com.example.me.alarmmanagerexample W/art:挂起所有线程花费:152.637ms 05-01 13:34:33.857 8342-8374/com.example.me.alarmmanagerexample W/art:暂停所有线程:32.790ms 05-01 13:34:35.340 8342-8463/com.example.me.alarmmanagerexa mple I /肾上腺EGL:EGL 1.4高通公司构建:(I8a1ccf9ecb) 的OpenGL ES着色器编译器版本:XE031.06.00.01 生成日期:15年11月2日星期一 当地分行:工作区 远程分支: 本地补丁: 重建分支: 05-01 13:34:35.353 8342-8463/com.example.me.alarmmanagerexample I/OpenGLRenderer:初始化的EGL,版本1.4 05-01 13:34:35.760 8342-8342/com.example .me.alarmmanagerexample I /编舞:跳过79帧!应用程序可能在其主线程上做了太多工作。 05-01 13:34:36.016 8342-8374/com.example.me.alarmmanagerexample W/art:暂停所有线程花费:189.200ms 05-01 13:34:36.436 8342-8374/com.example.me。 alarmmanagerexample W/art:暂停所有线程花费:109.066ms 05-01 13:34:37.237 8342-8342/com.example.me.alarmmanagerexample I /编舞:跳过了87帧!应用程序可能在其主线程上做了太多工作。 05-01 13:34:50.398 8342-8374/com.example.me.alarmmanagerexample W/art:暂停所有线程花费:49.095ms 05-01 13:34:56.375 8342-8374/com.example.me。 alarmmanagerexample W /艺术:挂起所有线程了:17.639ms

05-01 13:38:46.454 8342-8342/com.example.me.alarmmanagerexample I /为MyService:标志1 05-01 13:38:46.499 8342-8342/com.example.me.alarmmanagerexample E/AndroidRuntime:致命例外:main 进程:com.example.me.alarmmanagerexample,PID:8342 java.lang.IllegalStateException:无法执行android方法:onClick at android.support.v7.app.AppCompatViewInflater $ DeclaredOnClickListener.onClick(应用程序CompatViewInflater.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 .Zygote Init.main(ZygoteInit.java:618) 由于: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 com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java: 728) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 引起:java.lang.NullPointerException:试图调用虚拟方法java.lang.Object android.content.Context.getSystemService (java.lang.String)'在空对象引用 at android.content.ContextWrapper.getSystemService(ContextWrapper.java:627) at com.example.me.alarmmanagerexample.Alarm.SetAlarm(Alarm.java:43) 在com.example.me.alarmmanagere (com.example.me.alarmmanagerexample.MainActivity.startAlarm(MainActivity.java:61) at com.example.me.alarmmanagerexample.MainActivity.onBtnAlarmOnClick(MainActivity.java: 50) at android.support.v7.app java.lang.reflect.Method.invoke(Native Method) 。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) 在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)

+0

使用LogCat检查与您的崩溃相关的Java堆栈跟踪:https://stackoverflow.com/questions/23353173/uncomfort-myapp-has-stopped-how-can-i-solve-this – CommonsWare

+0

*程序已停止工作*和*应用程序已停止工作*是最终用户看到的显示。请参阅堆栈跟踪! –

+0

请粘贴stacktrace,以便我们检查导致崩溃的原因 – ishmaelMakitla

回答

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

决不发起与生命周期的Android组分如ServiceActivitynew用。这些实例不会被正确初始化,例如用作Context

不要自己调用生命周期方法,如onStart()。让框架为你打电话。

要正确启动Service,请使用startService()Intent

+0

谢谢。不过,我使用这样的服务是因为我对使用Android API的Android Development完全陌生,所以我对服务完全陌生,所以我不知道如何正确使用它们。但是我现在要查看一些关于如何使用服务的教程。所以你的回答似乎指向了一个很好的方向,以实现我在应用程序中完成的任务。 – user904542