Android : Not able to sync data between applications above Oreo + devices

删除回忆录丶 提交于 2020-01-01 19:22:37

问题


I am stuck on sync real time data between 2 app only in Oreo+ devices, Like if different user login to the app then it should be immediately effect in other app and It should also change in other app.(e.g. Facebook and Facebook Messenger. If you logout from Facebook, it will automatically logout from FB Messenger or If you log into Facebook then it will automatically logged into FB Messenger and vice versa) I created broadcast receiver in both app and if login changes from one app then send broadcast to other app where it will do rest of work.

I have googled on it and I found some ways.

I have read this document

https://developer.android.com/about/versions/oreo/background

  • We have published differently signed APKs so not able to provide same signature permission in receiver.

Already went through this links

Broadcast receiver not working in oreo

Oreo: Broadcast receiver Not working

Broadcast receiver registered in manifest not getting called in Android Oreo

Receiver stopped receiving in Oreo

Thought to implement this ways but..

1) Create foreground service and register receiver into it. - As this way, I need one notification which is required to run foreground service. and I can't do that.I can't show unnecessary notification.

2) Scheduled job: - I can't use it as I need to run service all time in background.

What I have tried so far:

1) Register receiver in Application class : This is not working after application is killed because context has been killed.

2) Registering receiver in FireBase Notification service, but it's only initialize when notification arrives.

Code:

Registering receiver in Application class

ASampleActionReceiver mASampleActionReceiver = new ASampleActionReceiver();
IntentFilter filterAction = new IntentFilter();
filterAction.addAction("com.sample.example.receiver.operation");
registerReceiver(mASampleActionReceiver, filterAction);

In Manifest

<receiver android:name=".receiver.ASampleActionReceiver">
        <intent-filter>
            <action android:name="com.sample.example.receiver.operation" />
        </intent-filter>
</receiver>

Intent service will start by receiver

<service
android:name="com.sample.example.services.SampleOperationService"
android:enabled="true"
android:exported="false" />

And a Receiver ASampleActionReceiver.java

    public class ASampleActionReceiver extends BroadcastReceiver {

    Context mContext;

    @Override
    public void onReceive(Context context, Intent intent) {
        mContext = context;
        AdoddleLog.d("LOG", intent.getExtras().getString("loginData"));

        Intent mIntent = new Intent(mContext, SampleOperationService.class);
        mIntent.putExtras(intent);
        mContext.startService(mIntent);
    }
}

can some one please suggest better solution?

Can I use AIDL for app communication ? does it work if any one application is idle or not running in background ?


回答1:


Finally, I found solution and I would like to post detailed answer.

I used AIDL for sharing data between 2 Apps

In Both app, Create AIDL file in same package name like com.common.app and create one aidl file in it.

// IRemoteService.aidl
package com.common.app;

// Declare any non-default types here with import statements

interface IRemoteService {
    void onReceive(String data);
}

In both app, Need to create intent-service SampleOperationService.java , it will do rest of work after data receiving from another app. you can use JobIntentService instead.

public class SampleOperationService extends IntentService{

    private String DEBUG_LOG = "SampleOperationService";

    /**
     * Creates an IntentService.  Invoked by your subclass's constructor.
     */
    public SampleOperationService() {
        super("SampleOperationService Service");
    }

    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        //here you will get data in intent extra, in "data" key, Which is send from another app. You can do rest of work here
    }
}

In Both App, create services not require to add in same package like aidl. It contain one service binder, which extend AIDL Stub. here you will get data from the other application.

public class RemoteService extends Service {
    @Override
    public IBinder onBind(Intent intent) {
        return (new RemoteServiceBinder());
    }

    private class RemoteServiceBinder extends IRemoteService.Stub {
        @Override
        public void onReceive(String data) {
            Intent mIntent = new Intent(RemoteService.this, SampleOperationService.class);
            mIntent.putExtra("data", data); // you will get data from the second app
            startService(mIntent);
        }
    }
}

Manifest.xml

For first app

<service
    android:name="com.firstapp.app.service.SampleOperationService"
    android:enabled="true"
    android:exported="false" />

<service android:name="com.firstapp.app.RemoteService"> // this is service 
    <intent-filter>
         <action android:name="com.common.app.IRemoteService" />// this is the path of aidl file
     </intent-filter>
</service>

For second app

<service
    android:name="com.secondapp.app.service.SampleOperationService"
    android:enabled="true"
    android:exported="false" />

<service android:name="com.secondapp.app.RemoteService">
    <intent-filter>
         <action android:name="com.common.app.IRemoteService" />// this is the path of aidl file which will on same place for both app
     </intent-filter>
</service>

Data Passing:

In Both app, We need to bind remote service.

In case of Activity, bind service in onCreate

public class SampleActivity extends AppCompatActivity implements ServiceConnection {

    private IRemoteService bindingRemoteService;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        bindRemoteService();
    }
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        bindingRemoteService = IRemoteService.Stub.asInterface(service);
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        bindingRemoteService = null;
    }

    private void bindRemoteService() {
        Intent implicit = new Intent(IRemoteService.class.getName());
        List<ResolveInfo> matches = getPackageManager()
                .queryIntentServices(implicit, 0);
        for (ResolveInfo mResolveInfo : matches) {

            if (mResolveInfo.serviceInfo.packageName.equalsIgnoreCase("com.secondapp.app")) {// for second app it will be "com.firstapp.app"
                Intent explicit = new Intent(implicit);
                ServiceInfo svcInfo = mResolveInfo.serviceInfo;
                ComponentName cn = new ComponentName(svcInfo.applicationInfo.packageName,
                        svcInfo.name);
                explicit.setComponent(cn);
                getApplicationContext().bindService(explicit, this, Context.BIND_AUTO_CREATE);
                break;
            }
        }
    }

}

Here just bind other app service. so it won't receive data in same app. and bind service to specific package for security purpose

To send data to other app

public void sendDataToOtherApp(){
    if (bindingRemoteService != null) {
        try {
            HashMap map = new HashMap();
            map.put("data", data);// data will be string
            bindingRemoteService.onReceive(new Gson().toJson(map));
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

And data will receive in RemoteService of the other application.



来源:https://stackoverflow.com/questions/53370019/android-not-able-to-sync-data-between-applications-above-oreo-devices

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!