Как запланировать выполнение кода в Android или: что такое потоки демонов в Android? - PullRequest
4 голосов
/ 07 октября 2010

В настоящее время я работаю над приложением для Android OS, которое время от времени требует извлекать данные с удаленного сервера.

, поскольку это «обновление» должно выполняться, даже если само приложение внешнего интерфейса не запущено, я реализовал удаленную службу, которая запускается при загрузке системы. Теперь мне нужно запланировать таймер, чтобы начать обновление.

Является ли класс "Таймер" правильным для этой работы? и если «да»: в чем разница между «обычным» Timer () и тем, который Timer (true) начал как «демон» (true)?

http://developer.android.com/reference/java/util/Timer.html не очень помогает с этим: (

EDIT:

хорошо, я вижу, что способов сделать это гораздо больше, чем я ожидал. уточнить:

  • Я хочу выполнить некоторый код в указанное время.
  • этот таймер используется для запуска выполнения кода через 7 дней. (то есть каждую неделю в определенный день и время недели)
  • код должен работать БЕЗ пробуждения телефона, если он «спит» (экран затемнен).
  • при запуске кода никакие действия не должны запускаться. то есть ни одно приложение не появляется на экране.
  • код, который выполняется, должен получить некоторые данные из Интернета. если в это время нет подключения к Интернету, таймер должен быть установлен как 30 минут, а затем повторите попытку.
  • после завершения выполнения кода таймер будет установлен на следующий интервал, который будет через 7 дней.
  • таймер должен запускаться при загрузке системы, например, если я перезагружаю телефон, таймер должен определить следующую дату для выполнения кода и запланировать таймер. это должно работать без ЛЮБОГО взаимодействия с пользователем!
  • при «спящем» потоке / сервисе / таймере / чем бы то ни было не должно потребляться никаких системных ресурсов, если это возможно ...

  • Что мне нужно, так это простой Unix Cronjob.

Я думаю, что кто-нибудь здесь знает "Newsrob" для Android? то, что я хочу понять, в значительной степени совпадает с новостной службой обновления новостей.

Ответы [ 2 ]

4 голосов
/ 07 октября 2010

Используйте AlarmManager. Это позволяет вам установить расписание, а затем выйти из ваших компонентов. Ваш код не должен оставаться в памяти и будет срабатывать, когда звучит сигнал тревоги.

я реализовал удаленную службу, которая запускается при загрузке системы

Пожалуйста, не делайте это только для запланированного задания. Используйте AlarmManager.

Если вы хотите, чтобы работа выполнялась, когда телефон спит, вам нужно будет использовать _WAKEUP тип будильника и, возможно, использовать что-то вроде моего WakefulIntentService, чтобы держать устройство включенным, пока работа ведется.

2 голосов
/ 07 октября 2010

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

Вот как я его спроектировал:

Я создал службу, запущенную либо явно внешним интерфейсом, при включении его через конфигурациюдиалоговое окно, запущенное BroadcastReceiver в ожидании активации подключения к сети:

    <receiver android:name=".notifications.MyReceiver">
        <intent-filter>
            <action android:name="android.net.conn.BACKGROUND_DATA_SETTING_CHANGED"/>
            <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
        </intent-filter>
    </receiver>

При запуске служба запускает новый HandlerThread и связывает его с Looper:

public class MyService extends Service {

    private Looper serviceLooper;
    private MyHandler serviceHandler;

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

    @Override
    public void onCreate() {
        //Toast.makeText(this, "service started", Toast.LENGTH_SHORT).show();

        HandlerThread thread = new HandlerThread("MyHandlerThread", Process.THREAD_PRIORITY_BACKGROUND);
        thread.start();

        serviceLooper = thread.getLooper();
        serviceHandler = new MyHandler(this, serviceLooper);

        // initial message
        serviceHandler.sendMessage(Message.obtain());
    }

    @Override
    public void onDestroy() {
        serviceLooper.quit();
        //Toast.makeText(this, "service stopped", Toast.LENGTH_SHORT).show();
    }

}

Когда сеть выходит из строя или веб-интерфейс отключает ее, служба останавливается, а также петлитель.

Теперь в MyHandler я фактически получаю обновления с сервера при получении сообщений.

public class MyHandler extends Handler {

    private final Context context;

    public MyHandler(Context context, Looper looper) {
        super(looper);
        this.context = context;
    }

    @Override
    public void handleMessage(Message msg) {
        // handle message and perform update
        // ...
        // try again 30 minutes
        this.sendMessageDelayed(Message.obtain(), 1000 * 60 * 30);
    }
}

Хитрость, как вы можете видеть, состоит в том, чтобы отправить себе отложенное сообщение, которое будет обработано через 30 минут.

Преимущество этого решения по сравнению с использованием AlarmManager заключается в том, что телефон НЕ насильно просыпаться в назначенное время, что означает, что он лучше работает с телефонными ресурсами, если не нужен.

Более того, я не запускаю службу во время загрузки, только когда есть активное подключение к Интернету, и я прекращаю его, как только подключение исчезает.

Пока это было довольно эффективно.

...