Using setresult() to pass data to activity - android

I'm developing a program in Android Studio to connect to a specific BLE device. I'm using setresult() to return the BLE device name etc once the BLE device is discovered. Unfortunately, setresult() is giving an error:
Error:(201, 25) error: method setResult in class BroadcastReceiver cannot be applied to given types;
required: int,String,Bundle,found: int,Intent, reason: actual and formal argument lists differ in length
Why is there an error and how do I resolve it?
private final BroadcastReceiver bleServiceReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent sintent) {
final String action = sintent.getAction();
if (MldpBluetoothService.ACTION_BLE_SCAN_RESULT.equals(action)) { //Service has sent a scan result
Log.d(TAG, "Scan scan result received");
final BleDevice device = new BleDevice(sintent.getStringExtra(MldpBluetoothService.INTENT_EXTRA_SERVICE_ADDRESS), sintent.getStringExtra(MldpBluetoothService.INTENT_EXTRA_SERVICE_NAME)); //Create new item to hold name and address
if(device.getName() != null) {
if (device.getName().contains("Prodigy")) { //+++++ Added by Chris
bleDeviceListAdapter.addDevice(device); //+++++ if Prodigy add to the device to list adapter that displays a list on the screen
bleDeviceListAdapter.notifyDataSetChanged(); //+++++ Refresh the list on the screen
scanStopHandler.removeCallbacks(stopScan); //Stop the scan timeout handler from calling the runnable to stop the scan
scanStop();
final Intent intent = new Intent(); //Create Intent to return information to the MldpTerminalActivity that started this activity
intent.putExtra(INTENT_EXTRA_SCAN_AUTO_CONNECT, alwaysConnectCheckBox.isChecked()); //Add to the Intent whether to automatically connect next time
intent.putExtra(INTENT_EXTRA_SCAN_NAME, device.getName()); //Add BLE device name to the intent
intent.putExtra(INTENT_EXTRA_SCAN_ADDRESS, device.getAddress()); //Add BLE device address to the intent
setResult(Activity.RESULT_OK, intent); //Return an intent to the calling activity with the selected BLE name and address
finish();
}
}
}
}
};

As your code is placed in broadcastReceiver, you are using the setResult() for BroadcastReceiver.
If this broadcastReceiver is in your activity, please try
YourActivity.this.setResult();
If it is outside your activity, you may need to keep the activity reference in broadcastReceiver for calling
yourActivityReference.setResult();

Related

android api-26+ shortcut broadcast receiver not called

I'm trying to create a pinned shortcut on the desktop for an app. The CreateShortcut method is called from a button and presents the android create-shortcut dialog. When the caller selects ok, the broadcast receiver should get called and execute finish so the activity exits.
This is the first time I've used a broadcast receiver but it looks like it's pretty straight-forward. Just create a receiver, register it with an intent filter that has the same action as an intent and when the intent is sent it should cause the receiver to be called, right?
The shortcut is created just fine but the broadcast receiver never gets called. I'm not seeing any messages on logcat.
private void CreateShortcut(final Context c) {
if (ShortcutManagerCompat
.isRequestPinShortcutSupported(c)) {
Intent shortcutIntent = new Intent(
c, CreateAppHomeShortcut.class);
shortcutIntent.setAction(
Intent.ACTION_CREATE_SHORTCUT);
ShortcutInfoCompat shortcutInfo
= new ShortcutInfoCompat
.Builder(c, "shortcut")
.setShortLabel(c.getString(R.string.app_name))
.setIcon(IconCompat.createWithResource(
c, R.drawable.qmark)
)
.setIntent(shortcutIntent)
.build();
registerReceiver(new BroadcastReceiver() {
#Override
public void onReceive(
Context context, Intent intent) {
Log.d(TAG, "msg received");
unregisterReceiver(this);
finish();
}
}
, new IntentFilter(
Intent.ACTION_CREATE_SHORTCUT
)
);
PendingIntent successCallback =
PendingIntent.getBroadcast(
c, 99
, shortcutIntent, 0
);
ShortcutManagerCompat.requestPinShortcut(c,
shortcutInfo,
successCallback.getIntentSender()
);
}
}
I've been working on this several days and I'm stumped.
Thanks
I finally got the callback to my BroadcastReceiver. My main problem was that I was using the intents wrong. I thought that the brodcast receiver intent and the shortcut intent could be the same as long as the action was correct. Wrong! The shortcut intent must hava an action set but in the tests I did, it didn't seem to care what that action was. And the broadcast receiver was created as "Intent = new Intent(context, class); setAction(...); ", the shortcut would be created and function fine but the broadcast receiver was never invoked. The only way I could get the broadcast receiver to work was with an Intent just for it with nothing but the action set (or possibly extras) set. I couldn't get the program to work using the same intent to create the shortcut and invoke the broadcast receiver.
The other problem encountered was that the interface allows you to create multiple pinned shortcuts -- and would then call your broadcast receiver once for each shortcut created. I discovered you can query the interface for all pinned shortcuts and filter by id to find out if your shortcut already exists and use that info to avoid creating multiple identical pinned shortcuts on your home page.
The code below seems to work fine API26+ for creating a shortcut and the receiver gets called as long as the user accepts the shortcut. The docs state that they will only call your receiver on the user's acceptance. That of course makes detecting the end of the user's interaction rather difficult. Since the request gets buried in my actual app, the plan was to open this as part of a separate activity, but I don't have any way to detect that the user is done if he doesn't want the shortcut. If anyone has suggestions, I'd appreciate hearing them.
// Create a shortcut and exit the activity. If the shortcut
// already exists,just exit.
private void CreateShortcut(final Context c) {
if (Build.VERSION.SDK_INT >= 26) {
ShortcutManager sm =
getSystemService(ShortcutManager.class);
if (sm != null && sm.isRequestPinShortcutSupported()) {
final String shortcutId = "StartApp";
boolean shortcutExists = false;
// We create the shortcut multiple times if given the
// opportunity. If the shortcut exists, put up
// a toast message and exit.
List<ShortcutInfo> shortcuts
= sm.getPinnedShortcuts();
for (int i = 0;
i < shortcuts.size() && !shortcutExists; i++) {
shortcutExists
= shortcuts.get(i).getId().equals(shortcutId);
if (shortcutExists) {
Toast.makeText(c , String.format(
"Shortcut %s already exists."
, shortcutId
)
, Toast.LENGTH_LONG
).show();
finishActivity();
}
else {
// this is the intent that actually creates the
// shortcut.
Intent shortcutIntent
= new Intent(c, CreateAppHomeShortcut.class);
shortcutIntent.setAction(
Intent.ACTION_CREATE_SHORTCUT);
ShortcutInfo shortcutInfo = new ShortcutInfo
.Builder(c, shortcutId)
.setShortLabel(
c.getString(R.string.app_name))
.setIcon(createWithResource(c
, R.drawable.qmark))
.setIntent(shortcutIntent)
.build();
// this intent is used to wake up the broadcast
// receiver.
// I couldn't get createShortcutResultIntent to
// work but just a simple intent as used for a
// normal broadcast intent works fine.
Intent broadcastIntent
= new Intent(Intent.ACTION_CREATE_SHORTCUT);
// create an anonymous broadcaster. Unregister
// to prevent leaks when done.
registerReceiver(new BroadcastReceiver() {
#Override
public void onReceive(
Context c, Intent intent) {
unregisterReceiver(this);
Log.d(TAG, String.format(
"ShortcutReceiver activity = "
+ "\"$1%s\""
, intent.getAction()));
finishActivity();
}
}
, new IntentFilter(
Intent.ACTION_CREATE_SHORTCUT)
);
PendingIntent successCallback
= PendingIntent.getBroadcast(
c, 99
, broadcastIntent, 0);
// Shortcut gets created here.
sm.requestPinShortcut(shortcutInfo
, successCallback.getIntentSender());
}
}
}
}

Launch app from wear and get the message regardless the state of app

I'm dealing with wearable, and my purpose is the next:
From my watch, I want to press a simple button, which send a simple message to the mobile. But I would like to handle all those behaviors :
when mobile app isn't yet launched, then launch the app and pass the message from wear, which can be handled in the launcher activity
when mobile app is launched but in the background, then just bring it to foreground and handle message from wear, which can be handled in the launcher activity
when mobile app is launched and in foreground, juste handle the message in the launcher activity
So far, I handle to launch the app when it isn't not yet launched, but I can't get the extra message in the launcher activity contained in the intent. Here the code.
the mobile service
public class MobileWearService extends WearableListenerService {
private static final String START_ACTIVITY = "/start_activity";
#Override
public void onMessageReceived(MessageEvent messageEvent) {
super.onMessageReceived(messageEvent);
String event = messageEvent.getPath();
String msg = new String(messageEvent.getData());
if (event.equals(START_ACTIVITY)) {
Intent intent = new Intent( this, MainActivity.class );
intent.putExtra("Data", msg);
intent.setFlags( Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity( intent );
}
}
}
However, if I use a broadcast to send the message from service to the main activity, it works only if the app is launched and foreground
public class MobileWearService extends WearableListenerService {
private static final String START_ACTIVITY = "/start_activity";
#Override
public void onMessageReceived(MessageEvent messageEvent) {
super.onMessageReceived(messageEvent);
String event = messageEvent.getPath();
String msg = new String(messageEvent.getData());
if (event.equals(START_ACTIVITY)) {
broadcastIntent.setAction("com.me.project.wear.to.app");
broadcastIntent.putExtra("Data", msg);
broadcastIntent.putExtras(intent);
sendBroadcast(broadcastIntent);
}
}
}
launcher activity
private IntentFilter mIntentFilter = new IntentFilter("com.me.project.wear.to.app");
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent != null && intent.getAction().equals("com.me.project.wear.to.app")) {
String msg = intent.getStringExtra("Data");
}
}
};
#Override
protected void onResume() {
super.onResume();
registerReceiver(mReceiver, mIntentFilter);
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(mReceiver);
}
So I would to combine the fact to get the message from wear (I know how to) but pass this message to get it in the launcher activity regardless of the state of the app.
Just make the static BroadcastReceiver
public class WatchMessageReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
if (intent != null &&
intent.getAction().equals("com.me.project.wear.to.app")) {
String msg = intent.getStringExtra("Data");
Intent launcherIntent = new Intent(context, LauncherActivity.class);
launcherIntent.putExtra("Data",msg);
startActivity(launcherIntent);
}
}
}
in your manifest file
<receiver android:name ="WatchMessageReceiver"
<intent-filter>
<action android:name="com.me.project.wear.to.app"/>
</intent-filter>
</receiver>
In the Sending and Syncing Data training, there is a Handling Data Layer Events:
When you make a call to the Data Layer API, you can receive the status of the call when it completes. You also can listen for data events, resulting from data changes that your application makes anywhere on the Android Wear network.
Listen for Data Layer Events
Because the data layer synchronizes and sends data across the handheld and wearable, it is usually necessary to listen for important events. Examples of such events include creation of data items and receipt of messages.
To listen for data layer events, you have two options:
Create a service that extends WearableListenerService.
Create an activity that implements DataApi.DataListener.
With both these options, you override the data event callback methods for the events you are interested in handling.
Some of the events you can listen for using WearableListenerService are as follows:
onDataChanged(): Whenever a data item object is created, deleted, or changed, the system triggers this callback on all connected nodes.
onMessageReceived(): A message sent from a node triggers this callback on the target node.
onCapabilityChanged(): When a capability that an instance of your app advertises becomes available on the network, that event triggers this callback. If you're looking for a nearby node you can query the isNearby() method of the nodes provided in the callback.
According to the related SO post:
WearableListenerService does not run constantly - it is only started when a new message/node connection/data layer change is sent and stopped when there are no more messages.
Hope this helps.

Is it a good idea to create an empty service in android?

I want to create an empty service that will just run in the background once a certain fragment is open - the service will fill an array in the background but is not used in the current (calling fragment):
Code to create the service:
Intent intent = new Intent();
intent.putExtra(ServiceActions.class.getName(), ServiceActions.GET_LIST_FROM_API);
intent.putExtra("api_code_id", "12345");
managerProvider.getRequestManager().startRetrievalService(intent);
Register & Unregister listener:
manager.registerReceiver(backgroundListReceiver , new IntentFilter(ServiceBroadcasts.GET_LIST_FROM_API_RESULT.name()));
manager.unregisterReceiver(backgroundListReceiver );
Then handle the receiver:
backgroundListReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
boolean result = extras.getBoolean(ServiceBroadcasts.GET_LIST_FROM_API_RESULT.name());
// DO Nothing here as the list is loading in the background
// and stored in the application class
}
};
I do register and unregister it in fragment, I guess I asking is this correct way to do it or is there another better process? The reason for doing it here is that the chance of the user selecting the list is quite high so I'm trying to preload the list prior to them selecting it.
Code to handle loading list in background:
private void getListInBackground() {
RequestResponse response = RestAPI.getListInBackground();
if (response.isSuccessful()) {
mApp.setBackgroundList(JacksonMapper.deserBackgroundList(response.getResponseString()));
}
Intent broadcast = new Intent(ServiceBroadcasts.GET_LIST_FROM_API_RESULT.name());
broadcast.putExtra(ServiceBroadcasts.GET_LIST_FROM_API_RESULT.name(), response.isSuccessful());
mManager.sendBroadcast(broadcast);
}

Starting an ActivityRecognitionService from within another active Service

I am having an issue getting my ActivityRecognition Service to remain running. I currently have a service (GService) that runs continuously in the background. I want to start the ActivityRecognition service within GService, and have the ActivityRecognition service broadcast the activity result back to GService. I am able to start the service and receive feedback that it is running, and I also get one result from the intent handler (no actual data), but never again.
Here is the section of code from my continuous service setting up the intent, pending intent:
#Override
public void onConnected(Bundle bundle) {
Log.d(TAG, "onConnected - isConnected ...............: " + mGoogleApiClient.isConnected());
startLocationUpdates();
//start process to receive activity updates
Intent intent = new Intent(this, DetectedActivitiesIntentService.class);
PendingIntent mActivityRecognitionPendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
ActivityRecognition.ActivityRecognitionApi.requestActivityUpdates(mGoogleApiClient, ActivityConstants.DETECTION_INTERVAL_MILLISECONDS_MOVING,
mActivityRecognitionPendingIntent).setResultCallback(this);
startService(intent); // this should start the DetectedActivitiesIntentService
This is the Broadcast receiver within GService:
public class ActivityDetectionBroadcastReceiver extends BroadcastReceiver {
protected static final String TAG_AR = "ADRR";
#Override
public void onReceive(Context context, Intent intent){
//ArrayList<DetectedActivity> updatedActivities =
// intent.getParcelableArrayListExtra(ActivityConstants.ACTIVITY_EXTRA);
//updateDetectedActivitiesList(updatedActivities);
String action = intent.getAction();
if(action.equals("com.gt.useractivity"))
{
Log.d(TAG_AR, "received broadcast from Activity service");
// below line should grab the resulting string activity from the intent and log it.
Log.d(TAG_AR, "activity is : " + intent.getExtras().getString(ActivityConstants.ACTIVITY_EXTRA));
}
}
}
Here is the ActivityRecognition Service code:
public class DetectedActivitiesIntentService extends IntentService {
protected static final String TAG = "ADIS";
/**
* This constructor is required, and calls the super IntentService(String)
* constructor with the name for a worker thread.
*/
public DetectedActivitiesIntentService() {
// Use the TAG to name the worker thread.
super(TAG);
Log.d(TAG, "Activity service started....");
}
#Override
public void onCreate() {
super.onCreate();
}
/**
* Handles incoming intents.
* #param intent The Intent is provided (inside a PendingIntent) when requestActivityUpdates()
* is called.
*/
#Override
protected void onHandleIntent(Intent intent) {
if(ActivityRecognitionResult.hasResult(intent))
{
ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent);
Intent localIntent = new Intent(ActivityConstants.BROADCAST_ACTION);
// Get the list of the probable activities associated with the current state of the
// device. Each activity is associated with a confidence level, which is an int between
// 0 and 100.
ArrayList<DetectedActivity> detectedActivities = (ArrayList) result.getProbableActivities();
// Log each activity.
Log.i(TAG, "activities detected");
for (DetectedActivity da: detectedActivities) {
Log.i(TAG, ActivityConstants.getActivityString(da.getType()) + " " + da.getConfidence() + "%");
}
String activity = result.getMostProbableActivity().toString(); // get the activity and convert to string
// Broadcast the list of detected activities.
//localIntent.putExtra(ActivityConstants.ACTIVITY_EXTRA, detectedActivities);
//localIntent.setAction("com.gt.useractivity");
localIntent.putExtra(ActivityConstants.ACTIVITY_EXTRA, activity); // set the activity string to be transmitted
LocalBroadcastManager.getInstance(this).sendBroadcast(localIntent);
}
else{
Log.d(TAG, "Intent had no activity data....");
}
}
}
This Activity recognition sample is based from the Google Github sample.
All the examples I have found when using the PendingIntent is being called from a main activity, not from a service. I'm obviously doing something incorrect, but I can't figure it out. Any advice would be appreciated. I should also note that I have 2 broadcast receivers within my GService. I don't know if this would cause an issue or not.
It looks like I have solved the problem. I have a second intent within my GService used for broadcasting. From what I can tell from this thread (Pending intent works correctly for first notification but not for the rest) if there are multiple intents being used, they have to be unique. Thus, I added one line of code when declaring my intent intent.setAction(Long.toString(System.currentTimeMillis())); which is enough to differentiate it from the other intent to the system. Once I did that, I began to receive the Activity broadcasts from the intent service, as well as still receiving the location requests from within the GService routine.

android Broadcastreceiver issue

Im developing an application,which blocks all outgoing calls and then after blocking that call ,another new call is initiated to a predefined number...
My problem is that,when i block the call using a broadcastreceiver,the second call which i programmatically initiate is also getting blocked...
Is any method to unregister the broadcast after blocking the first call,or any other method or technique???
This is my broadcastreceiver which i implemented for my app...
public class CallListenerActivity extends BroadcastReceiver {
Uri uri;
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if(bundle == null)
return;
String phonenumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Log.i("###OutgoingCallReceiver",phonenumber);
Log.i("###OutgoingCallReceiver",bundle.toString());
String info = "Detect Calls sample application\nOutgoing number: " + phonenumber;
Toast.makeText(context, info, Toast.LENGTH_LONG).show();
String phoneNumber = "5556";
Uri uri = Uri.fromParts("tel", phoneNumber, null);
Intent callIntent = new Intent(Intent.ACTION_CALL, uri);
callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(callIntent);
}
You could try starting your original (CallListenerActivity? The one which registered the broadcast receiver) activity again using a flag stored as extra in the intent.
Evaluate the intent in your activity and unregister the broadcast receiver if you see the flag in the extras. Then start the the call activity as shown in your example code.
You can use store a check when you are initiating a call and after the completion of the call mark it. For this this check you can use SharedPreference.

Categories

Resources