Reputation: 2023
I have looked at multiple examples and implementations, I have no more ideas to check. I hope for outside perspective to see if I have missed something. Here is complete project on github for full source
It doesn't give me any errors or anything, it even shows that I have registered my request successfully. But I don't get any result in my BroadcastReceiver.
Manifest:
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:exported="true"
android:enabled="true"
android:name="com.example.myapplication.ActivityTransitionBroadcastReceiver"
android:permission="com.google.android.gms.permission.ACTIVITY_RECOGNITION">
<intent-filter>
<action android:name="com.example.myapplication.ACTION_PROCESS_ACTIVITY_TRANSITIONS"/>
</intent-filter>
</receiver>
</application>
Main Activity:
List<ActivityTransition> transitions = new ArrayList<>();
transitions.add(
new ActivityTransition.Builder()
.setActivityType(DetectedActivity.STILL)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
.build());
transitions.add(
new ActivityTransition.Builder()
.setActivityType(DetectedActivity.STILL)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
.build());
transitions.add(
new ActivityTransition.Builder()
.setActivityType(DetectedActivity.IN_VEHICLE)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
.build());
transitions.add(
new ActivityTransition.Builder()
.setActivityType(DetectedActivity.IN_VEHICLE)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
.build());
ActivityTransitionRequest request = new ActivityTransitionRequest(transitions);
Intent intent = new Intent(this.getApplicationContext(), ActivityTransitionBroadcastReceiver.class);
intent.setAction(ActivityTransitionBroadcastReceiver.INTENT_ACTION);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this.getApplicationContext(), 0, intent,
PendingIntent.FLAG_CANCEL_CURRENT);
Task<Void> task = ActivityRecognition.getClient(this.getApplicationContext())
.requestActivityTransitionUpdates(request, pendingIntent);
task.addOnSuccessListener(aVoid -> Log.i(TAG, "\n\nTransitions API was successfully registered.\n\n"))
.addOnFailureListener(e -> Log.e(TAG, "Transitions API could not be registered: " + e));
Upvotes: 0
Views: 1960
Reputation: 5109
Make sure you have added these lines in your Manifest:
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION"/>
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
<receiver
android:name="com.example.myapplication.activity.ActivityBroadcastReceiver"
android:permission="com.google.android.gms.permission.ACTIVITY_RECOGNITION">
<intent-filter>
<action android:name="com.example.myapplication.ACTION_PROCESS_ACTIVITY_TRANSITIONS"/>
</intent-filter>
</receiver>
Upvotes: 0
Reputation: 134
First of all if you using compileSdkVersion 29 you need to request permission "Manifest.permission.ACTIVITY_RECOGNITION", so your MainActivity wiil be like this:
package com.example.myapplication;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import com.google.android.gms.location.ActivityRecognition;
import com.google.android.gms.location.ActivityTransition;
import com.google.android.gms.location.ActivityTransitionRequest;
import com.google.android.gms.location.DetectedActivity;
import com.google.android.gms.tasks.Task;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "TransitionTest";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public void onResume(){
super.onResume();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
checkIfAlreadyHavePermission();
}else{
requestForUpdates();
}
}
private void checkIfAlreadyHavePermission() {
int result = ContextCompat.checkSelfPermission(this, Manifest.permission.ACTIVITY_RECOGNITION);
if (result == PackageManager.PERMISSION_GRANTED) {
requestForUpdates();
} else {
requestPermissions();
}
}
private void requestPermissions(){
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.ACTIVITY_RECOGNITION},
1);
}
@Override
public void onRequestPermissionsResult(int requestCode,
@NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == 1) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
requestForUpdates();
} else {
Toast.makeText(MainActivity.this, "Recognition permission denied", Toast.LENGTH_SHORT).show();
}
}
}
private void requestForUpdates(){
List<ActivityTransition> transitions = new ArrayList<>();
transitions.add(
new ActivityTransition.Builder()
.setActivityType(DetectedActivity.STILL)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
.build());
transitions.add(
new ActivityTransition.Builder()
.setActivityType(DetectedActivity.STILL)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
.build());
transitions.add(
new ActivityTransition.Builder()
.setActivityType(DetectedActivity.IN_VEHICLE)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
.build());
transitions.add(
new ActivityTransition.Builder()
.setActivityType(DetectedActivity.IN_VEHICLE)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
.build());
transitions.add(
new ActivityTransition.Builder()
.setActivityType(DetectedActivity.WALKING)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
.build());
transitions.add(
new ActivityTransition.Builder()
.setActivityType(DetectedActivity.ON_FOOT)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
.build());
ActivityTransitionRequest request = new ActivityTransitionRequest(transitions);
Intent intent = new Intent(getApplicationContext(), ActivityTransitionBroadcastReceiver.class);
intent.setAction(ActivityTransitionBroadcastReceiver.INTENT_ACTION);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, intent,
PendingIntent.FLAG_CANCEL_CURRENT);
Task<Void> task = ActivityRecognition.getClient(getApplicationContext())
.requestActivityTransitionUpdates(request, pendingIntent);
task.addOnSuccessListener(aVoid -> Log.i(TAG, "\n\nTransitions API was successfully registered.\n\n"))
.addOnFailureListener(e -> Log.e(TAG, "Transitions API could not be registered: " + e));
}
}
in Manifest also try to add
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION"/>
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
<receiver
android:name="com.example.myapplication.ActivityBroadcastReceiver"
android:permission="com.google.android.gms.permission.ACTIVITY_RECOGNITION">
<intent-filter>
<action android:name="com.example.myapplication.ACTION_PROCESS_ACTIVITY_TRANSITIONS"/>
</intent-filter>
</receiver>
And for convenience create NotificationHelper class:
class NotificationHelper {
static void sendNotification(Context context, String textContent) {
Intent notificationIntent;
PendingIntent pendingIntent;
notificationIntent = new Intent(context, MainActivity.class);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NO_HISTORY);
pendingIntent = PendingIntent.getActivity(context, new Random().nextInt(100) + 1,
notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context,"notif_ch_myapplication")
.setContentTitle(context.getResources().getString(R.string.app_name))
.setContentText(textContent)
.setChannelId("notif_ch_myapplication")
.setSmallIcon(R.mipmap.ic_launcher)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE)
.setContentIntent(pendingIntent);
if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
mBuilder.setSmallIcon(R.mipmap.ic_launcher);
mBuilder.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_launcher_background));
} else {
mBuilder.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_launcher_background));
mBuilder.setSmallIcon(R.mipmap.ic_launcher);
}
android.app.NotificationManager notificationManager = (android.app.NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel("notif_ch_myapplication",
context.getResources().getString(R.string.app_name),
android.app.NotificationManager.IMPORTANCE_DEFAULT);
if (notificationManager != null) {
notificationManager.createNotificationChannel(channel);
}
}
if (notificationManager != null) {
notificationManager.notify(new Random().nextInt(100) + 1, mBuilder.build());
}
}
}
and use it in ActivityTransitionBroadcastReceiver:
public class ActivityTransitionBroadcastReceiver extends BroadcastReceiver {
public static final String INTENT_ACTION = "com.example.myapplication.ACTION_PROCESS_ACTIVITY_TRANSITIONS";
@Override
public void onReceive(Context context, Intent intent) {
if (ActivityTransitionResult.hasResult(intent)) {
ActivityTransitionResult result = ActivityTransitionResult.extractResult(intent);
for (ActivityTransitionEvent event : Objects.requireNonNull(result).getTransitionEvents()) {
NotificationHelper.sendNotification(context, "Activity type:" + event.getActivityType()
+ " Transition type: " + event.getTransitionType());
}
}
}
}
In such way you will be able to check in without android studio.
And one more important thing: when you will install application - go outside for at least 10 minutes or you can shake the phone at least a minute. In my case I have received new activity transition event only in ~5-7 minutes.
Upvotes: 3
Reputation: 16699
Have you tried to register BroadcastReceiver in the Activity's onCreate
or `onStart' method
class CustomBroadcast extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//do some stuff here
Log.d("Broadcast", "Success");
}
}
CustomBroadcast broadcast = new CustomBroadcast();
LocalBroadcastManager.getInstance(this).registerReceiver(broadcast,
new IntentFilter("com.example.myapplication.ACTION_PROCESS_ACTIVITY_TRANSITIONS"));
Then in onStop
unsubscribe:
LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcast);
I do it like that since after 26 it is quite problematic to use manifest declared ones.
Hope it helps.
Upvotes: 0
Reputation: 134
1) It can be caused by "apps that target the API level 26 or higher can no longer register broadcast receivers for implicit broadcasts in their manifest.". Please try to use IntentService but not BroadcastReceiver.
In manifest:
<service
android:name=".DetectedActivitiesIntentService"
android:exported="false" />
Service class:
public class DetectedActivityIntentService extends IntentService {
protected static final String LOG_TAG = DetectedActivityIntentService.class.getSimpleName();
public DetectedActivityIntentService() {
super(LOG_TAG);
}
@Override
protected void onHandleIntent(Intent intent) {
if (ActivityTransitionResult.hasResult(intent)) {
ActivityTransitionResult result = ActivityTransitionResult.extractResult(intent);
}
}
}
Pending intent:
private PendingIntent getActivityDetectionPendingIntent() {
Intent intent = new Intent(App.getInstance().getApplicationContext(), DetectedActivityIntentService.class);
return PendingIntent.getService(App.getInstance().getApplicationContext(), 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
And starting listen method:
public void startListenMoveUpdates(List<ActivityTransition> transitions) {
ActivityTransitionRequest request = new ActivityTransitionRequest(transitions);
Task<Void> task = mActivityRecognitionClient.requestActivityTransitionUpdates(request, getActivityDetectionPendingIntent());
task.addOnSuccessListener(
result -> LogManager.saveMsg("Start listen move actions")
);
task.addOnFailureListener(
e -> {
e.printStackTrace();
LogManager.saveMsg("Start listen move actions error");
}
);
}
2) I would also recommend avoiding testing in buildings where the gps signal strength is poor.
Upvotes: 0