java - Android AlarmManager 执行代码时常无法正常工作

标签 java android alarmmanager

在我的应用程序中,我使用 AlarmManager 使其每 24 小时执行一次我想要的操作(例如)。

它几乎工作完美,但出于测试目的,我将间隔定义为 5000,如您在此处看到的:

MainActivity.java:

public void startAlarm() {
    manager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
    int interval = 5000;
            //86400000;
    manager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), interval, pendingIntent);
}

我的 AlarmReceiver.java:

public class AlarmReceiver extends BroadcastReceiver {
QuestsHelper db = new QuestsHelper(MainActivity.appContext);

@Override
public void onReceive(Context context, Intent intent) {

    // For our recurring task, we'll just display a message
    Random rand = new Random();
    long id = rand.nextInt(10);

    newQuest = db.getRandomQuest(id+1);

    MainActivity.desc.setText(newQuest.getDesc());
    MainActivity.status.setText(String.valueOf(newQuest.getProgress()));
    MainActivity.exp.setText(String.valueOf(newQuest.getExp()));

    SharedPreferences DadosNewQuest = PreferenceManager.getDefaultSharedPreferences(context);
    SharedPreferences.Editor editor = DadosNewQuest.edit();
    editor.putString("desc", newQuest.getDesc());
    editor.putInt("status", newQuest.getProgress());
    editor.putInt("exp", newQuest.getExp());
    editor.apply();

    SharedPreferences shareprefs = context.getSharedPreferences("cscs", MODE_PRIVATE);
    SharedPreferences.Editor editor2 = shareprefs.edit();
    editor2.putLong("cscs", newQuest.getCsGoal());
    editor2.commit();

    showNewQuestNotification();

    Log.d("AlarmReceiver", "TRIGGER");
}

private void showNewQuestNotification() {

    NotificationCompat.Builder builder =
            (NotificationCompat.Builder) new NotificationCompat.Builder(appContext)
                    .setSmallIcon(R.drawable.lpq)
                    .setContentTitle("New Quest available")
                    .setContentText("You have a new quest to do !");

    // para vibrar:
    // builder.setVibrate(new long[] { 1000, 1000});
    builder.setSound(Settings.System.DEFAULT_NOTIFICATION_URI);

    Intent notificationIntent = new Intent(appContext, MainActivity.class);
    PendingIntent contentIntent = PendingIntent.getActivity(appContext, 0, notificationIntent,
            PendingIntent.FLAG_UPDATE_CURRENT);
    builder.setContentIntent(contentIntent);
    // Add as notification
    NotificationManager manager = (NotificationManager) appContext.getSystemService(Context.NOTIFICATION_SERVICE);
    manager.notify(0, builder.build());
}
}

下面是 android log-cat,即使间隔设置为 5000,它似乎每一分钟执行一次。

Logcat

完成MainActivity.java

public class MainActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener {

public static Context appContext;
private PendingIntent pendingIntent;
private AlarmManager manager;
private Game selectedGame;
private SessionManager session;
private static final String TAG = "teste";
private static final String TAG2 = "teste2";
public static TextView desc;
public static TextView status;
public static TextView exp;
public EditText search;
public Button button;
public Long csjogo = null; // minions farmados
public static Quest newQuest = new Quest();

String URL = "";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_about);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    appContext=getApplicationContext();

    final SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
    final SharedPreferences shareprefs = getSharedPreferences("cscs", MODE_PRIVATE);
    final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
    SharedPreferences DadosNewQuest = PreferenceManager.getDefaultSharedPreferences(this);

    session = new SessionManager(getApplicationContext());

    desc = (TextView) findViewById(R.id.desc);
    status = (TextView) findViewById(R.id.status);
    exp = (TextView) findViewById(R.id.exp);
    search = (EditText) findViewById(R.id.search);
    button = (Button) findViewById(R.id.button);

    Intent alarmIntent = new Intent(this, AlarmReceiver.class);
    pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, 0);

    if (!prefs.getBoolean("firstTime", false)) {
        Log.d(TAG, "onCreate: CORREU");
        startAlarm();
        SharedPreferences.Editor editor = prefs.edit();
        editor.putBoolean("firstTime", true);
        editor.commit();
    }

    desc.setText(DadosNewQuest.getString("desc", ""));
    status.setText(String.valueOf(DadosNewQuest.getInt("status", 0)));
    exp.setText(String.valueOf(DadosNewQuest.getInt("exp", 0)));

    Log.d("lul", DadosNewQuest.getString("desc", ""));
    Log.d("lul", String.valueOf(DadosNewQuest.getInt("status", 0)));
    Log.d("lul", String.valueOf(DadosNewQuest.getInt("exp", 0)));

    MainActivity.status.setText(String.valueOf(newQuest.getProgress()));
    MainActivity.exp.setText(String.valueOf(newQuest.getExp()));

    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Toast.makeText(MainActivity.this, "A verificar ...", Toast.LENGTH_SHORT).show();
            verifyQUEST(sharedPref.getString("username", ""), shareprefs.getLong("cscs",0));
        }
    });

    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
            .permitAll().build();
    StrictMode.setThreadPolicy(policy);

    AsyncRiotAPI.setRegion(Region.EUW);
    AsyncRiotAPI.setAPIKey("");

    Log.d(TAG2, String.valueOf(shareprefs.getLong("cscs",0)));

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
            this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
    drawer.setDrawerListener(toggle);
    toggle.syncState();

    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
    navigationView.setNavigationItemSelectedListener(this);
}

public void startAlarm() {
    manager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
    int interval = 5000;
            //86400000;
    manager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), interval, pendingIntent);
}

public void cancelAlarm() {
    if (manager != null) {
        manager.cancel(pendingIntent);
        Toast.makeText(this, "Alarm Canceled", Toast.LENGTH_SHORT).show();
    }
}

public void verifyQUEST(String nick, final long csquest) {
    AsyncRiotAPI.getRecentGames(new Action<List<Game>>() {
        @Override
        public void perform(final List<Game> games) {

            runOnUiThread(new Runnable() {
                public void run() {

                    selectedGame = games.get(0);
                    csjogo = (long) selectedGame.getStats().getMinionsKilled() + selectedGame.getStats().getNeutralMinionsKilledEnemyJungle() + selectedGame.getStats().getNeutralMinionsKilledYourJungle();
                    Log.d(TAG, String.valueOf(csjogo));

                    if (csjogo >= csquest ) {
                        final SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
                        ViewDialog alert = new ViewDialog();
                        alert.showDialog(MainActivity.this, "Congratulations, quest completed !", csquest, csjogo);
                        addPoints(newQuest.getExp(), sharedPref.getString("username", ""));
                    } else {
                        NegativeViewDialog alert = new NegativeViewDialog();
                        alert.showDialog(MainActivity.this, "What a noob, you failed the quest !", csquest, csjogo);
                    }
                }
            });
        }
        @Override
        public void handle(APIException e) {
            Log.d(TAG, "ERRO, RIP");
        }
    }, nick );
}

private void addPoints (final int points, final String nickname) {

    StringRequest stringRequest = new StringRequest(Request.Method.POST, URL,
            new Response.Listener<String>() {
                @Override
                public void onResponse(String response) {
                    System.out.println(response);
                    Toast.makeText(MainActivity.this,response,Toast.LENGTH_LONG).show();
                }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    Toast.makeText(MainActivity.this,error.toString(),Toast.LENGTH_LONG).show();
                }
            }){
        @Override
        protected Map<String,String> getParams(){
            Map<String,String> params = new HashMap<String, String>();
            params.put("points", String.valueOf(points));
            params.put("nickname", nickname);
            return params;
        }

    };
    RequestQueue requestQueue = Volley.newRequestQueue(this);
    requestQueue.add(stringRequest);
}

@Override
public void onBackPressed() {
    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    if (drawer.isDrawerOpen(GravityCompat.START)) {
        drawer.closeDrawer(GravityCompat.START);
    } else {
        super.onBackPressed();
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.about, 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);
}

@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
    // Handle navigation view item clicks here.
    int id = item.getItemId();

    if (id == R.id.nav_login) {
        if ( session.isLoggedIn()) {
            Toast.makeText(appContext, "You are already logged in !", Toast.LENGTH_SHORT).show();
        } else {
            Intent intent = new Intent(MainActivity.this, LoginActivity.class);
            startActivity(intent);
        }
    } else if (id == R.id.nav_about) {

    } else if (id == R.id.nav_profile) {
        Intent intent = new Intent(MainActivity.this, ProfileQuest.class);
        startActivity(intent);
    } else if (id == R.id.nav_manage) {
        Intent intent = new Intent(MainActivity.this, QuestsActivity.class);
        startActivity(intent);
    } else if (id == R.id.nav_board) {

    } else if (id == R.id.nav_contacts) {

    } else if (id == R.id.nav_logout) {
        if (session.isLoggedIn()) {
            session.setLogin(false);
        }
        Toast.makeText(appContext, "logout", Toast.LENGTH_SHORT).show();
        Intent intent = new Intent(MainActivity.this, LoginActivity.class);
        startActivity(intent);
    } else if (id == R.id.nav_settings) {
        Intent intent = new Intent(MainActivity.this, UserSettings.class);
        startActivity(intent);
    }

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    drawer.closeDrawer(GravityCompat.START);
    return true;
}
}

有什么困难吗?

最佳答案

警报管理器不允许您在任何模式下每 20 秒触发一次以上。如果您需要更频繁地使用它,请使用 Handler 和 postDelayed 而不是警报。

使用 setRepeating,Android 保留重新安排您到系统更方便的时间的权利,以最大限度地减少定时器触发时的电池电量。 setExact 是获得更快计时器所需的方法,但仅应在绝对需要时使用。

请注意,在较新的 Android 上,Doze 将停止由 setExact 设置的任何计时器,但一旦 Doze 打开,每 15 分钟左右就会停止一个小窗口。 setExactAndAllowWhileIdle 将在打瞌睡期间触发,但只应用于非常重要的计时器,例如闹钟和 session 提醒。

关于java - Android AlarmManager 执行代码时常无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41528089/

相关文章:

android - 如何使用警报管理器重复我的服务?

android - 警报管理器不工作

java - 基类 C# 和 Java 不同的行为

java - Android - 膨胀类 EditText 时出错

android - 将三星安卓设备添加到eclipse

android - AlarmManager Android 每天上午10点触发闹钟

java - 如何用java实现MongoDB聚合 "switch"

java - 有没有办法阻止用户访问 Resteasy 中的 PUT、POST 和 DELETE 资源?

android - onRestoreInstanceState() 仅在屏幕旋转时调用吗?

Android 本地化 阿拉伯语