3

我用过报警服务。我已经实现了每 1 分钟运行一次的警报。因此,即使在应用程序退出后,广播接收器 onReceive 方法也会被调用。我想在这个 onReceive 方法中实现一个计时器。我必须开始位置跟踪并等待 20 秒,然后我需要停止位置跟踪。

我已经尝试了以下,

TimerTask
Handler
Local Broadcast Receiver

但是一旦应用退出,以上所有内容都无法运行。

在警报接收器内部,我想实现计时器以等待 20 秒。
当应用程序处于退出状态时,我该如何实现?

我的 AlaramReceiver onReceive 方法:

 @Override
public void onReceive(Context context, Intent intent) {
    mContext = context;
    mSharedPrefManager = SharedPrefManager.getInstance(mContext);

    mAppUtilInstance.logDebugMessage(TAG, "Track interval alarm receiver.");

    // // Check the preference having any current activity
    if (mSharedPrefManager.checkForCurrentActivityPref()) {
        userActivity = mSharedPrefManager.getCurrentUserActivityPref();

        if (mSharedPrefManager.getIsUserMovedPref()) {
            // User MOVED
            // Call the location service
            LocationUpdateTimer locationUpdateTimer = new LocationUpdateTimer(
            mContext, userActivity, true);
                locationUpdateTimer.initialize();
            mSharedPrefManager.setIsUserMovedPref(false);
        } else {
            // User not MOVED in between the track interval period. He is
            // IDLE
            // Check whether the location information is returned by the
            // google API
            if (mSharedPrefManager.checkForLocationEntityPref()
                    && mSharedPrefManager.getLocationEntityPref()
                            .getLatitude().length() > 0) {
                // Send the packet information to the Fleetilla server
                StoreAndSendLocationInformation storeAndSendLocationInformation = new StoreAndSendLocationInformation(
                        mContext,
                        mSharedPrefManager.getLocationEntityPref(),
                        userActivity);
                storeAndSendLocationInformation.storeAndSend();
            } else {
                // If the location information is not available
                mAppUtilInstance
                        .logDebugMessage(TAG,
                                "Location information is not generated to store and send.");
            }
        }
    }
}

位置更新定时器类:

/**
 * LocationUpdateTimer Constructor
 */
public LocationUpdateTimer(Context context, String userActivity,
        boolean isTosend) {
    // Save the context
    mContext = context;
    mUserCurrentActivity = userActivity;
    isToSendLocationInfo = isTosend;
}

/**
 * To start the location reporting
 */
private void startLocationReporting() {
    if (mLocationProviderStatusListener != null) {
        mLocationProviderStatusListener
                .requestLocationProvidersToUpdateStatus(mConstants.EMPTY_STRING);
        scheduleTimerTask();
    }
}

/**
 * To schedule the 20 seconds timer task to get the best location
 * information and send it to Fleetilla server.
 */
private void scheduleTimerTask() {
    bestGPSInfoTimerHandler = new Handler();
    bestGPSInfoTimerHandler.postDelayed(bestGPSInfoRunnable,
            Constants.TIMER_TASK_DELAY);
    mAppUtilInstance.logDebugMessage(TAG,
            "20 Sec Location Update TimerTask Scheduled");
}

/**
 * To cancel the timer tack which was scheduled for 30sec location update
 */
private void cancelTimerTask() {
    if (bestGPSInfoTimerHandler != null) {
        mAppUtilInstance.logDebugMessage(TAG, "20 sec TimerTask canceled");
        bestGPSInfoTimerHandler.removeCallbacks(bestGPSInfoRunnable);
        bestGPSInfoTimerHandler = null;
    }
}
/**
 * A runnable will be called after the 20 sec time interval
 */
Runnable bestGPSInfoRunnable = new Runnable() {
    @Override
    public void run() {
        // Called after 20 seconds
        mAppUtilInstance.logDebugMessage(TAG,
                "TimerTask running after 20 sec interval.");
        stopLocationReporting();
        cancelTimerTask();

        if (isToSendLocationInfo) {
            // Check whether the location information is returned by the
            // google api
            if (mSharedPrefManager.checkForLocationEntityPref()
                    && mSharedPrefManager.getLocationEntityPref()
                            .getLatitude().length() > 0) {
                // Send the packet information to the server
                StoreAndSendLocationInformation storeAndSendLocationInformation = new StoreAndSendLocationInformation(
                        mContext,
                        mSharedPrefManager.getLocationEntityPref(),
                        mUserCurrentActivity);
                storeAndSendLocationInformation.storeAndSend();
            } else {
                // If the location information is not available
                mAppUtilInstance
                        .logDebugMessage(TAG,
                                "Location information is not generated to store and send.");
                mAppUtilInstance
                        .broadcastStatusMessage(
                                mContext,
                                Constants.STATUS_MSG_127
                                        + "Location information is not generated to store and send.",
                                Constants.STATUS_CODE_127);
            }
        }

    }
};
4

2 回答 2

1

从 Android API 11 开始,您可以在方法中调用goAsync()onReceive()。此方法返回PendingResult类型的对象。Android 系统认为接收者是活动的,直到你调用PendingResult.finish()这个对象。使用此选项,您可以在接收器中触发异步处理。一旦该线程完成,它的任务就会调用finish()以向 Android 系统指示该组件可以被回收。

这是一个要演示的示例项目goAsync()BroadcastReceiver

于 2014-12-30T09:59:39.890 回答
0

带有 PendingIntent 的 AlarmManager 可以工作。这就是我在我的一个应用程序中执行此操作的方式:

    myAlarm = (AlarmManager) getSystemService(ALARM_SERVICE);
    Intent myNewIntent = new Intent(MyCurrentActivityClass.this, MyNewActivityClass.class);
    Calendar wakeUpTime = Calendar.getInstance(); 
    wakeUpTime.add(Calendar.MILLISECOND, (int) myTimeRemaining); 

    myPendingIntent = PendingIntent.getActivity(MyCurrentActivityClass.this, 0, myNewIntent, 0);
    myAlarm.set(AlarmManager.RTC_WAKEUP, wakeUpTime.getTimeInMillis(), myPendingIntent);

您还可以将以下内容放入您的 MyNewActivityClass 以唤醒设备并通过安全屏幕显示。

public void onAttachedToWindow() {
    //make the activity show even the screen is locked.
    Window window = getWindow();

    window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
            + WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
            + WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
            + WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
}
于 2014-12-30T09:54:23.563 回答