Cordova Webview SSLErrorHandler, playstore rejects after few days since released - android-security

i have a problem with cordova application: when i publish app on playstore, after few days the app will be removed because of vulnerability to Webview SSLErrorHandler. I tried a lot of solution found on stack overflow but the error persists.
The last one i tried is the following:
#Override
public void onReceivedSslError(WebView view, final SslErrorHandler handler, SslError error) {
final AlertDialog.Builder builder = new AlertDialog.Builder(view.getContext());
String message = "SSL Certificate error.";
switch (error.getPrimaryError()) {
case SslError.SSL_UNTRUSTED:
message = "The certificate authority is not trusted.";
break;
case SslError.SSL_EXPIRED:
message = "The certificate has expired.";
break;
case SslError.SSL_IDMISMATCH:
message = "The certificate Hostname mismatch.";
break;
case SslError.SSL_NOTYETVALID:
message = "The certificate is not yet valid.";
break;
}
message += " Do you want to continue anyway?";
builder.setTitle("SSL Certificate Error");
builder.setMessage(message);
builder.setPositiveButton("continue", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
handler.proceed();
}
});
builder.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
handler.cancel();
}
});
final AlertDialog dialog = builder.create();
dialog.show();
}
Do you have any suggestion for resolving the issue?
Thanks a lot !

Related

Using firebase cloud messaging for user to user push notifications [duplicate]

I have been trying to read the official docs and guides about how to send message from one device to another. I have saved registration token of both devices in the Real Time Database, thus I have the registration token of another device.
I have tried the following way to send the message
RemoteMessage message = new RemoteMessage.Builder(getRegistrationToken())
.setMessageId(incrementIdAndGet())
.addData("message", "Hello")
.build();
FirebaseMessaging.getInstance().send(message);
However this is not working. The other device doesn't receive any message. I am not even sure, if I can use upstream message sending to conduct device to device communication.
PS: I just want to know if device-to-device messaging is possible using FCM? If yes, then is the code I used have some issue? If yes, then what is the correct way.
Update:
My question was to ask whether device to device messaging without using any separate server other than firebase could messaging is possible or not, if yes than how, since there's no documentation about it. I do not understand what is left to explain here? Anyways I got the answer and will update it as an answer once the question gets reopened.
Firebase has two features to send messages to devices:
the Notifications panel in your Firebase Console allows you to send notifications to specific devices, groups of users, or topics that users subscribed to.
by calling Firebase Cloud Messaging API, you can send messages with whatever targeting strategy you prefer. Calling the FCM API requires access to your Server key, which you should never expose on client devices. That's why you should always run such code on an app server.
The Firebase documentation shows this visually:
Sending messages from one device directly to another device is not supported through the Firebase Cloud Messaging client-side SDKs.
Update: I wrote a blog post detailing how to send notifications between Android devices using Firebase Database, Cloud Messaging and Node.js.
Update 2: You can now also use Cloud Functions for Firebase to send messages securely, without spinning up a server. See this sample use-case to get started. If you don't want to use Cloud Functions, you can run the same logic on any trusted environment you already have, such as your development machine, or a server you control.
Warning There is a very important reason why we don't mention this approach anywhere. This exposes your server key in the APK that
you put on every client device. It can (and thus will) be taken from
there and may lead to abuse of your project. I highly recommend
against taking this approach, except for apps that you only put on
your own devices. – Frank van Puffelen
Ok, so the answer by Frank was correct that Firebase does not natively support device to device messaging. However there's one loophole in that. The Firebase server doesn't identify whether you have send the request from an actual server or are you doing it from your device.
So all you have to do is send a Post Request to Firebase's messaging server along with the Server Key. Just keep this in mind that the server key is not supposed to be on the device, but there's no other option if you want device-to-device messaging using Firebase Messaging.
I am using OkHTTP instead of default way of calling the Rest API. The code is something like this -
public static final String FCM_MESSAGE_URL = "https://fcm.googleapis.com/fcm/send";
OkHttpClient mClient = new OkHttpClient();
public void sendMessage(final JSONArray recipients, final String title, final String body, final String icon, final String message) {
new AsyncTask<String, String, String>() {
#Override
protected String doInBackground(String... params) {
try {
JSONObject root = new JSONObject();
JSONObject notification = new JSONObject();
notification.put("body", body);
notification.put("title", title);
notification.put("icon", icon);
JSONObject data = new JSONObject();
data.put("message", message);
root.put("notification", notification);
root.put("data", data);
root.put("registration_ids", recipients);
String result = postToFCM(root.toString());
Log.d(TAG, "Result: " + result);
return result;
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String result) {
try {
JSONObject resultJson = new JSONObject(result);
int success, failure;
success = resultJson.getInt("success");
failure = resultJson.getInt("failure");
Toast.makeText(getCurrentActivity(), "Message Success: " + success + "Message Failed: " + failure, Toast.LENGTH_LONG).show();
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(getCurrentActivity(), "Message Failed, Unknown error occurred.", Toast.LENGTH_LONG).show();
}
}
}.execute();
}
String postToFCM(String bodyString) throws IOException {
RequestBody body = RequestBody.create(JSON, bodyString);
Request request = new Request.Builder()
.url(FCM_MESSAGE_URL)
.post(body)
.addHeader("Authorization", "key=" + SERVER_KEY)
.build();
Response response = mClient.newCall(request).execute();
return response.body().string();
}
I hope Firebase will come with a better solution in future. But till then, I think this is the only way. The other way would be to send topic message or group messaging. But that was not in the scope of the question.
Update:
The JSONArray is defined like this -
JSONArray regArray = new JSONArray(regIds);
regIds is a String array of registration ids, you want to send this message to. Keep in mind that the registration ids must always be in an array, even if you want it to send to a single recipient.
I have also been using direct device to device gcm messaging in my prototype. It has been working very well. We dont have any server. We exchange GCM reg id using sms/text and then communicate using GCM after that. I am putting here code related to GCM handling
**************Sending GCM Message*************
//Sends gcm message Asynchronously
public class GCM_Sender extends IntentService{
final String API_KEY = "****************************************";
//Empty constructor
public GCM_Sender() {
super("GCM_Sender");
}
//Processes gcm send messages
#Override
protected void onHandleIntent(Intent intent) {
Log.d("Action Service", "GCM_Sender Service Started");
//Get message from intent
String msg = intent.getStringExtra("msg");
msg = "\"" + msg + "\"";
try{
String ControllerRegistrationId = null;
//Check registration id in db
if(RegistrationIdAdapter.getInstance(getApplicationContext()).getRegIds().size() > 0 ) {
String controllerRegIdArray[] = RegistrationIdAdapter.getInstance(getApplicationContext()).getRegIds().get(1);
if(controllerRegIdArray.length>0)
ControllerRegistrationId = controllerRegIdArray[controllerRegIdArray.length-1];
if(!ControllerRegistrationId.equalsIgnoreCase("NULL")){
// 1. URL
URL url = new URL("https://android.googleapis.com/gcm/send");
// 2. Open connection
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
// 3. Specify POST method
urlConnection.setRequestMethod("POST");
// 4. Set the headers
urlConnection.setRequestProperty("Content-Type", "application/json");
urlConnection.setRequestProperty("Authorization", "key=" + API_KEY);
urlConnection.setDoOutput(true);
// 5. Add JSON data into POST request body
JSONObject obj = new JSONObject("{\"time_to_live\": 0,\"delay_while_idle\": true,\"data\":{\"message\":" + msg + "},\"registration_ids\":[" + ControllerRegistrationId + "]}");
// 6. Get connection output stream
OutputStreamWriter out = new OutputStreamWriter(urlConnection.getOutputStream());
out.write(obj.toString());
out.close();
// 6. Get the response
int responseCode = urlConnection.getResponseCode();
BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null){
response.append(inputLine);
}
in.close();
Log.d("GCM getResponseCode:", new Integer(responseCode).toString());
}else{
Log.d("GCM_Sender:","Field REGISTRATION_TABLE is null");
}
}else {
Log.d("GCM_Sender:","There is no Registration ID in DB ,please sync devices");
}
} catch (Exception e) {
e.printStackTrace();
//MessageSender.getInstance().sendMessage(msg, Commands.SMS_MESSAGE);
}
}
//Called when service is no longer alive
#Override
public void onDestroy() {
super.onDestroy();
//Do a log that GCM_Sender service has been destroyed
Log.d("Action Service", "GCM_Sender Service Destroyed");
}
}
**************Receiving GCM Message*************
public class GCM_Receiver extends WakefulBroadcastReceiver {
public static final String RETRY_ACTION ="com.google.android.c2dm.intent.RETRY";
public static final String REGISTRATION ="com.google.android.c2dm.intent.REGISTRATION";
public SharedPreferences preferences;
//Processes Gcm message .
#Override
public void onReceive(Context context, Intent intent) {
ComponentName comp = new ComponentName(context.getPackageName(),
GCMNotificationIntentService.class.getName());
//Start GCMNotificationIntentService to handle gcm message asynchronously
startWakefulService(context, (intent.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
/*//Check if DatabaseService is running .
if(!DatabaseService.isServiceRunning) {
Intent dbService = new Intent(context,DatabaseService.class);
context.startService(dbService);
}*/
//Check if action is RETRY_ACTION ,if it is then do gcm registration again .
if(intent.getAction().equals(RETRY_ACTION)) {
String registrationId = intent.getStringExtra("registration_id");
if(TextUtils.isEmpty(registrationId)){
DeviceRegistrar.getInstance().register(context);
}else {
//Save registration id to prefs .
preferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = preferences.edit();
editor.putString("BLACKBOX_REG_ID",registrationId);
editor.commit();
}
} else if (intent.getAction().equals(REGISTRATION)) {
}
}
}
//Processes gcm messages asynchronously .
public class GCMNotificationIntentService extends IntentService{
public static final int NOTIFICATION_ID = 1;
private NotificationManager mNotificationManager;
String gcmData;
private final String TAG = "GCMNotificationIntentService";
//Constructor with super().
public GCMNotificationIntentService() {
super("GcmIntentService");
}
//Called when startService() is called by its Client .
//Processes gcm messages .
#Override
protected void onHandleIntent(Intent intent) {
Log.d("GCMNotificationIntentService", "GCMNotificationIntentService Started");
Bundle extras = intent.getExtras();
//Get instance of GoogleCloudMessaging .
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
//Get gcm message type .
String messageType = gcm.getMessageType(intent);
if (!extras.isEmpty()) {
if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR
.equals(messageType)) {
sendNotification("Send error: " + extras.toString());
} else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED
.equals(messageType)) {
sendNotification("Deleted messages on server: "
+ extras.toString());
} else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE
.equals(messageType)) {
Log.i(TAG, "Completed work # " + SystemClock.elapsedRealtime());
gcmData = extras.getString("message");
Intent actionService = new Intent(getApplicationContext(),Action.class);
actionService.putExtra("data", gcmData);
//start Action service .
startService(actionService);
//Show push notification .
sendNotification("Action: " + gcmData);
//Process received gcmData.
Log.d(TAG,"Received Gcm Message from Controller : " + extras.getString("message"));
}
}
GCM_Receiver.completeWakefulIntent(intent);
}
//Shows notification on device notification bar .
private void sendNotification(String msg) {
mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
Intent notificationIntent = new Intent(this, BlackboxStarter.class);
//Clicking on GCM notification add new layer of app.
notificationIntent.setFlags( Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
this).setSmallIcon(R.drawable.gcm_cloud)
.setContentTitle("Notification from Controller")
.setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
.setContentText(msg);
mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
//Play default notification
try {
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), notification);
r.play();
} catch (Exception e) {
e.printStackTrace();
}
}
//Called when service is no longer be available .
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Log.d("GCMNotificationIntentService", "GCMNotificationIntentService Destroyed");
}
}
According to the new documentation which was updated on October 2, 2018 you must send post request as below
https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA //Server key
{
"to": "sent device's registration token",
"data": {
"hello": "message from someone",
}
}
To get device's registration token extend FirebaseMessagingService and override onNewToken(String token)
For more info refer to doc https://firebase.google.com/docs/cloud-messaging/android/device-group
I am late but above solutions has helped me to write down this simple answer, you can send your message directly to android devices from android application, here is the simple implementation I have done and it works great for me.
compile android volley library
compile 'com.android.volley:volley:1.0.0'
Just copy paste this simple function ;) and your life will become smooth just like knife in butter. :D
public static void sendPushToSingleInstance(final Context activity, final HashMap dataValue /*your data from the activity*/, final String instanceIdToken /*firebase instance token you will find in documentation that how to get this*/ ) {
final String url = "https://fcm.googleapis.com/fcm/send";
StringRequest myReq = new StringRequest(Request.Method.POST,url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Toast.makeText(activity, "Bingo Success", Toast.LENGTH_SHORT).show();
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(activity, "Oops error", Toast.LENGTH_SHORT).show();
}
}) {
#Override
public byte[] getBody() throws com.android.volley.AuthFailureError {
Map<String, Object> rawParameters = new Hashtable();
rawParameters.put("data", new JSONObject(dataValue));
rawParameters.put("to", instanceIdToken);
return new JSONObject(rawParameters).toString().getBytes();
};
public String getBodyContentType()
{
return "application/json; charset=utf-8";
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Authorization", "key="+YOUR_LEGACY_SERVER_KEY_FROM_FIREBASE_CONSOLE);
headers.put("Content-Type","application/json");
return headers;
}
};
Volley.newRequestQueue(activity).add(myReq);
}
Note
If you want to send message to topics so you can change parameter instanceIdToken to something like /topics/topicName.
For groups implementation is the same but you just need to take care of parameters. checkout Firebase documentation and you can pass those parameters.
let me know if you face any issue.

Changing phone number for Firebase Phone Auth creates a new user UID? [duplicate]

I am using Android Firebase Auth Ui for providing Phone Number based sign in option in an android app. I am trying to provide an additional option to signed in users to switch their signed in phone number to another number keeping the same user account.
But as per Firebase Docs for Phone number there are no options to change the signed in number.
There are options for linking different auth providers like email, google or Facebook login etc to same account. But there is no way mentioned about how to change the phone number or email id keeping the same user id.
Is there a workaround or method by which we can achieve this?
An API exists for updating the phone number of a current user: FirebaseUser#updatePhoneNumber(PhoneAuthCredential credential)
I also had this challenge to update user phone number and when I go on documentation I got something by using I have done this task.
you can go for documentation by click here
Now the method you can use : - for java android project.
PhoneAuthCredential phoneAuthCredential = PhoneAuthProvider.getCredential( "+91-98298XXXX2", "OTP_CODE" );
// Update Mobile Number...
firebaseAuth.getCurrentUser().updatePhoneNumber(phoneAuthCredential)
.addOnCompleteListener(new OnCompleteListener <Void>() {
#Override
public void onComplete(#NonNull Task <Void> task) {
if (task.isSuccessful()) {
// Update Successfully
} else {
// Failed
}
}
}
);
val options = PhoneAuthOptions.newBuilder(FirebaseAuth.getInstance())
.setPhoneNumber(phoneNumber) // Phone number to verify
.setTimeout(100L, TimeUnit.SECONDS) // Timeout and unit
.setActivity(activity) // Activity (for callback binding)
.setCallbacks(returnCallBack()) // OnVerificationStateChangedCallbacks
.build()
PhoneAuthProvider.verifyPhoneNumber(options)
private fun returnCallBack() = object : PhoneAuthProvider
.OnVerificationStateChangedCallbacks() {
override fun onVerificationCompleted(credential: PhoneAuthCredential) {
FirebaseAuth.getCurrentUser()?.updatePhoneNumber(credential)
}
override fun onVerificationFailed(e: FirebaseException) {
// This callback is invoked in an invalid request for verification is made,
// for instance if the the phone number format is not valid.
Log.e("phone", e.toString())
}
override fun onCodeSent(verificationId: String, token: PhoneAuthProvider.ForceResendingToken) {
//You need this to pass as a parameter for the update method call.
vericationSent = verificationId
}
}
fun confirmChange(code: String, context: Context?) {
if(code.contains(Regex(onlyNumber))) {
Log.d("codeSent" , "Right code : $code")
FirebaseAuth.getCurrentUser()
?.updatePhoneNumber(PhoneAuthProvider.getCredential(vericationSent, code))
?.addOnCompleteListener {task ->
//it worked if you reach here.
}?.addOnFailureListener {
//Show the error to user
}
}
vericationSent = EMPTY
} else {
Log.d("codeSent" , "wrong code : $code")
}
}
Try this
//Send otp to phone number
String verificationId;
private void startLoginFirebase(){
PhoneAuthProvider.getInstance(firebaseAuth).verifyPhoneNumber(phone, 90L, TimeUnit.SECONDS, PhoneAuthActivity.this, new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
#Override
public void onCodeSent(#NonNull String s, #NonNull PhoneAuthProvider.ForceResendingToken forceResendingToken) {
super.onCodeSent(s, forceResendingToken);
verificationId = s;
updatePhoneNum();
}
#Override
public void onCodeAutoRetrievalTimeOut(#NonNull String s) {
super.onCodeAutoRetrievalTimeOut(s);
}
#Override
public void onVerificationCompleted(#NonNull PhoneAuthCredential phoneAuthCredential) {
}
#Override
public void onVerificationFailed(#NonNull FirebaseException e) {
processFurther(e.getLocalizedMessage().toString(), 0);
}
});
}
//Verify Otp
private void updatePhoneNum(){
PhoneAuthCredential phoneAuthCredential = PhoneAuthProvider.getCredential(verificationId, otp);
firebaseAuth.getCurrentUser().updatePhoneNumber(phoneAuthCredential).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
}
});
}
Apparently - according to the project maintainers - FirebaseUI-Android doesn't support this feature, and it looks like they have no plans of doing it any time soon :(

FCM on iOS An error occured on client IDB480752 while executing a reply for topic xvs/idb/4.8.0.752/stop-app

I added firecloud messaging to my iOS app as described here https://components.xamarin.com/gettingstarted/firebaseioscloudmessaging#subscribe-the-client-app-to-a-topic and it seems to work fine for both foreground and background notificaitons on initial run of the app. I am actually using the nuget Xamarin.Firebase.iOS.CloudMessaging not the component.
When I open the app a second time after having sent at least one push notification I get this error at launch in the debug output.
An error occured on client IDB480752 while executing a reply for topic xvs/idb/4.8.0.752/stop-app
Looking at the ide logs gives a little more detail.
NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)
2018-02-16 16:47:54.525 RecoveryConnect_Mobile_PCLiOS[1018:3202793] Encounter network error. Code, error: -1200, Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSURLErrorFailingURLPeerTrustErrorKey=, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, NSErrorPeerCertificateChainKey=(
"",
""
), NSUnderlyingError=0x10b0f5190 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, kCFStreamPropertySSLPeerTrust=, _kCFNetworkCFStreamSSLErrorOriginalValue=-9802, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, kCFStreamPropertySSLPeerCertificates=(
"",
""
)}}, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://play.googleapis.com/log, NSErrorFailingURLStringKey=https://play.googleapis.com/log, NSErrorClientCertificateStateKey=0}
The app has been terminated.
Failed to Stop app: An error occured on client IDB480752 while executing a reply for topic xvs/idb/4.8.0.752/stop-app
The app has been terminated.
public partial class AppDelegate :
global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate,
IUNUserNotificationCenterDelegate, IMessagingDelegate
{
global::Xamarin.Forms.Forms.Init();
global::Xamarin.FormsMaps.Init();
App.BuildNumber = NSBundle.MainBundle.InfoDictionary[new
NSString("CFBundleVersion")].ToString();
LoadApplication(new App());
RegisterForPushNotifications();
return base.FinishedLaunching(app, options);
}
public override void DidEnterBackground(UIApplication uiApplication)
{
//Messaging.SharedInstance.ShouldEstablishDirectChannel = false;
Messaging.SharedInstance.Disconnect();
}
public override void OnActivated(UIApplication uiApplication)
{
ConnectFCM();
UIApplication.SharedApplication.ApplicationIconBadgeNumber = 0;
base.OnActivated(uiApplication);
}
private void RegisterForPushNotifications()
{
try
{
Firebase.Core.App.Configure();
if (UIDevice.CurrentDevice.CheckSystemVersion(10, 0))
{
// iOS 10 or later
var authOptions = UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound;
UNUserNotificationCenter.Current.RequestAuthorization(authOptions, (granted, error) => {
Console.WriteLine(granted);
});
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.Current.Delegate = this;
// For iOS 10 data message (sent via FCM)
Messaging.SharedInstance.RemoteMessageDelegate = this;
}
else
{
// iOS 9 or before
var allNotificationTypes = UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound;
var settings = UIUserNotificationSettings.GetSettingsForTypes(allNotificationTypes, null);
UIApplication.SharedApplication.RegisterUserNotificationSettings(settings);
}
UIApplication.SharedApplication.RegisterForRemoteNotifications();
Firebase.InstanceID.InstanceId.Notifications.ObserveTokenRefresh((sender, e) =>
{
var newToken = Firebase.InstanceID.InstanceId.SharedInstance.Token;
var FCMTokenRegistration = new Models.Model_FCMToken(newToken);
FCMTokenRegistration.StoreToken();
// if you want to send notification per user, use this token
System.Diagnostics.Debug.WriteLine(newToken);
ConnectFCM();
});
}
catch(System.Exception ex)
{
Helpers.Helper_ErrorHandling.SendErrorToServer(ex);
}
}
private void ConnectFCM()
{
Messaging.SharedInstance.Connect(error => {
if (error != null)
{
// Handle if something went wrong while connecting
}
else
{
// Let the user know that connection was successful
}
});
}
public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)
{
// If you are receiving a notification message while your app is in the background,
// this callback will not be fired 'till the user taps on the notification launching the application.
// Do your magic to handle the notification data
System.Console.WriteLine(userInfo);
}
// To receive notifications in foreground on iOS 10 devices.
[Export("userNotificationCenter:willPresentNotification:withCompletionHandler:")]
public void WillPresentNotification(UNUserNotificationCenter center, UNNotification notification, Action<UNNotificationPresentationOptions> completionHandler)
{
// Do your magic to handle the notification data
System.Console.WriteLine(notification.Request.Content.UserInfo);
}
// Receive data message on iOS 10 devices.
public void ApplicationReceivedRemoteMessage(RemoteMessage remoteMessage)
{
Console.WriteLine(remoteMessage.AppData);
}
[Export("userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:")]
public void DidReceiveNotificationResponse(UNUserNotificationCenter center, UNNotificationResponse response, Action completionHandler)
{
// Do your magic to handle the notification data
System.Console.WriteLine("");
}
public void DidRefreshRegistrationToken(Messaging messaging, string fcmToken)
{
var token = fcmToken;
//var newToken = Firebase.InstanceID.InstanceId.SharedInstance.Token;
//var FCMTokenRegistration = new Models.Model_FCMToken(newToken);
//FCMTokenRegistration.StoreToken();
//// if you want to send notification per user, use this token
//System.Diagnostics.Debug.WriteLine(newToken);
//ConnectFCM();
}
I did try adding NSAppTransportSecurity for arbitrary loads with no avail.

how to resolve this error.....i am trying to implement custom firebase notification application

Error:(29, 44) error: cannot access AbstractSafeParcelable
class file for com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable not found
public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
private static final String TAG = MyFirebaseInstanceIDService.class.getSimpleName();
#Override
public void onTokenRefresh() {
super.onTokenRefresh();
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
// Saving reg id to shared preferences
storeRegIdInPref(refreshedToken);
// sending reg id to your server
sendRegistrationToServer(refreshedToken);
// Notify UI that registration has completed, so the progress indicator can be hidden.
Intent registrationComplete = new Intent(Config.REGISTRATION_COMPLETE);
registrationComplete.putExtra("token", refreshedToken);
LocalBroadcastManager.getInstance(this).sendBroadcast(registrationComplete);
}
private void sendRegistrationToServer(final String token) {
// sending gcm token to server
Log.e(TAG, "sendRegistrationToServer: " + token);
}
private void storeRegIdInPref(String token) {
SharedPreferences pref = getApplicationContext().getSharedPreferences(Config.SHARED_PREF, 0);
SharedPreferences.Editor editor = pref.edit();
editor.putString("regId", token);
editor.commit();
}
}
In your Gradle file all the versions of google-play-service and firebase should all use the same version.
As you are using :
compile 'com.google.firebase:firebase-core:10.0.1'
You should use :
compile 'com.google.firebase:firebase-messaging:10.0.1' // and not 9.4.0
So if you are using google-play-services, please update the version to 10.0.1.

Android HTTP POST not working with PARTIAL WAKE LOCK when the phone screen goes dark

I have a code which has an activity with a button which when clicked starts the accelerometer service .
Accelerometer service Uses PARTIAL_WAKE_LOCK in the onStart() as shown :
#Override
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
super.onStart(intent, startId);
//Power Manager
PowerManager pm = (PowerManager)getApplicationContext().getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MY WK");
wl.acquire();
//Power Manager
try{
mInitialized = false;
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(this, mAccelerometer,SensorManager.SENSOR_DELAY_NORMAL);
}
catch(Exception e)
{
Log.e("acc","catch1");
}
}// end of onStart()
and in the onSensorChange(Sensor event) i have the code which logs the data to remote server using HTTP POSt as shown :
synchronized public void onSensorChanged(SensorEvent event) {
if( event.sensor.getType() == Sensor.TYPE_ACCELEROMETER )
{
//-----------------------------sending it to server---------
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("xaxis", xaxis));
nameValuePairs.add(new BasicNameValuePair("yaxis", yaxis));
nameValuePairs.add(new BasicNameValuePair("zaxis", zaxis));
//------------------
Thread networkThread = new Thread() {
#Override
public void run() {
HttpClient httpclient1 = new DefaultHttpClient();
HttpPost httppost1 = new HttpPost("http://www.xxxxx.com/filename.php");
httppost1.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response1 = httpclient1.execute(httppost1);
}
};
networkThread.start();
//----------------------------------
}//and of if
}//end of onSensorChanged
My problem is :
When the phone screen goes dark ,HTTP stops logging to the server . But when the screen is bright even if the keypad is locked it logs data .
Please help me as i want to make this service run in background and log data to server even when the screen is locked .
So , its working fine till the screen goes dark after which its not logging any data .
Does HTTP not work with Partial_WAKE_Lock.
I searched for the answers but could not find any. Hoping to get some help !
Thank You
Fortunately , i have found an answer in this link Android accelerometer not working when screen is turned off which says that its not the HTTP post not working but when the screen is off no accelerometer values are generated . Thank you

Resources