13

Tôi đang tái cấu trúc một số mã để ứng dụng của tôi sẽ lấy dữ liệu từ một trang web một lần một ngày tại một thời điểm nhất định. Từ nghiên cứu của tôi, có vẻ như AlarmManager là cách tiếp cận thích hợp nhất.AlarmManager, BroadcastReceiver và Dịch vụ không hoạt động

Các hướng dẫn, tôi đã theo là: http://mobile.tutsplus.com/tutorials/android/android-fundamentals-downloading-data-with-services/

Cho đến nay, AlarmManagerBroadcastReceiver dường như làm việc, tuy nhiên Service bao giờ dường như bắt đầu (. Tức là onStartCommand dường như không được gọi)

Dưới đây là các đoạn quan trọng của mã tôi có cho đến nay:

MyActivity.java

private void setRecurringAlarm(Context context) { 
    Calendar updateTime = Calendar.getInstance(); 
    updateTime.setTimeZone(TimeZone.getDefault()); 
    updateTime.set(Calendar.HOUR_OF_DAY, 20); 
    updateTime.set(Calendar.MINUTE, 30); 

    Intent downloader = new Intent(context, AlarmReceiver.class); 
    downloader.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
    PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, downloader, PendingIntent.FLAG_CANCEL_CURRENT); 
    AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); 
    // should be AlarmManager.INTERVAL_DAY (but changed to 15min for testing) 
    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis(), AlarmManager.INTERVAL_FIFTEEN_MINUTES, pendingIntent); 
    Log.d("MyActivity", "Set alarmManager.setRepeating to: " + updateTime.getTime().toLocaleString()); 
} 

AlarmReceiver.java

public class AlarmReceiver extends BroadcastReceiver { 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     Intent dailyUpdater = new Intent(context, MyService.class); 
     context.startService(dailyUpdater); 
     Log.d("AlarmReceiver", "Called context.startService from AlarmReceiver.onReceive"); 
    } 
} 

MyService.java

public class MyService extends Service { 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     Log.d("MyService", "About to execute MyTask"); 
     new MyTask().execute(); 
     return Service.START_FLAG_REDELIVERY; 
    } 

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

    private class MyTask extends AsyncTask<String, Void, boolean> { 
     @Override 
     protected boolean doInBackground(String... strings) { 
      Log.d("MyService - MyTask", "Calling doInBackground within MyTask"); 
      return false; 
     } 
    } 
} 

AndroidManifest.xml

<application ...> 
    ... 
    <service android:name="MyService"></service> 
    <receiver android:name="AlarmReceiver"></receiver> 
</application> 

Khi tôi tr igger setRecurringAlarm trong MyActivity bản ghi nhật ký như mong đợi, tương tự, cứ mỗi 15 phút nhật ký xuất hiện từ AlarmReceiver sẽ xuất hiện. Tuy nhiên, tôi không bao giờ nhìn thấy các bản ghi từ MyService :(

Ví dụ về những gì tôi nhìn thấy trong các bản ghi:

DEBUG/MyActivity(688): Set alarmManager.setRepeating to: Jan 29, 2012 8:30:06 PM 
DEBUG/AlarmReceiver(688): Called context.startService from AlarmReceiver.onReceive 
DEBUG/AlarmReceiver(688): Called context.startService from AlarmReceiver.onReceive 

dường như không thể tìm ra những gì tôi đã làm sai - hiểu biết của tôi từ Android Dev Docs được rằng trong AlarmReceiver khi tôi gọi context.startService(dailyUpdater) rằng trong cuộc gọi lần lượt onStartCommand trong MyService, mặc dù điều đó dường như không nên là trường hợp!

tôi đang làm gì sai đó gây ra MyService để không bắt đầu

01 ở tất cả?
+0

1 Cảm ơn mã của bạn giúp tôi .. – Nirali

+0

Bạn cũng đang chạy vào một hành vi wakelock không rõ ràng bắt đầu các dịch vụ để đáp ứng với báo động. Có một số chi tiết và đề xuất trong các câu trả lời tại http://stackoverflow.com/questions/25852309/does-alarmmanager-require-the-pendingintent-to-be-of-type-broadcastreceiver – ctate

Trả lời

15

Đã tìm ra!

MyService nên được mở rộng IntentService thay vì Dịch vụ!

Với thay đổi này, nó cũng có nghĩa là thay vì trọng onStartCommand nên trọng onHandleIntent thay thế (xem tài liệu trên IntentService)

Vì vậy MyService bây giờ trông như thế này:

public class MyService extends IntentService { 

    public MyService() { 
     super("MyServiceName"); 
    } 

    @Override 
    protected void onHandleIntent(Intent intent) { 
     Log.d("MyService", "About to execute MyTask"); 
     new MyTask().execute(); 
    } 

    private class MyTask extends AsyncTask<String, Void, boolean> { 
     @Override 
     protected boolean doInBackground(String... strings) { 
      Log.d("MyService - MyTask", "Calling doInBackground within MyTask"); 
      return false; 
     } 
    } 
} 

Note : Từ tài liệu, việc triển khai mặc định onBind trả về null do đó không cần phải ghi đè lên.

biết thêm thông tin về việc gia hạn IntentService: http://developer.android.com/guide/topics/fundamentals/services.html#ExtendingIntentService

+1

+1 Cảm ơn mã của bạn đã giúp tôi – Nirali

+1

+1 Cảm ơn! Lớp" Dịch vụ "hoạt động tốt trên các thiết bị Android 4.x nhưng tôi không thể tập luyện tại sao nó không hoạt động trên các thiết bị Android 2.x.Khi thay đổi thành "IntentService", nó hoạt động như một sự quyến rũ. –

0

Bạn có thể nhận AlarmManager để chạy Dịch vụ ngay lập tức chứ không phải trải qua một BroadcastReceiver, nếu bạn thay đổi ý định của bạn như thế này:

//Change the intent 
Intent downloader = new Intent(context, MyService.class); 
    downloader.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 

//Change to getService() 
PendingIntent pendingIntent = PendingIntent.getService(context, 0, downloader, PendingIntent.FLAG_CANCEL_CURRENT); 

Điều này có thể giải quyết vấn đề của bạn!

+0

Cảm ơn đề xuất - Tôi đã thử trước (mặc dù không có downloader.addFlags) và nó không hoạt động - sẽ thử với addFlags và xem nó có giúp ích gì không! Chỉ cần tự hỏi, tại sao 'BroadcastReceiver' tồn tại nếu bạn chỉ có thể chạy Dịch vụ trực tiếp? – pyko

+0

Đã thử thay đổi này - không hoạt động :(cũng đã cố gắng thay đổi 'ngữ cảnh' thành 'this' theo gợi ý của kumar ... không may mắn! – pyko

0

Thay vì sử dụng

Intent dailyUpdater = new Intent(context, MyService.class);

sử dụng

Intent dailyUpdater = new Intent(this, MyService.class);

gợi ý khác là để bắt đầu dịch vụ trực tiếp từ báo động hơn là gửi một phát sóng và bắt đầu phục vụ trong máy thu phát sóng.

+0

bạn đã thử mã ur không có downloader.addFlags (Intent.FLAG_ACTIVITY_NEW_TASK); –

+0

hi kumar, vâng tôi tin rằng tôi đã thử nó mà không có 'addFlags' là tốt, cũng không hoạt động. – pyko

Các vấn đề liên quan