2013-01-18 27 views
5

Tôi có câu hỏi liên quan đến các tiện ích Android và đặc biệt là các dịch vụ Android. Đây là những gì tôi muốn làm: Trên điện thoại, người dùng có thể thêm tiện ích của tôi vào màn hình chính của mình. Các widget được dữ liệu của nó từ mạng. Sau khi đọc một số tutrials về điều này, tôi phát hiện ra rằng cách tiếp cận tốt nhất là tạo một dịch vụ lấy dữ liệu từ mạng (TCP socket) và sau đó cập nhật widget liên tục. Điều đó được thực hiện với ScheduledExecutorService thực hiện một Runnable trong một khoảng thời gian nhất định. Runnable sẽ kết nối với máy chủ, lấy dữ liệu và cập nhật tiện ích).Android - cập nhật tiện ích con trên dịch vụ với dữ liệu từ mạng. Cách tiếp cận tốt nhất?

Vấn đề của tôi bây giờ là tiện ích không cần phải cập nhật khi màn hình tắt và vì vậy dịch vụ không nên chạy vì hết pin. Câu hỏi của tôi là: Làm thế nào để làm điều đó một cách tốt nhất?

tôi thấy 2 phương pháp mà nhiều hơn hoặc ít hơn sẽ làm những gì tôi muốn:

  1. Khi trường hợp đầu tiên của widget được thêm vào màn hình chính, nó sẽ đăng ký một Receiver Broadcast rằng nhận được ACTION_SCREEN_ON và Hành động ý định ACTION_SCREEN_OFF từ hệ điều hành Android. Nếu ACTION_SCREEN_ON được kích hoạt, nó sẽ khởi động dịch vụ cập nhật, nếu không nó sẽ dừng dịch vụ. Nhưng tôi thực sự không chắc chắn nếu đó là một cách tiếp cận tốt vì thời gian phát sóng phát sóng.

  2. Trong Runnable của dịch vụ cập nhật, được thực thi định kỳ bởi ScheduledExecutorService và thực sự thực hiện công cụ mạng, tôi kiểm tra qua PowerManager.isScreenOn(), nếu màn hình đang bật. Nếu có, tôi thực thi mã mạng, nếu không thì sẽ không. Nhưng khi thiết bị ở chế độ chờ thì sao? Mã này có được thực hiện sau đó không? Điều gì về pin cống ở đây?

Có cách tiếp cận "thực hành tốt nhất" cho những gì tôi muốn làm không? Tôi đã đọc rất nhiều về AlarmManager và nó là một công cụ rất mạnh mẽ. Bạn có thể lên lịch các nhiệm vụ với điều này theo cách này, rằng chúng chỉ được thực thi khi màn hình đang bật không?

Cảm ơn sự giúp đỡ của bạn.

Trân trọng NiThDi

+0

Bạn có nghĩ gì về [Google Cloud Messaging] (http://developer.android.com/google/gcm/index.html) không? Bằng cách này, bạn sẽ không cần phải thăm dò ý kiến ​​cho dữ liệu (ngay cả khi chỉ khi thiết bị được thức) và bạn sẽ nhận được dữ liệu mới chỉ khi nó thay đổi. Ngoài ra, bạn sẽ nhận được lợi ích khi hiển thị phần mới nhất của nó khi người dùng đánh thức thiết bị của mình mà không bị chậm trễ ban đầu. – Audrius

+0

Xin chào, cảm ơn bạn đã trả lời nhanh. Tôi không nghĩ rằng Google Cloud Messaging có thể làm những gì tôi muốn. Vấn đề là (để làm rõ), rằng máy chủ được đề cập ở trên không phải là MỘT máy chủ cho tất cả người dùng. Nó là một ứng dụng máy chủ đang chạy trong máy tính của họ. Trong thực tế, ứng dụng này là một điều khiển từ xa kết nối với máy chủ trên một máy tính trong mạng LAN qua TCP/IP. – NiThDi

Trả lời

3

giải pháp đầu tiên của bạn (màn hình xử lý phụ tùng ON và chương trình phát sóng OFF) để vấn đề là con đường để đi. Bắt đầu một IntentService mới để liên lạc nền với máy chủ ứng dụng của bạn. Sau khi hoàn thành, gửi chương trình phát sóng "Đã hoàn thành" tùy chỉnh của bạn với kết quả và sau đó xử lý nó trong tiện ích của bạn.

Là một lợi ích bổ sung, nó sẽ cho phép nhiều phiên bản tiện ích của bạn hoạt động từ một "nguồn" và sẽ không tiêu thụ bất kỳ tài nguyên nào trong trường hợp người dùng không thêm bất kỳ tiện ích nào.

CẬP NHẬT Vì nó là không thể sử dụng màn hình ON/OFF chương trình phát sóng với một widget, tôi sẽ có thể sử dụng this (AlarmManager với một báo động ELAPSED_REALTIME (không ELAPSED_REALTIME_WAKEUP)) để sắp xếp một (mục đích) dịch vụ chạy. Bằng cách này, dịch vụ của bạn sẽ không được lên lịch khi màn hình tắt, nhưng sẽ chạy định kỳ khi nó được bật. Và nếu độ trễ giữa màn hình BẬT và TẮT lớn hơn khoảng thời gian, màn hình sẽ chạy ngay lập tức trên màn hình trở lại BẬT.

Đối với câu hỏi của bạn về thời gian phát của người phát sóng, như đã nói trước đó, hãy sử dụng IntentService cho một tác vụ dài và sau đó phát lại kết quả của bạn từ đó. Khi bạn bắt đầu một dịch vụ mà cuộc gọi không chặn để người nhận phát sóng sẽ kết thúc trong một vấn đề kịp thời.

CẬP NHẬT 2 Theo dõi màn hình this TẮT không có nghĩa là thiết bị đang ngủ. Bạn đã có một giải pháp cho vấn đề này bằng cách sử dụng PowerManager.isScreenOn().

+0

Cảm ơn câu trả lời của bạn. Nhưng còn về vòng đời của máy thu phát sóng thì sao? Tôi biết rằng một widget cũng là một bộ thu phát sóng, nhưng có vẻ như một lớp mở rộng AppWidgetProvider không thể nhận các hành động ACTION_SCREEN_ON/OFF. Và thật không may nếu tôi đăng ký một máy thu phát sóng mới (vì vậy một lớp mở rộng BroadcastReceiver) Tôi không thể chắc chắn về cuộc đời. Tôi cho rằng Android có thể giết bất kỳ BroadcastREceiver nào nếu nó cần bộ nhớ ?! – NiThDi

+0

Tôi đã không chú ý đến màn hình ON/OFF điều. Bạn nói đúng, không thể sử dụng nó với một widget. Tôi sẽ cập nhật câu trả lời của mình. – Audrius

0

Cách tiếp cận ELAPSED_REALTIME có thể hoạt động mà tôi nghĩ, nhưng kỳ lạ nó không phải là một ứng dụng thử nghiệm nhỏ mà tôi đã tạo. Về cơ bản ứng dụng thử nghiệm là một tiện ích và một IntentService. Widget chỉ hiển thị thời gian hiện tại, trong khi Intent Service nhận thời gian hiện tại và gửi một broadcast mà widget sử dụng trong phương thức onReceive() và tự cập nhật. Các widget là tất nhiên một người nhận đăng ký cho các hành động phát sóng tùy chỉnh. Trong phương thức onEnabled() trong tiện ích, tôi khởi tạo báo thức cho AlarmManager. Bây giờ một số mã:

Widget onEnabled():

@Override 
public void onEnabled(Context c) { 
    super.onEnabled(c); 

    Intent intent = new Intent(c.getApplicationContext(), SimpleIntentService.class); 

    PendingIntent intentExecuted = PendingIntent.getService(c.getApplicationContext(), 45451894, intent, 
      PendingIntent.FLAG_UPDATE_CURRENT); 

    AlarmManager alarmManager = (AlarmManager) c.getApplicationContext().getSystemService(Context.ALARM_SERVICE); 
    alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, 0, 3000, intentExecuted); 
} 

Widget onReceive():

SimpleIntentService onHandleIntent():

@Override 
protected void onHandleIntent(Intent intent) { 
    Log.w("TestService", "SimpleIntentService onHandleIntent called."); 
    String msg = new Date().toGMTString(); 

    Intent broadcastIntent = new Intent(); 
    broadcastIntent.setAction(Widget.ACTION_RESP); 
    broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT); 
    broadcastIntent.putExtra("msg", msg); 
    sendBroadcast(broadcastIntent); 
} 

Vì vậy, tôi đã thử nghiệm điều này trên Nexus 4 chạy Android 4.2.1 và trên trình giả lập với Android 4.0.4. Trong cả hai trường hợp, SimpleIntentService được tạo và onHandleIntent() được gọi cứ 3 giây một lần, ngay cả khi tôi tắt màn hình theo cách thủ công. Tôi hoàn toàn không biết tại sao AlarmManager vẫn lên lịch báo thức, bạn có ?!

Cảm ơn bạn!

+0

Theo [this] (https://groups.google.com/d/msg/android-developers/Airlo3g5luw/OcLEUW2aq6UJ) màn hình tắt không có nghĩa là thiết bị đang ngủ. Bạn đã có một giải pháp cho vấn đề này bằng cách sử dụng 'PowerManager.isScreenOn()'. – Audrius

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