Geofencing Intent Not Firing - android

Hello everyone i am implementing geofencing feature in my android application to send toast notifications.The thing is when i am inside(where i am making fences) a fence that i have created then the intent is fired but when i try to fire the event again by reentering the location intent is not firing here is my code
protected override void OnHandleIntent (Intent intent)
{
Intent broadcastIntent = new Intent();
var geofencingEvent = GeofencingEvent.FromIntent (intent);
if (geofencingEvent.HasError) {
var errorMessage = GeofenceErrorMessages.GetErrorString (this, geofencingEvent.ErrorCode);
Log.Error (TAG, errorMessage);
return;
}
int geofenceTransition = geofencingEvent.GeofenceTransition;
if (geofenceTransition == Geofence.GeofenceTransitionEnter ||
geofenceTransition == Geofence.GeofenceTransitionExit) {
Toast.MakeText(this, "Service Started", ToastLength.Long).Show();
IList<IGeofence> triggeringGeofences = geofencingEvent.TriggeringGeofences;
string geofenceTransitionDetails = GetGeofenceTransitionDetails (this, geofenceTransition, triggeringGeofences);
SendNotification (geofenceTransitionDetails);
Log.Info (TAG, geofenceTransitionDetails);
} else {
// Log the error.
Log.Error (TAG, GetString (Resource.String.geofence_transition_invalid_type, new [] { new Java.Lang.Integer (geofenceTransition) }));
}
}
string GetGeofenceTransitionDetails (Context context, int geofenceTransition, IList<IGeofence> triggeringGeofences)
{
string geofenceTransitionString = GetTransitionString (geofenceTransition);
var triggeringGeofencesIdsList = new List<string> ();
foreach (IGeofence geofence in triggeringGeofences) {
triggeringGeofencesIdsList.Add (geofence.RequestId);
}
var triggeringGeofencesIdsString = string.Join (", ", triggeringGeofencesIdsList);
return geofenceTransitionString + ": " + triggeringGeofencesIdsString;
}
void SendNotification (string notificationDetails)
{
var notificationIntent = new Intent (ApplicationContext, typeof(MainActivity));
var stackBuilder = Android.Support.V4.App.TaskStackBuilder.Create (this);
stackBuilder.AddParentStack (Java.Lang.Class.FromType (typeof(MainActivity)));
stackBuilder.AddNextIntent (notificationIntent);
var notificationPendingIntent = stackBuilder.GetPendingIntent (0, (int)PendingIntentFlags.UpdateCurrent);
var builder = new NotificationCompat.Builder (this);
builder.SetSmallIcon (Resource.Drawable.icon)
.SetLargeIcon (BitmapFactory.DecodeResource (Resources, Resource.Drawable.icon))
.SetColor (Color.Red)
.SetContentTitle (notificationDetails)
.SetContentText (GetString (Resource.String.geofence_transition_notification_text))
.SetContentIntent (notificationPendingIntent);
builder.SetAutoCancel (true);
var mNotificationManager = (NotificationManager)GetSystemService (Context.NotificationService);
mNotificationManager.Notify (0, builder.Build ());
}
string GetTransitionString (int transitionType)
{
switch (transitionType) {
case Geofence.GeofenceTransitionEnter:
return GetString (Resource.String.geofence_transition_entered);
case Geofence.GeofenceTransitionExit:
return GetString (Resource.String.geofence_transition_exited);
default:
return GetString (Resource.String.unknown_geofence_transition);
}
}
and my main activity is
{
protected const string TAG = "creating-and-monitoring-geofences";
protected GoogleApiClient mGoogleApiClient;
protected IList<IGeofence> mGeofenceList;
bool mGeofencesAdded;
PendingIntent mGeofencePendingIntent;
ISharedPreferences mSharedPreferences;
Button mAddGeofencesButton;
Button mRemoveGeofencesButton;
protected override void OnCreate (Bundle savedInstanceState)
{
base.OnCreate (savedInstanceState);
SetContentView (Resource.Layout.main_activity);
mAddGeofencesButton = FindViewById<Button> (Resource.Id.add_geofences_button);
mRemoveGeofencesButton = FindViewById<Button> (Resource.Id.remove_geofences_button);
mAddGeofencesButton.Click += AddGeofencesButtonHandler;
mRemoveGeofencesButton.Click += RemoveGeofencesButtonHandler;
mGeofenceList = new List<IGeofence> ();
mGeofencePendingIntent = null;
mSharedPreferences = GetSharedPreferences (Constants.SHARED_PREFERENCES_NAME,
FileCreationMode.Private);
mGeofencesAdded = mSharedPreferences.GetBoolean (Constants.GEOFENCES_ADDED_KEY, false);
SetButtonsEnabledState ();
PopulateGeofenceList ();
BuildGoogleApiClient ();
}
protected void BuildGoogleApiClient ()
{
mGoogleApiClient = new GoogleApiClient.Builder (this)
.AddConnectionCallbacks (this)
.AddOnConnectionFailedListener (this)
.AddApi (LocationServices.API)
.Build ();
}
private IntentFilter mIntentFilter;
protected override void OnResume ()
{
base.OnResume();
mGoogleApiClient.Connect ();
}
protected override void OnStart()
{
base.OnStart();
mGoogleApiClient.Connect();
}
protected override void OnStop ()
{
base.OnStop ();
// mGoogleApiClient.Disconnect ();
}
public void OnConnected (Bundle connectionHint)
{
Log.Info (TAG, "Connected to GoogleApiClient");
}
public void OnConnectionSuspended (int cause)
{
Log.Info (TAG, "Connection suspended");
}
public void OnConnectionFailed (Android.Gms.Common.ConnectionResult result)
{
Log.Info (TAG, "Connection failed: ConnectionResult.getErrorCode() = " + result.ErrorCode);
}
GeofencingRequest GetGeofencingRequest ()
{
var builder = new GeofencingRequest.Builder ();
builder.SetInitialTrigger (GeofencingRequest.InitialTriggerEnter);
builder.AddGeofences (mGeofenceList);
return builder.Build ();
}
public async void AddGeofencesButtonHandler (object sender, EventArgs e)
{
if (!mGoogleApiClient.IsConnected) {
Toast.MakeText (this, GetString (Resource.String.not_connected), ToastLength.Short).Show ();
return;
}
try {
var status = await LocationServices.GeofencingApi.AddGeofencesAsync (mGoogleApiClient, GetGeofencingRequest (),
GetGeofencePendingIntent ());
HandleResult (status);
} catch (SecurityException securityException) {
LogSecurityException(securityException);
}
}
public async void RemoveGeofencesButtonHandler (object sender, EventArgs e)
{
if (!mGoogleApiClient.IsConnected) {
Toast.MakeText (this, GetString(Resource.String.not_connected), ToastLength.Short).Show ();
return;
}
try {
var status = await LocationServices.GeofencingApi.RemoveGeofencesAsync (mGoogleApiClient,
GetGeofencePendingIntent ());
HandleResult (status);
} catch (SecurityException securityException) {
LogSecurityException (securityException);
}
}
void LogSecurityException (SecurityException securityException)
{
Log.Error (TAG, "Invalid location permission. " +
"You need to use ACCESS_FINE_LOCATION with geofences", securityException);
}
public void HandleResult (Statuses status)
{
if (status.IsSuccess) {
mGeofencesAdded = !mGeofencesAdded;
var editor = mSharedPreferences.Edit ();
editor.PutBoolean (Constants.GEOFENCES_ADDED_KEY, mGeofencesAdded);
editor.Commit ();
SetButtonsEnabledState ();
Toast.MakeText (
this,
GetString (mGeofencesAdded ? Resource.String.geofences_added :
Resource.String.geofences_removed),
ToastLength.Short
).Show ();
} else {
var errorMessage = GeofenceErrorMessages.GetErrorString (this,
status.StatusCode);
Log.Error (TAG, errorMessage);
}
}
PendingIntent GetGeofencePendingIntent ()
{
if (mGeofencePendingIntent != null) {
return mGeofencePendingIntent;
}
//var intent = new Intent(this, typeof(Test));
//SendBroadcast(intent);
//return PendingIntent.GetBroadcast(this, 0, intent, PendingIntentFlags.UpdateCurrent);
var intent = new Intent(this, typeof(GeofenceTransitionsIntentService));
//SendBroadcast(intent);
return PendingIntent.GetService(this, 0, intent, PendingIntentFlags.UpdateCurrent);
}
public void PopulateGeofenceList ()
{
foreach (var entry in Constants.BAY_AREA_LANDMARKS) {
mGeofenceList.Add (new GeofenceBuilder ()
.SetRequestId (entry.Key)
.SetCircularRegion (
entry.Value.Latitude,
entry.Value.Longitude,
Constants.GEOFENCE_RADIUS_IN_METERS
)
.SetExpirationDuration (Constants.GEOFENCE_EXPIRATION_IN_MILLISECONDS)
.SetTransitionTypes (Geofence.GeofenceTransitionEnter |
Geofence.GeofenceTransitionExit)
.Build ());
}
}
void SetButtonsEnabledState ()
{
if (mGeofencesAdded) {
mAddGeofencesButton.Enabled = false;
mRemoveGeofencesButton.Enabled = true;
} else {
mAddGeofencesButton.Enabled = true;
mRemoveGeofencesButton.Enabled = false;
}
}
}
}
also i have tried making a broadcast reciever but it didnt helped me much

I see your code looks exactly like the sample you pull from the google developer page, and is the one many people is using more commonly at first. I myself was having issues with accuracy and missing fence transitions with that one too. I read that manually adding an instance of the previous location request package (LocationManager) and explicitly specifying GPS as a provider in high update mode can make it more accurate. That's how I have it working now. You can also try making your fences' radii wider, that way you will take into account the minimum wi-fi accuracy which is stated to be around 50m not considering drift.

Related

Setting Pending Intent to Builder in Onesignal NotificationExtenderService doesn't get Detected

I want to call Webview_activity on Notification Tap when app is killed , so in NotificationExtender Service ive attached Pending intent with the builder using setContentIntent() method, but nothing happens when notification is tapped.
Webview_activity is successfully called when application is alive, as that is handled by notificationOpened(), but when app is killed, onNotificationProcessing() is called but on Notification tap Webview_activity is not called.
I also read that Onesignal do not detect the setContentIntent() when attached to the builder here is the link :
https://github.com/OneSignal/OneSignal-Android-SDK/issues/511
is there a way around? how can i call my activity on notification tap using onNotificationProcessing() of NotificationExtender Service when app is killed.
#Override
protected boolean onNotificationProcessing(final OSNotificationReceivedResult notification) {
Log.d(TAG, "onNotificationProcessing");
final NotificationCompat.Builder[] newbuilder = new NotificationCompat.Builder[1];
OverrideSettings overrideSettings = new OverrideSettings();
overrideSettings.extender = new NotificationCompat.Extender() {
#Override
public NotificationCompat.Builder extend(NotificationCompat.Builder builder) {
// Sets the background notification color to Green on Android 5.0+ devices.
newbuilder[0] = builder;
Intent intent = new Intent();
try {
JSONObject data = notification.payload.additionalData;
if (data != null) {
String url = data.optString("url", null);
if (url != null) {
if (getApplicationContext() != null) {
Log.d(TAG, "context is not null");
intent = new Intent(getApplicationContext(), Webview_activity.class);
intent.putExtra("url", url);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
} else {
Log.d(TAG, "context is null");
}
}
}
**PendingIntent pendIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
newbuilder[0] = builder.setContentIntent(pendIntent);**
} catch (Exception e) {
e.printStackTrace();
}
return newbuilder[0];
}
};
overrideSettings.extender.extend(newbuilder[0]);
OSNotificationDisplayedResult displayedResult = displayNotification(overrideSettings);
Log.d("OneSignalExample", "Notification displayed with id: " + displayedResult.androidNotificationId);
return true;
}
#Override
public void notificationOpened(OSNotificationOpenResult result)
{
Log.d(TAG,"notificationOpened");
try {
JSONObject data = result.notification.payload.additionalData;
if (data != null) {
String url = data.optString("url", null);
if (url != null) {
if (context!=null)
{
Log.d(TAG,"context is not null");
Intent intent = new Intent(context, Webview_activity.class);
intent.putExtra("url", url);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}else {
Log.d(TAG,"context is null");
}
}
}
}catch (Exception e)
{
e.printStackTrace();
}
}

Service runs app is closed

I have an application in Xamarin.Forms and I have developed a service that works only when the application is open or minimized.
I've added some logs and the service keeps running even with the application closed, but part of my code that is on Portable does not run.
Code MainActivity
var alarmIntent = new Intent(context.ApplicationContext, typeof(Receiver.AlarmReceiver));
var broadcast = PendingIntent.GetBroadcast(context.ApplicationContext, 0, alarmIntent, PendingIntentFlags.NoCreate);
if (broadcast == null)
{
var pendingIntent = PendingIntent.GetBroadcast(context.ApplicationContext, 0, alarmIntent, 0);
var alarmManager = (AlarmManager)context.GetSystemService(Context.AlarmService);
alarmManager.SetRepeating(AlarmType.ElapsedRealtimeWakeup, SystemClock.ElapsedRealtime(), 15000, pendingIntent);
}
Code Alarm Receiver
[BroadcastReceiver]
class AlarmReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
var backgroundServiceIntent = new Intent(context, typeof(ServiceBackground));
context.StartService(backgroundServiceIntent);
}
}
Code Service
[Service]
public class ServiceBackground : Service
{
private const string TAG = "[ServiceBackground]";
private bool _isRunning;
private Context _context;
private Task _task;
public override IBinder OnBind(Intent intent)
{
return null;
}
public override void OnCreate()
{
_context = this;
_isRunning = false;
_task = new Task(RunServiceBackground);
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
if (!_isRunning)
{
_isRunning = true;
_task.Start();
}
return StartCommandResult.Sticky;
}
private void RunServiceBackground()
{
Log.Info(TAG, "StartCommandResult");
Task.Run(() =>
{
try
{
Log.Info(TAG, "init background portable");
var serviceOrdersSvc = new ServiceOrdersService();
serviceOrdersSvc.BackgroundExecute()
.ContinueWith(itemResult => {
if (!string.IsNullOrEmpty(itemResult.Result))
{
Log.Info(TAG, "itemResult");
}
});
}
catch (Android.OS.OperationCanceledException ex)
{
Log.Info(TAG, $"ex msg: {ex.Message} | s: {ex.StackTrace}");
}
catch (Exception ex)
{
Log.Info(TAG, $"ex msg: {ex.Message} | s: {ex.StackTrace}");
}
finally
{
StopSelf();
}
});
}
public override void OnDestroy()
{
base.OnDestroy();
}
}
Code portable (This part that does not work)
public async Task<string> BackgroundExecute()
{
//insert sqllite
await LogService.InsertLogAsync("init - BackgroundExecute");
//get sqllite
var list = await BackgroundTaskRequest.GetListAsync();
var rtnBackground = "";
if (list != null && list.Count > 0)
{
LogService.InsertLogAsync("list count: " + list.Count.ToString());
await Task.Run(async () =>
{
foreach (var item in list)
{
//send information web-api
}
});
}
LogService.InsertLogAsync($"end rtn: {rtnBackground}");
return rtnBackground;
}
Is the something i am missing here?

Cannot get android service to start at bootup

I have a boot receiver starting a service and also I can start and stop the service within the app.
But when I boot up the phone the service does start but stops instantly after starting. I have set the return on onStartCommand to START_STICKY.
This is my boot receiver:
public void onReceive(final Context context, final Intent intent) {
if(Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())){
Toast.makeText(context, "Boot received", Toast.LENGTH_LONG).show();
this.sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext());
this.mTelephonyMgr = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
this.encryption = new Encryption(mTelephonyMgr, sharedPreferences);
//startService(context);
Intent i = new Intent(context, ProfileActivity.class);
i.putExtra("boot_received", false);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
sharedPreferences.edit().putBoolean(Keys.AVAILABILITY, false).apply();
}
}
public void startService(final Context context){
final Intent intent = new Intent(context, PhoneCallService.class);
// If no token, try getting one.
if (Keys.phoneServiceToken == null || Keys.phoneServiceToken.isEmpty()) {
getToken(context, new Callbacks.ReceivePhoneServiceTokenCallback() {
#Override
public void receivePhoneServiceTokenCallback(boolean gotToken) {
if (gotToken) {
intent.putExtra(Keys.PHONE_SERVICE_TOKEN_EXTRA, Keys.phoneServiceToken);
intent.setAction(PhoneCallService.START_SERVICE);
context.startService(intent);
} else {
Log.d(LOG_TAG, String.valueOf(R.string.unexpected_error));
}
}
});
} else {
intent.putExtra(Keys.PHONE_SERVICE_TOKEN_EXTRA, Keys.phoneServiceToken);
intent.setAction(PhoneCallService.START_SERVICE);
context.startService(intent);
}
}
public void getToken(Context context, final Callbacks.ReceivePhoneServiceTokenCallback callback){
final String API = Keys.getpvmURL() + SharedResources.URL_DIRECT_CALL_TOKEN;
JsonObject json = encryption.getID();
json.addProperty("versionCode", BuildConfig.VERSION_CODE);
Ion.with(context)
.load(API)
.setTimeout(Keys.TIMEOUT_DIRECT_CALL_TOKEN)
.setJsonObjectBody(json)
.asJsonObject()
.withResponse()
.setCallback(new FutureCallback<Response<JsonObject>>() {
#Override
public void onCompleted(Exception e, Response<JsonObject> result) {
if(e == null) {
Log.d(LOG_TAG, "No Exceptions");
if(result.getHeaders().code() == 200) {
if(result.getResult().has("result")) {
Keys.phoneServiceToken = result.getResult().get("result").getAsString();
callback.receivePhoneServiceTokenCallback(true);
} else {
Log.w(LOG_TAG, "Does not have result");
callback.receivePhoneServiceTokenCallback(false);
}
} else {
Log.w(LOG_TAG, "Not getting 200 " + result.getHeaders().message());
callback.receivePhoneServiceTokenCallback(false);
}
} else {
Log.e(LOG_TAG, "Exception has occurred " + e.getClass());
callback.receivePhoneServiceTokenCallback(false);
}
}
});
This is my onStart and onCreate methods:
#Override
public void onCreate() {
Log.d(LOG_TAG, "Service started");
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(PhoneCallService.this);
notificationManager = (NotificationManager) PhoneCallService.this.getSystemService(Context.NOTIFICATION_SERVICE);
voiceBroadcastReceiver = new VoiceBroadcastReceiver();
registerReceiver();
audioManager = (AudioManager) PhoneCallService.this.getSystemService(Context.AUDIO_SERVICE);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(intent == null || intent.getAction() == null) {
Log.d(LOG_TAG, "No Action");
}
else if (intent.getAction().equals(START_SERVICE)) {
Log.d(LOG_TAG, "Starting PhoneCallService");
accessToken = intent.getStringExtra(Keys.PHONE_SERVICE_TOKEN_EXTRA);
Log.d(LOG_TAG, accessToken);
if (accessToken != null && !accessToken.isEmpty()) {
registerForCallInvites();
MyFcmListenerService.availableToCall = true;
} else {
stopSelf();
MyFcmListenerService.availableToCall = false;
}
}
else if (intent.getAction().equals(STOP_SERVICE)) {
stopSelf();
MyFcmListenerService.availableToCall = false;
}
else if (intent.getAction().equals(ACTION_INCOMING_CALL)) {
handleIncomingCallIntent(intent);
}
else {
Log.d(LOG_TAG, intent.getAction());
}
return START_STICKY;
}
For some reason I just can't get it to work on the boot request.

Android: onReceiveResult is not triggered

I'm trying to get some data from a Service that gets an address from coordinates. I followed the step by step official android tutorial about this (http://developer.android.com/training/location) but i'm stuck. I'm sending the data from the Service class to the Activity using the send method but the onReceiveResult method doesn't seem to trigger. Here's my Service class:
public class FetchAddressIntentService extends IntentService {
protected ResultReceiver mReceiver;
public FetchAddressIntentService(String name) {
super(name);
}
public FetchAddressIntentService() {
super("FetchAddressIntentService");
}
#Override
protected void onHandleIntent(Intent intent) {
Geocoder geocoder = new Geocoder(this, Locale.getDefault());
String errorMessage = "";
// Get the location passed to this service through an extra.
Location location = intent.getParcelableExtra(Constants.LOCATION_DATA_EXTRA);
mReceiver = new ResultReceiver(new Handler());
List < Address > addresses = null;
try {
addresses = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1); //we want 1 result
} catch (IOException ioException) {
errorMessage = getString(R.string.service_not_available);
Log.e("TAG", errorMessage, ioException);
} catch (IllegalArgumentException illegalArgumentException) {
errorMessage = getString(R.string.invalid_lat_long_used);
Log.e("TAG", errorMessage + ". " + "Latitude = " + location.getLatitude() + ", Longitude = " + location.getLongitude(), illegalArgumentException);
}
if (addresses == null || addresses.size() == 0) {
if (errorMessage.isEmpty()) {
errorMessage = getString(R.string.no_address_found);
Log.e("TAG", errorMessage);
}
deliverResultToReceiver(Constants.FAILURE_RESULT, errorMessage);
} else {
Address address = addresses.get(0);
ArrayList < String > addressFragments = new ArrayList < String > ();
for (int i = 0; i < address.getMaxAddressLineIndex(); i++) {
addressFragments.add(address.getAddressLine(i));
}
Log.i("TAG", getString(R.string.address_found) + ": " + addressFragments.get(0));
deliverResultToReceiver(Constants.SUCCESS_RESULT, TextUtils.join(System.getProperty("line.separator"), addressFragments));
}
}
private void deliverResultToReceiver(int resultCode, String message) {
Bundle bundle = new Bundle();
bundle.putString(Constants.RESULT_DATA_KEY, message);
mReceiver.send(resultCode, bundle);
}
}
And the relevant part of my Activity:
class AddressResultReceiver extends ResultReceiver {
public AddressResultReceiver(Handler handler) {
super(handler);
}
#Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
mAddressOutput = resultData.getString(Constants.RESULT_DATA_KEY);
Log.i("address", mAddressOutput);
address.setText(mAddressOutput);
if (resultCode == Constants.SUCCESS_RESULT) {
Toast.makeText(LocationActivity.this, getString(R.string.address_found),
Toast.LENGTH_LONG).show();
}
}
}
You need to create receiver in Activity
private AddressResultReceiver mReceiver;
#Override
protected void onResume() {
super.onResume();
mReceiver = new AddressResultReceiver(new Handler());
mReceiver.setReceiver(this);
}
and pass to Intent service
public void onStarService() {
final Intent intent = new Intent("SOME_COMMAND_ACTION", null, this, FetchAddressIntentService.class);
intent.putExtra("RECEIVER", mReceiver);
startService(intent);
}
and in FetchAddressIntentService
#Override
protected void onHandleIntent(Intent intent) {
final ResultReceiver receiver = intent.getParcelableExtra("RECEIVER");
/// your code
}
The problem is with this line:
mReceiver = new ResultReceiver(new Handler());
Replace it with this:
mReceiver = intent.getParcelableExtra(Constants.RECEIVER);
The problem is that you're creating a new ResultReceiver instead of using the one that is presumably passed in as an Intent extra from this code:
protected void startIntentService() {
Intent intent = new Intent(this, FetchAddressIntentService.class);
intent.putExtra(Constants.RECEIVER, mResultReceiver);
intent.putExtra(Constants.LOCATION_DATA_EXTRA, mLastLocation);
startService(intent);
}
So, just use the one passed in as an extra in the Intent, and it should work.

android not getting calls on the other side when using gcm and sinch sdk

I'm trying to use gcm to start calls in sinch, I send the push notification and I get it on the other side but when I try to start a call I get null pointer exception in my service at mCall.addCallListener( );
this is the part of the gcm intent service where I get the notification and start sinch service :
{
String callId = intent.getExtras().getString("callId");
Intent intent3 = new Intent(this, SinchClientService.class);
intent3.setAction(SinchClientService.ACTION_START_CALL);
intent3.putExtra(SinchClientService.INTENT_EXTRA_CALLID, callId);
startService(intent3);
}
this is what I do in the sinch service:
else if(intent.getAction().equals(ACTION_START_CALL))
{
String callId = intent.getStringExtra(INTENT_EXTRA_CALLID);
if(callId != null)
{
startCall(callId);
}
}
public void startCall(String callId) {
if (mCallClient != null) {
Call call = mCallClient.getCall(callId);
CurrentCall.currentCall = call;
Intent intent = new Intent(this, CallService.class);
startService(intent);
}
}
and this is how I start sinch client:
private void startSinchClient(String id, String userName) {
mSinchClient = Sinch.getSinchClientBuilder().context(this).userId(id).
applicationKey(APP_KEY).applicationSecret(APP_SECRET).environmentHost(ENVIRONMENT).build();
mSinchClient.addSinchClientListener(this);
mSinchClient.setSupportCalling(true);
mSinchClient.setSupportMessaging(true);
mSinchClient.setSupportPushNotifications(true);
mSinchClient.setSupportActiveConnectionInBackground(false);
//mSinchClient.startListeningOnActiveConnection();
mMessageClient = mSinchClient.getMessageClient();
mMessageClient.addMessageClientListener(this);
mCallClient = mSinchClient.getCallClient();
mCallClient.addCallClientListener(this);
mSinchClient.checkManifest();
mSinchClient.start();
}
and this is my onIcommingCall method:
#Override
public void onIncomingCall(CallClient client, Call call) {
Log.d(TAG, "Incoming call");
CurrentCall.currentCall = call;
Intent intent = new Intent(this, CallService.class);
startService(intent);
}
and this is the part of my call service where I get null pointer exception:
if(CurrentCall.currentCall == null)
stopSelf();
mCall = CurrentCall.currentCall;
mCall.addCallListener(this);
Note: my call service implements call listener
I never get the call, can someone help me?
Edit this is how I initialize a call:
in the sinch service:
public void callFriend(String id) {
if (mCallClient != null) {
Call call = mCallClient.callUser(id);
CurrentCall.currentCall = call;
Intent intent = new Intent(this, CallService.class);
startService(intent);
}
}
in the call service:
#Override
public void onShouldSendPushNotification(Call call, List<PushPair> pushPairs) {
Log.d(LOG_TAG, "Should send push notification");
Log.d("payload", pushPairs.get(0).getPushPayload());
asyncTask = new sendPushNotifications(this, call.getRemoteUserId(), pushPairs, call.getCallId());
asyncTask.execute();
}
class sendPushNotifications extends AutoAsyncTask {
List<PushPair> pushPairs;
String message;
String senderId;
String message_id;
String time_stamp;
String callId;
public sendPushNotifications(Context context, String senderId, List<PushPair> pushPairs, String callId) {
super(context, false);
this.pushPairs = pushPairs;
this.senderId = senderId;
this.callId = callId;
}
#Override
protected Integer doInBackground(Void... params) {
boolean connectedToInternet = connManager.getNetworkInfo( ConnectivityManager.TYPE_WIFI).isConnected()
|| connManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).isConnected();
if (connectedToInternet)
{
String regId;
//JSONArray arrayList = new JSONArray();
for(PushPair p: pushPairs)
{
regId = new String(p.getPushData());
//arrayList.put(regId);
UserFunctions.sendCallPushNotifications(senderId, regId, "call", callId);
}
asyncTask = null;
return 0;
}
else
{
asyncTask = null;
return 1;
}
}
#Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
if (result == 0)
{
Log.d("call push sent", "sent");
}
else if (result == 1)
{
Toast.makeText(getApplicationContext(),
"No Network Connection !!", Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(
getApplicationContext(),
"Error occured,Please Try Again Later !!",
Toast.LENGTH_SHORT).show();
}
}
}
}
latest edit so I did what you said and I only get calls in the messaging activity, my new codes are:
in the call service:
#Override
public void onShouldSendPushNotification(Call call, List<PushPair> pushPairs) {
Log.d(LOG_TAG, "Should send push notification");
Log.d("payload", pushPairs.get(0).getPushPayload());
asyncTask = new sendPushNotifications(this, call.getRemoteUserId(), pushPairs, call.getCallId());
asyncTask.execute();
}
class sendPushNotifications extends AutoAsyncTask {
List<PushPair> pushPairs;
String message;
String senderId;
String message_id;
String time_stamp;
String callId;
public sendPushNotifications(Context context, String senderId, List<PushPair> pushPairs, String callId) {
super(context, false);
this.pushPairs = pushPairs;
this.senderId = senderId;
this.callId = callId;
}
#Override
protected Integer doInBackground(Void... params) {
boolean connectedToInternet = connManager.getNetworkInfo( ConnectivityManager.TYPE_WIFI).isConnected()
|| connManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).isConnected();
if (connectedToInternet)
{
String regId;
String payload;
//JSONArray arrayList = new JSONArray();
for(PushPair p: pushPairs)
{
regId = new String(p.getPushData());
payload = new String(p.getPushPayload());
//arrayList.put(regId);
UserFunctions.sendCallPushNotifications(senderId, regId, "call", callId, payload);
}
asyncTask = null;
return 0;
}
else
{
asyncTask = null;
return 1;
}
}
#Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
if (result == 0)
{
Log.d("call push sent", "sent");
}
else if (result == 1)
{
Toast.makeText(getApplicationContext(),
"No Network Connection !!", Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(
getApplicationContext(),
"Error occured,Please Try Again Later !!",
Toast.LENGTH_SHORT).show();
}
}
}
the gcm intent service:
else
{
String callId = intent.getExtras().getString("callId");
String payload = intent.getExtras().getString("payload");
Intent intent3 = new Intent(this, SinchClientService.class);
intent3.setAction(SinchClientService.ACTION_START_CALL);
intent3.putExtra(SinchClientService.INTENT_EXTRA_CALLID, callId);
intent3.putExtra(SinchClientService.INTENT_EXTRA_PAYLOAD, payload);
startService(intent3);
}
the sinch service:
else if(intent.getAction().equals(ACTION_START_CALL))
{
String callId = intent.getStringExtra(INTENT_EXTRA_CALLID);
if(callId != null)
{
startCall(callId);
}
}
public void startCall(String callId) {
/*if (mCallClient != null) {
Call call = mCallClient.getCall(callId);
CurrentCall.currentCall = call;
Intent intent = new Intent(this, CallService.class);
startService(intent);
}*/
if(INTENT_EXTRA_PAYLOAD != null)
{
if(mSinchClient.isStarted())
mSinchClient.relayRemotePushNotificationPayload(INTENT_EXTRA_PAYLOAD);
else
{
DatabaseHandler handler = new DatabaseHandler(this);
UserInfo info = handler.getUserDetails();
startSinchClient(String.valueOf(info.uid), info.name);
String gcm_regId = ChatDatabaseHandler.getInstance(this).getGcmRegId();
mSinchClient.registerPushNotificationData(gcm_regId.getBytes());
}
}
}
#Override
public void onIncomingCall(CallClient client, Call call) {
Log.d(TAG, "Incoming call");
/*if(INTENT_EXTRA_CALLID != null)
{
CurrentCall.currentCall = mCallClient.getCall(INTENT_EXTRA_CALLID);
INTENT_EXTRA_CALLID = null;
}*/
CurrentCall.currentCall = call;
Intent intent = new Intent(this, CallService.class);
startService(intent);
}
that is also what I do when I bind and unbind with the service:
#Override
public boolean onUnbind(Intent intent) {
mSinchClient.stopListeningOnActiveConnection();
return super.onUnbind(intent);
}
#Override
public IBinder onBind(Intent intent) {
mSinchClient.startListeningOnActiveConnection();
return mServiceInterface;
}
You seem to be missing the code where you actually send the Sinch-specific payload in your push, you should use PushPair.getPushPayload() to retrieve it in the onShouldSendPushNotification callback and make sure to include that in the push message.
After you add that, you need to retrieve the payload on the receiver side and pass in to relayRemotePushNotificationPayload(String payload). This will give you the onIncomingCall callback on the receiver side.

Categories

Resources