如何从Android中的同步适配器服务访问已经运行的应用程序上下文?

时间:2011-11-05 04:53:04

标签: service sync android

我有一个由多个活动组成的应用程序,我使用应用程序上下文(从应用程序类中使用,并使其持久化)在所有活动之间共享数据和对象。我使用Application Class而不是后台服务有几个很好的理由,我不会在这里讨论。

我最近还在我的应用中添加了自定义联系人同步适配器。它在相同的包下,在同一个APK中。因此,我将其设置为访问应用程序上下文,就像我的应用程序中的其他内容一样,使其可以访问所有共享数据和对象。但是,即使它(大多数情况下)有效,它也会创建一个新的Application Context实例。因此,我的应用程序基本上有两个独立的实例在运行,并且它们之间不共享数据。

我认为问题在于我的应用程序永远不会启动同步服务,操作系统会这样做。我的所有其他活动都是由应用程序启动的,或者主活动在启动时访问Application Context,然后App Context控制其他所有活动。有没有办法让同步服务访问现有的应用程序上下文,而不是创建它的新实例?

以下是我的应用的基本结构:

该应用程序

package com.mycomany.myapp;    
public class MyApp extends Application{
    ...
}

活性1

package com.mycomany.myapp;
public class MyActivity1 extends Activity{
    MyApp a;

    @Override
    public void onCreate(Bundle savedInstanceState){
        a = (MyApp) getApplicationContext();
        ...
    }
}

SyncAdapterService

package com.mycomany.myapp;
public class SyncAdapterService extends Service {
    private static SyncAdapterImpl sSyncAdapter = null;
    private static final Object sSyncAdapterLock = new Object();
    private static ContentResolver mContentResolver = null;
    private static MyApp a;

    public SyncAdapterService() {
        super();
    }

    private static class SyncAdapterImpl extends AbstractThreadedSyncAdapter {
        private Context mContext;

        public SyncAdapterImpl(Context context) {
            super(context, true);
            mContext = context;
        }

        @Override
        public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
            try {
                SyncAdapterService.performSync(mContext, account, extras, authority, provider, syncResult);
            } catch (OperationCanceledException e) {}
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        synchronized (sSyncAdapterLock) {
            if(a == null){
                a = (MyApp) getApplicationContext();
            }
            if (sSyncAdapter == null) {
                sSyncAdapter = new SyncAdapterImpl(getApplicationContext());
            }
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return sSyncAdapter.getSyncAdapterBinder();
    }

    private static void performSync(Context context, Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult)
            throws OperationCanceledException {
...
    }
}

3 个答案:

答案 0 :(得分:7)

您是否已为SyncAdapter http://developer.android.com/training/sync-adapters/creating-sync-adapter.html复制并粘贴了此培训?

最后有这个XML片段:

    <service
            android:name="com.example.android.datasync.SyncService"
            android:exported="true"
            android:process=":sync">
        <intent-filter>com.example.android.datasync.provider
            <action android:name="android.content.SyncAdapter"/>
        </intent-filter>
        <meta-data android:name="android.content.SyncAdapter"
                android:resource="@xml/syncadapter" />
    </service>

使用属性android:process =“:sync”表示您创建了一个单独的同步过程。删除它,你很高兴。

答案 1 :(得分:1)

您可能希望将服务绑定到Application上下文。这样,如果您的应用程序上下文不存在,该服务将不存在,因为它在相同的进程(Application的进程)中运行。见bindSerivce()

如果您的服务是远程服务,请尝试使用callbacks

答案 2 :(得分:1)

你还有这个问题吗? 如果在清单文件中声明服务而未指定其他android:进程,那么它是否应该在您的任务定义的默认进程中运行? 在这种情况下你不能只使用getApplicationContext来获得你需要的东西吗? 我有以这种方式实现的同步适配器,它正在工作