17

ユーザーが自分の連絡先をオンラインで確認できるように、Androidの連絡先リストの詳細をリモートサーバーに送信したいと考えているアプリがあります。これを行うには、電話で行われた変更を連絡先リストに変更したことをリモートサーバーに通知します。

電話の起動時に開始されるサービスから、「ContactsContract.Contacts.CONTENT_URI」にContentObserverを設定しました。

私にはいくつかの質問があります。最初の2つは偶発的なもので、3つ目は私の主な関心事です。

1:カーソルにContentObserverを登録するサービスを設定した後、そのオブザーバーはサービス内にのみ存在しますか?つまり、サービスが強制終了された場合、contentObserverは引き続き監視しますか?

2:答えはノーだと思いますが、とにかく聞いてみます。更新されている連絡先がcontentObserverのonchangeメソッドをトリガーしていることを知る方法はありますか?現在、電話上のすべての連絡先のリストを編集してリモートサーバーに送信する必要があります。更新されている連絡先の詳細を送信する方が、はるかに簡単です。

3:これが私の主な質問です。連絡先リストに変更を加えると、onChangeメソッドが2回続けて実行されます。1回の変更、2回の呼び出し。これを管理する方法はありますか?

    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);
        }
    }
}

私のlogCatの2つのクイックラインで結果:

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

5 に答える 5

31

私は同様の実装を行い、ContentObserverカレンダーのイベントを設定しましたURI。そして私はすべての問題に直面しました、あなたは今直面しています。だから私の解決策/提案に関するあなたの質問はここに行きます...

1)カーソルにContentObserverを登録するサービスを設定した後、そのオブザーバーはサービス内にのみ存在しますか?つまり、サービスが強制終了された場合、contentObserverは引き続き監視しますか?

いいえ、URIを介してコンテンツを監視することはありません。しかし、これには解決策があります。常に実行されるサービスを作成できます。このサービスは、メモリの問題またはその他の予期しない却下のために却下されるとすぐに再作成されます。明示的に却下されない限り、常に実行を継続します。OnStartCommand(Intent intent, int flags, final int startId)Serviceクラスでそのようなサービスオーバーライドを作成し、を返しSTART_STICKYます。以下のコードをご覧ください。

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:答えはノーだと思いますが、とにかく聞いてみます。更新されている連絡先がcontentObserverのonchangeメソッドをトリガーしていることを知る方法はありますか?現在、電話上のすべての連絡先のリストを編集してリモートサーバーに送信する必要があります。更新されている連絡先の詳細を送信する方が、はるかに簡単です。

あなたは再びそれを正しく推測しました。:)。答えは「いいえ
」です。どの連絡先が更新されたかを具体的に知る方法はありません。ContentObserverは、URIが指すデータに何らかの変更が加えられたことを通知するイベントを提供するだけです。しかし、すべての連絡先のリストをコンパイルしてサーバーに送り返すため、状況を非効率的に処理していると思います。
サーバーに正常に送信された連絡先のリストをローカルストレージに保持することをお勧めします。そして、次にあなたの呼び出しonChange()メソッドを受け取ったときに、からcontentObserverすべてをフェッチし、それらを以前に保存されたリストと比較して、更新された連絡先のみをサーバーに送信します。 contactscontent_URI

3:これが私の主な質問です。連絡先リストに変更を加えると、onChangeメソッドが2回続けて実行されます。1回の変更、2回の呼び出し。これを管理する方法はありますか?

はい、これは起こりますが、あなたは間違った印象を持っていると思います。私の場合、それはランダムに2回、3回、またはそれ以上の回数発砲していました。だから私はthreshold_time間隔を設定しました。ContentObserver再度起動された場合、処理されない時間間隔。私はこのようなことをしました。

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();
        }

    }  

これらの提案/解決策がお役に立てば幸いです。

于 2012-05-25T10:25:42.150 に答える
12

オブザーバーを登録する方法を検討してください。の2番目の引数registerContentObserverboolean notifyForDescendents、に設定しましたtrue。そのため、ContactsContract.Contacts.CONTENT_URIまたはそのデスカンダントURIのいずれかが変更されたときに通知されます。特定のIDを使用した連絡先の操作によって、特定の連絡先URIとグローバル連絡先URIの両方の通知がトリガーされる可能性があります。2番目の引数はtrue、オブザーバーが両方を監視することです。

もう1つは、特定の連絡先IDuri-のコンテンツオブザーバーを登録できることですContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId)。ただし、これは問題とは関係ありませんが、連絡先ごとに個別のオブザーバーを登録するのはかなり醜いようです;)

別の提案:たぶん、最後のフィールドとしてオブザーバーをonCreateで再作成しないでください(ただし、そこに登録するだけです)。

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();
    }
}
于 2012-05-26T15:23:50.760 に答える
5

あなたの番号にすぐに来てください。3: オブザーバーへの 2 つの呼び出しの間にどのくらいの時間がありますか? 連絡先の同期により、オブザーバーが2回呼び出され、データベースも更新されると思います。すなわち。1 回目は実際の更新で、2 回目は同期が完了し、同期値が同じ連絡先行に登録されたときです。

同期をオフにして、まだ 2 回呼び出されるかどうかを確認できますか?

于 2012-09-16T13:32:56.337 に答える
0

同じ ContactsContract.Contacts.CONTENT_URI に登録されている ContactService のインスタンスが 2 つ以上ある場合があります。

于 2016-08-11T01:07:38.190 に答える