我正在嘗試創建一個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)
使用LogCat檢查與您的崩潰相關的Java堆棧跟蹤:https://stackoverflow.com/questions/23353173/uncomfort-myapp-has-stopped-how-can-i-solve-this – CommonsWare
*程序已停止工作*和*應用程序已停止工作*是最終用戶看到的顯示。請參閱堆棧跟蹤! –
請粘貼stacktrace,以便我們檢查導致崩潰的原因 – ishmaelMakitla