简体   繁体   中英

My onReceive method get called multiple and trigger onCreate from my MainActivity (Wear)

I am fairly new to android. I am trying to send data from my tablet to my phone using a WearableListenerService. This part works well, I can see through logs that the data is sent. The problem is that I receive the data from the tablet in the Listener class and I have to transmit it to Mainactivity in order to update my Views. To do this I use a LocalBroadcaster and I implemented the onReceive method in my MainActivity. So when I give the order to send the data from the phone the onReceive gets called multiple time most of the time between 2 or 3 times and furthermore the activity is recreated because onCreate is triggered by this method (I don't know if this behavior is expected).

Here is the code:

DataLayerListenerService.java (Listener)

public class DataLayerListenerService extends WearableListenerService {

// Tag for Logcat
private static final String TAG = "DataLayerService";
private int notificationId = 001;
private String notif;

// Member for the Wear API handle
GoogleApiClient mGoogleApiClient;

@Override
public void onCreate() {
    super.onCreate();

    // Start the Wear API connection
    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addApi(Wearable.API)
            .build();
    mGoogleApiClient.connect();
}

//@Override
public void onDataChanged(DataEventBuffer dataEvents) {
    Log.v(TAG, "onDataChanged: " + dataEvents);
    for (DataEvent event : dataEvents) {
        if (event.getType() == DataEvent.TYPE_CHANGED) {

            Log.e(TAG, "DataItem Changed: " + event.getDataItem().toString() + "\n"
                    + DataMapItem.fromDataItem(event.getDataItem()).getDataMap());

            String path = event.getDataItem().getUri().getPath();

            switch (path) {
                case DataLayerCommons.NOTIFICATION_PATH:
                    Log.v(TAG, "Data Changed for NOTIF_PATH: " + event.getDataItem().toString());
                    DataMapItem dataMapItem = DataMapItem.fromDataItem(event.getDataItem());
                    notif = dataMapItem.getDataMap().getString(DataLayerCommons.NOTIFICATION_KEY);
                    Intent intent = new Intent(NOTIFICATION_RECEIVED);
                    intent.putExtra(NOTIFICATION_RECEIVED, notif);
                    LocalBroadcastManager.getInstance(this).sendBroadcast(intent);

                    break;
                case DataLayerCommons.COUNT_PATH:
                    Log.v(TAG, "Data Changed for COUNT_PATH: " + event.getDataItem() + "\n"
                            + "Count data = " + DataMapItem.fromDataItem(event.getDataItem())
                            .getDataMap().getInt(DataLayerCommons.COUNT_KEY));
                    break;
                default:
                    Log.v(TAG, "Data Changed for unrecognized path: " + path);
                    break;
            }
        } else if (event.getType() == DataEvent.TYPE_DELETED) {
            Log.v(TAG, "DataItem Deleted: " + event.getDataItem().toString());
        }

        }
    }
}

Main Activity

public class MainActivity extends Activity {

private static final String TAG = "MainActivity";
public static final String NOTIFICATION_RECEIVED = "NOTIFICATION_RECEIVED";
private String notif="";

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Log.e(TAG,"OnCreate");
    setContentView(R.layout.main_activity);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
            new IntentFilter(NOTIFICATION_RECEIVED));

}

private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {

        Log.e(TAG, "Got message!");
        notif = intent.getStringExtra(NOTIFICATION_RECEIVED);
        TextView warnView = findViewById(R.id.warningView);
        warnView.setText(notif);

    }
};

}

AndroidManifest.xml

<uses-feature android:name="android.hardware.type.watch" />
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-permission android:name="android.permission.VIBRATE"/>

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/Theme.AppCompat">


    <meta-data
        android:name="com.google.android.wearable.standalone"
        android:value="false" />

    <meta-data
    android:name="com.google.android.gms.version"
    android:value="@integer/google_play_services_version" />

    <service android:name=".DataLayerListenerService">
        <intent-filter>
            <action android:name="com.google.android.gms.wearable.DATA_CHANGED" />

            <data
                android:host="*"
                android:pathPrefix="/notification"
                android:scheme="wear" />
        </intent-filter>
        <intent-filter>
            <action android:name="com.google.android.gms.wearable.MESSAGE_RECEIVED" />
            <data
                android:host="*"
                android:pathPrefix="/start-activity"
                android:scheme="wear" />
        </intent-filter>
    </service>

    <activity
        android:name=".MainActivity"
        android:label="@string/app_name">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
        <intent-filter>
            <action android:name="com.example.android.wearable.datalayer.EXAMPLE" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>

</application>

Thanks for the help

I would suggest using Application class to store your Activity instead of BroadcastReceiver registering.

What I mean:

in Application class create a variable that stores your activity:

class MyApp extends Application {
public static MyActivity activity;
}

to link save into this variable current activity at onCreate and release while onDestroy .

Somehow:

public MyActivity extends Activity {
void onCreate() {
MyApp.activity = this;
}

void onDestroy() {
MyApp.activity = null;
}

void redraw() {
//redraw
}

}

inside the service do something like this:

class MyService extends WearableListenerService {

void onDataChanged() {
if (MyApp.activity != null) {
MyApp.activity.redraw()
}
}

}

do not forget to set application in the manifest:

<application
    android:name=".MyApp"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/Theme.AppCompat">

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM