2012-04-16 39 views
14

Tôi có một ứng dụng mà tôi hy vọng sẽ gửi chi tiết trong danh sách liên hệ Android tới máy chủ từ xa để người dùng có thể xem danh bạ của mình trực tuyến. Để thực hiện việc này, tôi muốn thông báo cho máy chủ từ xa về bất kỳ thay đổi nào được thực hiện trên điện thoại vào danh sách liên lạc.Phương thức Observer onChange được gọi là hai lần sau 1 thay đổi trong con trỏ

Tôi đã thiết lập một ContentObserver trên 'ContactsContract.Contacts.CONTENT_URI' từ một dịch vụ được bắt đầu khi điện thoại được khởi động.

Tôi có một số thời gian, 2 người đầu tiên là ngẫu nhiên, thứ ba là mối quan tâm chính của tôi.

1: Khi tôi đã thiết lập dịch vụ đăng ký ContentObserver trên Con trỏ của tôi, người quan sát đó chỉ tồn tại trong dịch vụ? Ý tôi là, nếu dịch vụ bị giết, thì contentObserver có tiếp tục quan sát không?

2: Tôi nghi ngờ câu trả lời là không, nhưng tôi vẫn sẽ hỏi. Có anyway biết được liên lạc đang được cập nhật là kích hoạt phương thức onchange của contentObserver của tôi? hiện tại tôi phải biên dịch danh sách tất cả địa chỉ liên hệ trên điện thoại và gửi chúng đến máy chủ từ xa của tôi, sẽ dễ dàng hơn rất nhiều khi chỉ gửi chi tiết danh bạ đang được cập nhật.

3: Đây là câu hỏi chính của tôi, khi tôi thực hiện thay đổi đối với Danh sách liên hệ, phương thức onChange đang được kích hoạt hai lần liên tiếp. 1 thay đổi, 2 cuộc gọi. Có anyway quản lý này?

public class ContactService extends Service { 

    JSONArray contactList; 

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

    @Override 
    public void onCreate() { 
     Log.i("C2DM","content observers initialised"); 
     super.onCreate(); 



     //Call Log Content Provider observer 

     MyContentContactsObserver contactsObserver = new MyContentContactsObserver(); 
     ContactService.this.getContentResolver().registerContentObserver (ContactsContract.Contacts.CONTENT_URI, true, contactsObserver); 

    } 

    private class MyContentContactsObserver extends ContentObserver { 

     public MyContentContactsObserver() { 
      super(null); 
     } 

     @Override 
     public void onChange(boolean selfChange) { 
      super.onChange(selfChange);  
      Log.i("LOG","detected change in contacts: "+selfChange); 
     } 
    } 
} 

kết quả trong 2 dòng nhanh chóng trong logcat của tôi:

detected change in contacts: false 
detected change in contacts: false 

Trả lời

29

tôi đã làm một việc thực hiện tương tự và đã thiết lập một ContentObserver qua các sự kiện lịch của URI. và tôi phải đối mặt với tất cả các vấn đề, bạn đang phải đối mặt với bây giờ. Vì vậy, câu hỏi của bạn với các giải pháp của tôi/gợi ý đi đây ....

1) Một lần tôi đã thiết lập một dịch vụ đăng ký một ContentObserver trên Cursor tôi, không quan sát mà chỉ tồn tại trong các dịch vụ? Ý tôi là, nếu dịch vụ bị giết, thì contentObserver có tiếp tục quan sát không?

Không, nó sẽ không quan sát nội dung của bạn trên URI. nhưng có giải pháp cho điều này. bạn có thể tạo một dịch vụ luôn chạy. Dịch vụ này sẽ được tạo lại ngay sau khi được loại bỏ do một số vấn đề về bộ nhớ hoặc sự loại bỏ bất ngờ khác. Nó sẽ luôn tiếp tục chạy trừ khi nó được loại bỏ một cách rõ ràng. Để tạo ghi đè dịch vụ như vậy OnStartCommand(Intent intent, int flags, final int startId) trong lớp Dịch vụ của bạn và trả lại START_STICKY. Hãy xem mã bên dưới.

public int onStartCommand(Intent intent, int flags, final int startId) { 

    String authenticationKey = ((MainApplication) getApplicationContext()).getDbConnector().getUserAuthDefault() ; 
    // if user is not registered yet, stop this service, it may be called from boot reciever. 
    if(authenticationKey == null){ 
     stopSelf(); 
    } 

    // restart, if we get killed. 
    return START_STICKY; 
} 

.

2: Tôi nghi ngờ câu trả lời là không, nhưng tôi vẫn sẽ hỏi. Có anyway khi biết số liên lạc đang được cập nhật nào đang kích hoạt phương thức onchange của contentObserver của tôi? hiện tại tôi phải biên dịch danh sách tất cả địa chỉ liên hệ trên điện thoại và gửi chúng tới máy chủ từ xa của tôi, sẽ dễ dàng hơn nhiều khi chỉ gửi chi tiết danh bạ đang được cập nhật.

Bạn lại đoán đúng. :). câu trả lời là không.
Không có cách nào để biết cụ thể địa chỉ liên hệ nào đã được cập nhật. ContentObserver chỉ cung cấp một sự kiện để cho bạn biết rằng một số thay đổi đã được thực hiện đối với dữ liệu được chỉ bởi uri. Nhưng tôi nghĩ rằng bạn đang xử lý tình hình không hiệu quả, khi bạn đang biên soạn danh sách của tất cả các địa chỉ liên lạc và gửi chúng trở lại máy chủ.
Tôi sẽ đề nghị bạn duy trì một danh sách các liên hệ đã được gửi thành công tới máy chủ, trong bộ nhớ cục bộ. Và lần tới khi bạn nhận được cuộc gọi theo phương thức onChange() của contentObserver, bạn tìm nạp tất cả contacts từ content_URI, so sánh chúng với danh sách được lưu trước đó và chỉ gửi các địa chỉ liên hệ được cập nhật lên máy chủ.

3: Đây là câu hỏi chính của tôi, khi tôi thực hiện một sự thay đổi của tôi Danh sách liên hệ phương pháp onChange đang được bắn hai lần liên tiếp nhanh chóng. 1 thay đổi, 2 cuộc gọi. Có anyway quản lý điều này?

Có điều này xảy ra, nhưng tôi đoán bạn đang có ấn tượng sai. Trong trường hợp của tôi, nó được sử dụng để bắn ngẫu nhiên hai lần hoặc ba lần hoặc thậm chí nhiều lần hơn. vì vậy tôi đã thiết lập một khoảng thời gian threshold_time. Khoảng thời gian trong đó nếu ContentObserver được kích hoạt lại, thì tôi sẽ không xử lý nó. Tôi đã làm một việc như thế này ..

long lastTimeofCall = 0L; 
long lastTimeofUpdate = 0L; 
long threshold_time = 10000; 

    /* (non-Javadoc) 
    * @see android.database.ContentObserver#onChange(boolean) 
    */ 
    @Override 
    public void onChange(boolean selfChange) { 
     super.onChange(selfChange); 

     Log.d("content service", "on change called"); 

     lastTimeofCall = System.currentTimeMillis(); 

     if(lastTimeofCall - lastTimeofUpdate > threshold_time){ 

     //write your code to find updated contacts here 

      lastTimeofUpdate = System.currentTimeMillis(); 
     } 

    } 

Hy vọng những đề xuất/giải pháp này sẽ hữu ích.

+1

+1, 10000ms giây có hoạt động trong mọi trường hợp mà không thành công hay không, bạn có thực hiện bất kỳ phản hồi nào về điều này từ người dùng không, cảm ơn? –

+0

i havent nhận được bất kỳ phản hồi nào từ người dùng về vấn đề này. Tôi sẽ không nói cách tốt nhất để thực hiện nhưng nó làm việc tốt như bây giờ.một loại bản vá mà chúng tôi phải thực hiện. –

+0

Tôi giống như 'currentTime = System.CurrentTimeMillis()' 'if (nextCallTime Kobor42

10

Xem xét cách bạn đăng ký người quan sát của mình. Đối số thứ hai của registerContentObserverboolean notifyForDescendents, bạn đã đặt nó thành true. vì vậy bạn sẽ được thông báo khi ContactsContract.Contacts.CONTENT_URI hoặc bất kỳ uris descandants của nó đã được thay đổi. Có thể là một số hoạt động liên hệ với thông báo kích hoạt id đã cho cả thông tin liên hệ uri và địa chỉ liên hệ toàn cầu uri - với đối số thứ hai là true người quan sát của bạn quan sát cả hai.

Một điều khác là bạn có thể đăng ký người quan sát nội dung cho số liên lạc id uri cụ thể - ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId). Tuy nhiên, điều này không liên quan gì đến vấn đề của bạn, nhưng việc đăng ký người quan sát riêng cho mỗi người liên hệ có vẻ khá xấu xí;)

Một đề xuất khác: Có thể giữ người quan sát là trường cuối cùng không tạo lại nó trong đó (nhưng chỉ đăng ký ở đó).

public class ContactService extends Service { 

    private final ContentObserver contactsObserver = new ContentObserver(null) { 

     @Override 
     public void onChange(boolean selfChange) { 
      super.onChange(selfChange);  
      Log.i("LOG","detected change in contacts: "+selfChange); 

      //your code here 
     } 
    }; 

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

    @Override 
    public void onCreate() { 

     super.onCreate(); 

     getContentResolver().registerContentObserver(
       ContactsContract.Contacts.CONTENT_URI, true, contactsObserver); 
    } 

    @Override 
    public void onDestroy() { 

     getContentResolver().unregisterContentObserver(contactsObserver); 

     super.onDestroy(); 
    } 
} 
5

Để đến ngay vị trí của bạn. 3: Có bao nhiêu thời gian giữa hai cuộc gọi đến người quan sát của bạn? Tôi nghĩ người quan sát của bạn được gọi hai lần vì đồng bộ hóa danh bạ, cũng cập nhật cơ sở dữ liệu. I E. lần đầu tiên là bản cập nhật thực tế của bạn, lần thứ hai là khi đồng bộ hóa hoàn tất và đăng ký giá trị đồng bộ hóa của nó trong cùng một hàng liên hệ.

Bạn có thể tắt đồng bộ hóa và xem liệu nó có được gọi hai lần không?

+0

Ahh, đó là một cuộc gọi tốt. Ive kể từ khi làm việc xung quanh vấn đề với lời khuyên được cung cấp ở trên, nhưng trả lời của bạn có ý nghĩa tốt. –

+0

hoàn toàn có ý nghĩa, đã không cố gắng nhưng có ý nghĩa .. và nếu đây là trường hợp? tôi vẫn nghĩ rằng chúng ta cần phải sử dụng một số cảnh ngưỡng .. – Farhan

-1

Đối mặt với cùng một vấn đề trong mã của riêng tôi và phát hiện ra rằng tôi đã gọi registerContentObserver() hai lần. Mặc dù nó dành cho cùng một URI và trong cùng một lớp, phương thức onChange (boolean selfChange) của tôi được gọi hai lần như là kết quả.

0

bạn có thể có hai hoặc nhiều phiên bản của ContactService mà tất cả chúng đều được đăng ký cùng một ContactsContract.Contacts.CONTENT_URI.

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