2016-05-01 173 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