我正在尝试创建一个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