【问题标题】:How do I repeat a method every 10 minutes after a button press and end it on another button press如何在按下按钮后每 10 分钟重复一次方法并在按下另一个按钮时结束它
【发布时间】:2012-04-30 14:36:27
【问题描述】:

我正在编写一个 Android 应用程序,它可以检索手机的当前位置并将其发送到网络服务器。 我希望能够按下开始按钮并让应用程序以预定的时间间隔(比如每 10 分钟)继续检索和发送位置,然后在按下另一个按钮时停止。

这是我的按钮的代码:

public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

   startButton.setOnClickListener(new OnClickListener() {
    @Override
    //When the button is clicked
    public void onClick(View v) {
            finishButton.setEnabled(true);
            startButton.setEnabled(false);

            //Loops every 10mins
            pingCurrentLocation();

        }
    });

  finishButton.setOnClickListener(new OnClickListener() {
    @Override
    //When the button is clicked
    public void onClick(View v) {
            startButton.setEnabled(true);
            finishButton.setEnabled(false);

            pingCurrentLocation();

        }
    });  
}

pingCurrentLocation 是获取位置并发送它的函数。

我知道使用 AlarmManager 可能会实现我想要的,但我无法理解其中的任何一个。是否有任何明确的步骤或模板适用于我的情况。

【问题讨论】:

  • 我不明白,警报管理器是一种理想的方法......我正在使用警报管理器做同样的事情。服务会占用内存而且我不是特别喜欢线程所以我选择了AlarmManager。你想让我在这里分享我的代码吗?
  • 我知道这将是理想的,只是我在实现它时遇到了很多问题。如果您不介意分享您的代码,那就太好了。
  • @X-Man - 我更新了答案,详细说明了使用 AlarmManager/BroadcaseReceiver 组合。

标签: android


【解决方案1】:

创建一个BroadcastReceiver

public class AlarmReceiver extends BroadcastReceiver
{   

 @Override
 public void onReceive(Context context, Intent intent)
  {   
    //get and send location information
  }
}

并将其添加到您的AndroidManifest 以便注册接收者

<receiver
    android:name="com.coderplus.AlarmReceiver"
    android:exported="false">
</receiver>

现在您可以从您的Activity 设置一个重复警报,它将每 10 分钟调用一次接收器:

AlarmManager alarmManager=(AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis(),600000,
                                                                      pendingIntent);

若要取消警报,请使用等效的PendingIntentAlarmManager 上调用cancel()

AlarmManager alarmManager=(AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
alarmManager.cancel(pendingIntent);

或者如果你不想使用AlarmManager / BroadcastReceiver,那么这样的东西会帮助你。在你开始之前,请检查 - difference between timer and alarmmanager

private class MyTimerTask extends TimerTask {
    @Override
    public void run() {           
      //get and send location information 
    }
}

初始化TimerTimer任务:

Timer myTimer = new Timer();
MyTimerTask myTimerTask= new MyTimerTask();

停止或启动Timer

//to Stop
myTimer.cancel();
//to start
myTimer.scheduleAtFixedRate(myTimerTask, 0, 600000); //(timertask,delay,period)

参考 http://developer.android.com/reference/java/util/TimerTask.html

http://developer.android.com/reference/java/util/Timer.html

【讨论】:

  • 这可行,但是有一个问题。当我按下执行myTimer.scheduleAtFixedRate(myTimerTask, 0, 600000); 的开始按钮并按下停止/取消按钮然后再次按下开始时,应用程序崩溃了。
  • @coderplus:如果我从内存中杀死应用程序怎么办?还能用吗?
  • 您如何在此处取消注册接收器?
【解决方案2】:

使用Android-TimerTaskAndroid-AlarmManager 每10 分钟发送一次位置数据。看看这个SO问题Track Gps At every 10 minutes using timer in android还有这个Good way of getting the user's location in Android

TimerTask:

TimerTask 类表示要在指定时间运行的任务。该任务可以运行一次或重复运行。

【讨论】:

    【解决方案3】:

    这就是我所做的。

    首先创建了一个报警管理器对象,并设置了重复定时器

    AlarmManager alarmMgr = alarmMgr=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
    Intent alarmIntent = alarmIntent = new Intent("AlarmIntentReceiver"); 
    PendingIntent pendingAlarmIntent = pendingAlarmIntent = PendingIntent.getBroadcast(context.getApplicationContext(), 0, alarmIntent, 0);
    alarmMgr.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, 30*1000, 3*60*1000,  pendingAlarmIntent); //start in 30 secs and rest in 3 mins interval
    

    根据该意图名称创建了一个活动,该活动将捕获该意图并在指定的时间间隔内执行其代码,如果您愿意,还可以创建一个广播接收器。

    在您的按钮单击事件中取消它。写这个

    alarmMgr.cancel(pendingAlarmIntent);
    

    【讨论】:

    • context 是什么?它的价值观是什么?抱歉,我是编程新手。
    • 上下文是关于应用程序环境的全局信息的接口。这是一个抽象类,其实现由Android系统提供。它允许访问特定于应用程序的资源和类,以及向上调用应用程序级操作,例如启动活动、广播和接收意图等。您可以在此处阅读更多内容 (developer.android.com/reference/android/content/Context.html)... 如果您不这样做'不了解上下文,那么您可能需要先了解一些 android 基础知识...
    【解决方案4】:

    您可以启动一项服务,该服务将检查用户位置并将其发送到您指定的网址,如下所述。

    您可以获取更多关于服务here的信息

    public class TaxiLocationUpdator extends Service{
        Location location;
        Timer timer = new Timer();
        private final Handler handler = new Handler();
        Intent intent;
    
        @Override
        public IBinder onBind(Intent arg0) {
            // TODO Auto-generated method stub
            return null;
        }
    
        public void  onCreate(){
            super.onCreate();
            updateNotification();
        }
    
        //int onStartCommand(Intent intent, int flags, int startId) 
        public void onStart(Intent intent,int startId){
            super.onStart(intent, startId);
            handler.removeCallbacks(sendUpdatesToUI);
                handler.postDelayed(sendUpdatesToUI, 1000); // 1 second
            Log.v("Location Servics", "Start Service");
        }
    
         private Runnable sendUpdatesToUI = new Runnable() {
                public void run() {
                    DisplayLoggingInfo();           
                        handler.postDelayed(this, 15000); // 60 seconds here you can give your time
                }
            };    
    
        public void onDestroy(){
            super.onDestroy();
            Log.v("Location Servics", "Destroy Service");
        }
    
        public boolean isOnline(){
                ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
                NetworkInfo netInfo = cm.getActiveNetworkInfo();
                boolean isconnected;
                if (netInfo==null || !netInfo.isConnected())
                isconnected=false;
                else
                isconnected=true;
                Log.v("isOnliNe",isconnected+"");
                return isconnected;
            }
    
        protected void updateNotification() {
                 LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
                 LocationListener locationListener = new MyLocationlistener();
    
                 lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, normallocationwait, 0.250f, locationListener);
                 location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
           }
    
           private class MyLocationlistener implements LocationListener {
    
             public void onLocationChanged(Location location){
                 if(location!=null){
                     if(location.hasAccuracy()){
                           dumpLocation(location);
                     }else{
                           dumpLocation(location);
                    }
                 } 
             }
    
             public void onProviderDisabled(String provider){
                 Log.v("Loc Update","\nProvider disabled: " + provider);
             }
    
             public void onProviderEnabled(String provider){
                 Log.v("Loc Update","\nProvider enabled: " + provider);
             }
    
             public void onStatusChanged(String provider, int status, Bundle extras){
                 Log.v("Loc Update","\nProvider status changed: " + provider + ", status="
                            + status + ", extras=" + extras);
             }
    
             private void dumpLocation(Location location) {
                     if (location == null)
                            Log.v("Loc Update","\nLocation[unknown]");
                     else{
                             Log.v("Loc Update","\n" + location.toString());
                             Log.v("Demo", location.toString());
                                     String url  = Your url;
                             Toast.makeText(getBaseContext(), "Location Update", Toast.LENGTH_SHORT).show();
                             if(isOnline()){
                                HttpClient httpclient = new DefaultHttpClient();
                                HttpPost httppost = new HttpPost(url);
                                try {
                                    HttpResponse response = httpclient.execute(httppost);
                                    Log.v("Message", response.toString());
                                  } catch (ClientProtocolException e) {
                                      Log.e("Sending Message",e.getMessage().toString());
                                  } catch (IOException e) {
                                      Log.e("Sending Message",e.getMessage().toString());
                                }
                         }
                    } 
              }
    
             public boolean isOnline(){
                ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
                NetworkInfo netInfo = cm.getActiveNetworkInfo();
                boolean isconnected;
                if (netInfo==null || !netInfo.isConnected())
                isconnected=false;
                else
                isconnected=true;
                Log.v("isOnliNe",isconnected+"");
                return isconnected;
             }
         }
    }
    

    【讨论】:

      【解决方案5】:

      使用线程和处理程序

         Handler alarmCheckHandler = new Handler() {
      
              @Override
              public void handleMessage(Message msg) {
                  super.handleMessage(msg);
      
                      System.out.println("getting message from alarm thread");
                      //Call your function for ping
      
      
      
          };
      Thread alarmCheckThread = new Thread() {
              public void run() {
                  int i = 0;
                  synchronized (this) {
                      while (checkflag) {
                          i++;
                          try {
                              sleep(1000);
                          } catch (InterruptedException e) {
                              // TODO Auto-generated catch block
                              e.printStackTrace();
                          }
                          if (i == 600) {
                              alarmCheckHandler.sendMessage(alarmCheckHandler
                                      .obtainMessage());
                              i = 0;
                          }
      
                      }
                      System.out.println("End of unlimited while loop reched");
                  }
              }
          };
      

      开始通话

      alarmCheckThread.start();
      

      停止通话

      alarmCheckThread.interrupt();
      

      【讨论】:

      • interrupt 已被弃用,如何阻止它?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多