2015-08-15 2 views
1

Я потратил свое лето на изучение кода и создание своего первого приложения (в андроид-студии). Поэтому я не эксперт-кодер. На этой неделе я столкнулся с проблемой. В принципе, я разрабатываю приложение для викторины, и когда пользователь получает ответ неправильно, ему приходится ждать 5 минут. Дело в том, что когда начинается обратный отсчет времени, и пользователь закрывает приложение (закрывая приложение, я имею в виду уничтожить его, а не просто нажать кнопку «домой»). Countdowntimer останавливается. Мне интересно, как я могу удержать таймер, даже если приложение закрыто. Ваша помощь будет принята с благодарностью, и было бы замечательно, если бы вы, ребята, дали мне образец кода. Спасибо заранее!Как сохранить CountDownTimer, даже если приложение закрыто?

ответ

3

Запустите его в сервисе как таковом: используйте созданный широковещательный приемник в своей деятельности и передайте услуги для трансляции.

package com.example.cdt; 

import android.app.Service; 
import android.content.Intent; 
import android.os.CountDownTimer; 
import android.os.IBinder; 
import android.util.Log; 

public class BroadcastService extends Service { 

    private final static String TAG = "BroadcastService"; 

    public static final String COUNTDOWN_BR = "your_package_name.countdown_br"; 
    Intent bi = new Intent(COUNTDOWN_BR); 

    CountDownTimer cdt = null; 

    @Override 
     public void onCreate() {  
      super.onCreate(); 

      Log.i(TAG, "Starting timer..."); 

      cdt = new CountDownTimer(30000, 1000) { 
       @Override 
       public void onTick(long millisUntilFinished) { 

        Log.i(TAG, "Countdown seconds remaining: " + millisUntilFinished/1000); 
        bi.putExtra("countdown", millisUntilFinished); 
        sendBroadcast(bi); 
       } 

       @Override 
       public void onFinish() { 
        Log.i(TAG, "Timer finished"); 
       } 
      }; 

      cdt.start(); 
     } 

     @Override 
     public void onDestroy() { 

      cdt.cancel(); 
      Log.i(TAG, "Timer cancelled"); 
      super.onDestroy(); 
     } 

     @Override 
     public int onStartCommand(Intent intent, int flags, int startId) {  
      return super.onStartCommand(intent, flags, startId); 
     } 

     @Override 
     public IBinder onBind(Intent arg0) {  
      return null; 
     } 
} 

От основной деятельности:

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

    startService(new Intent(this, BroadcastService.class)); 
    Log.i(TAG, "Started service"); 
} 

private BroadcastReceiver br = new BroadcastReceiver() { 
    @Override 
    public void onReceive(Context context, Intent intent) {    
     updateGUI(intent); // or whatever method used to update your GUI fields 
    } 
}; 

@Override 
public void onResume() { 
    super.onResume();   
    registerReceiver(br, new IntentFilter(BroadcastService.COUNTDOWN_BR)); 
    Log.i(TAG, "Registered broacast receiver"); 
    } 

@Override 
public void onPause() { 
    super.onPause(); 
    unregisterReceiver(br); 
    Log.i(TAG, "Unregistered broacast receiver"); 
} 

@Override 
public void onStop() { 
    try { 
     unregisterReceiver(br); 
    } catch (Exception e) { 
     // Receiver was probably already stopped in onPause() 
    } 
    super.onStop(); 
} 
@Override 
public void onDestroy() {   
    stopService(new Intent(this, BroadcastService.class)); 
    Log.i(TAG, "Stopped service"); 
    super.onDestroy(); 
} 

private void updateGUI(Intent intent) { 
    if (intent.getExtras() != null) { 
     long millisUntilFinished = intent.getLongExtra("countdown", 0); 
     Log.i(TAG, "Countdown seconds remaining: " + millisUntilFinished/1000);    
    } 
} 

Примечание Я получил этот код из How to run CountDownTimer in a Service in Android?, который я модифицированное для моего собственного андроида countDownTimer.

+0

Пожалуйста, отметьте правильный ответ, если это поможет! :) – Sunny

+0

Как служба продолжает работать, когда приложение закрыто? OnPause/Stop не регистрирует приемник с onDestroy, останавливая обслуживание. Я понимаю, что активность не будет существовать, если приложение будет удалено из диспетчера задач, но вы хотите, чтобы служба продолжала работать, если ее countDownTimer все еще тикает – xceed

0

Вы должны использовать сервис. Вы можете узнать больше об этом link

1

Скачать исходный код здесь Android Countdown Timer Run In Background

activity_main.xml

<RelativeLayout android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    xmlns:android="http://schemas.android.com/apk/res/android"> 


     <EditText 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:id="@+id/et_hours" 
      android:hint="Hours" 
      android:inputType="time" 
      android:layout_marginRight="5dp" 
      /> 

    <Button 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:id="@+id/btn_timer" 
     android:layout_above="@+id/btn_cancel" 
     android:text="Start Timer"/> 

    <Button 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:layout_alignParentBottom="true" 
     android:id="@+id/btn_cancel" 
     android:text="cancel timer"/> 

    <TextView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:id="@+id/tv_timer" 
     android:layout_centerInParent="true" 
     android:textSize="25dp" 
     android:textColor="#000000" 
     android:text="00:00:00"/> 

    </RelativeLayout> 

MainActivity.java

package com.countdowntimerservice; 

import android.content.BroadcastReceiver; 
import android.content.Context; 
import android.content.Intent; 
import android.content.IntentFilter; 
import android.content.SharedPreferences; 
import android.preference.PreferenceManager; 
import android.support.v7.app.AppCompatActivity; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.Button; 
import android.widget.EditText; 
import android.widget.TextView; 
import android.widget.Toast; 

import java.text.SimpleDateFormat; 
import java.util.Calendar; 


public class MainActivity extends AppCompatActivity implements View.OnClickListener { 

    private Button btn_start, btn_cancel; 
    private TextView tv_timer; 
    String date_time; 
    Calendar calendar; 
    SimpleDateFormat simpleDateFormat; 
    EditText et_hours; 

    SharedPreferences mpref; 
    SharedPreferences.Editor mEditor; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     init(); 
     listener(); 


    } 

    private void init() { 
     btn_start = (Button) findViewById(R.id.btn_timer); 
     tv_timer = (TextView) findViewById(R.id.tv_timer); 
     et_hours = (EditText) findViewById(R.id.et_hours); 
     btn_cancel = (Button) findViewById(R.id.btn_cancel); 



     mpref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); 
     mEditor = mpref.edit(); 

     try { 
      String str_value = mpref.getString("data", ""); 
      if (str_value.matches("")) { 
       et_hours.setEnabled(true); 
       btn_start.setEnabled(true); 
       tv_timer.setText(""); 

      } else { 

       if (mpref.getBoolean("finish", false)) { 
        et_hours.setEnabled(true); 
        btn_start.setEnabled(true); 
        tv_timer.setText(""); 
       } else { 

        et_hours.setEnabled(false); 
        btn_start.setEnabled(false); 
        tv_timer.setText(str_value); 
       } 
      } 
     } catch (Exception e) { 

     } 



    } 

    private void listener() { 
     btn_start.setOnClickListener(this); 
     btn_cancel.setOnClickListener(this); 

    } 

    @Override 
    public void onClick(View v) { 

     switch (v.getId()) { 
      case R.id.btn_timer: 


       if (et_hours.getText().toString().length() > 0) { 

        int int_hours = Integer.valueOf(et_hours.getText().toString()); 

        if (int_hours<=24) { 


         et_hours.setEnabled(false); 
         btn_start.setEnabled(false); 


         calendar = Calendar.getInstance(); 
         simpleDateFormat = new SimpleDateFormat("HH:mm:ss"); 
         date_time = simpleDateFormat.format(calendar.getTime()); 

         mEditor.putString("data", date_time).commit(); 
         mEditor.putString("hours", et_hours.getText().toString()).commit(); 


         Intent intent_service = new Intent(getApplicationContext(), Timer_Service.class); 
         startService(intent_service); 
        }else { 
         Toast.makeText(getApplicationContext(),"Please select the value below 24 hours",Toast.LENGTH_SHORT).show(); 
        } 
/* 
        mTimer = new Timer(); 
        mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(), 5, NOTIFY_INTERVAL);*/ 
       } else { 
        Toast.makeText(getApplicationContext(), "Please select value", Toast.LENGTH_SHORT).show(); 
       } 
       break; 


      case R.id.btn_cancel: 


      Intent intent = new Intent(getApplicationContext(),Timer_Service.class); 
      stopService(intent); 

       mEditor.clear().commit(); 

       et_hours.setEnabled(true); 
       btn_start.setEnabled(true); 
       tv_timer.setText(""); 


       break; 

     } 

    } 

    private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { 
     @Override 
     public void onReceive(Context context, Intent intent) { 
      String str_time = intent.getStringExtra("time"); 
      tv_timer.setText(str_time); 

     } 
    }; 

    @Override 
    protected void onResume() { 
     super.onResume(); 
     registerReceiver(broadcastReceiver,new IntentFilter(Timer_Service.str_receiver)); 

    } 

    @Override 
    protected void onPause() { 
     super.onPause(); 
     unregisterReceiver(broadcastReceiver); 
    } 
} 

Timer_Service.java

package com.countdowntimerservice; 


import android.app.Service; 
import android.content.Intent; 
import android.content.SharedPreferences; 
import android.os.Handler; 
import android.os.IBinder; 
import android.preference.PreferenceManager; 
import android.support.annotation.Nullable; 
import android.util.Log; 

import java.text.SimpleDateFormat; 
import java.util.Calendar; 
import java.util.Date; 
import java.util.Timer; 
import java.util.TimerTask; 
import java.util.concurrent.TimeUnit; 

public class Timer_Service extends Service { 

    public static String str_receiver = "com.countdowntimerservice.receiver"; 

    private Handler mHandler = new Handler(); 
    Calendar calendar; 
    SimpleDateFormat simpleDateFormat; 
    String strDate; 
    Date date_current, date_diff; 
    SharedPreferences mpref; 
    SharedPreferences.Editor mEditor; 

    private Timer mTimer = null; 
    public static final long NOTIFY_INTERVAL = 1000; 
    Intent intent; 

    @Nullable 
    @Override 
    public IBinder onBind(Intent intent) { 
     return null; 
    } 

    @Override 
    public void onCreate() { 
     super.onCreate(); 

     mpref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); 
     mEditor = mpref.edit(); 
     calendar = Calendar.getInstance(); 
     simpleDateFormat = new SimpleDateFormat("HH:mm:ss"); 

     mTimer = new Timer(); 
     mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(), 5, NOTIFY_INTERVAL); 
     intent = new Intent(str_receiver); 
    } 


    class TimeDisplayTimerTask extends TimerTask { 

     @Override 
     public void run() { 
      mHandler.post(new Runnable() { 

       @Override 
       public void run() { 

        calendar = Calendar.getInstance(); 
        simpleDateFormat = new SimpleDateFormat("HH:mm:ss"); 
        strDate = simpleDateFormat.format(calendar.getTime()); 
        Log.e("strDate", strDate); 
        twoDatesBetweenTime(); 

       } 

      }); 
     } 

    } 

    public String twoDatesBetweenTime() { 


     try { 
      date_current = simpleDateFormat.parse(strDate); 
     } catch (Exception e) { 

     } 

     try { 
      date_diff = simpleDateFormat.parse(mpref.getString("data", "")); 
     } catch (Exception e) { 

     } 

     try { 


      long diff = date_current.getTime() - date_diff.getTime(); 
      int int_hours = Integer.valueOf(mpref.getString("hours", "")); 

      long int_timer = TimeUnit.HOURS.toMillis(int_hours); 
      long long_hours = int_timer - diff; 
      long diffSeconds2 = long_hours/1000 % 60; 
      long diffMinutes2 = long_hours/(60 * 1000) % 60; 
      long diffHours2 = long_hours/(60 * 60 * 1000) % 24; 


      if (long_hours > 0) { 
       String str_testing = diffHours2 + ":" + diffMinutes2 + ":" + diffSeconds2; 

       Log.e("TIME", str_testing); 

       fn_update(str_testing); 
      } else { 
       mEditor.putBoolean("finish", true).commit(); 
       mTimer.cancel(); 
      } 
     }catch (Exception e){ 
      mTimer.cancel(); 
      mTimer.purge(); 


     } 

     return ""; 

    } 

    @Override 
    public void onDestroy() { 
     super.onDestroy(); 
     Log.e("Service finish","Finish"); 
    } 

    private void fn_update(String str_time){ 

     intent.putExtra("time",str_time); 
     sendBroadcast(intent); 
    } 
} 

Спасибо!

Смежные вопросы