/*
* VoIP.ms SMS
* Copyright (C) 2015-2016 Michael Kourlas
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.kourlas.voipms_sms.notifications;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.AsyncTask;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.firebase.iid.FirebaseInstanceId;
import net.kourlas.voipms_sms.R;
import net.kourlas.voipms_sms.preferences.CustomSwitchPreference;
import net.kourlas.voipms_sms.preferences.Preferences;
import net.kourlas.voipms_sms.utils.Utils;
import org.json.JSONObject;
import java.net.URLEncoder;
/**
* Handles push notification setup. This includes registering for the VoIP.ms
* callback and Firebase Cloud Messaging.
*/
public class PushNotifications {
private static PushNotifications instance = null;
private final Context applicationContext;
private final Preferences preferences;
/**
* Initializes a new instance of the PushNotifications class.
*
* @param applicationContext The application context.
*/
private PushNotifications(Context applicationContext) {
this.applicationContext = applicationContext;
this.preferences = Preferences.getInstance(applicationContext);
}
/**
* Gets the sole instance of the PushNotifications class. Initializes the
* instance if it does not already exist.
*
* @param applicationContext The application context.
* @return The sole instance of the PushNotifications class.
*/
public static PushNotifications getInstance(Context applicationContext) {
if (instance == null) {
instance = new PushNotifications(applicationContext);
}
return instance;
}
/**
* Enable push notifications by configuring the VoIP.ms URL callback,
* registering for FCM and making the appropriate changes to the
* application preferences.
*
* @param activity The source activity.
*/
public void enablePushNotifications(
final Activity activity,
final CustomSwitchPreference preference)
{
if (preferences.getEmail().equals("")
|| preferences.getPassword().equals("")
|| preferences.getDid().equals(""))
{
Utils.showInfoDialog(activity, applicationContext.getString(
R.string.notifications_callback_username_password_did));
return;
}
registerForVoipCallback(activity, preference);
}
private void registerForVoipCallback(
final Activity activity,
final CustomSwitchPreference preference)
{
final ProgressDialog progressDialog = new ProgressDialog(activity);
progressDialog.setMessage(activity.getString(
R.string.notifications_callback_progress));
progressDialog.setCancelable(false);
progressDialog.show();
new AsyncTask<Boolean, Void, Boolean>() {
@Override
protected Boolean doInBackground(Boolean... params) {
try {
String url =
"https://www.voip.ms/api/v1/rest.php?"
+ "api_username=" + URLEncoder.encode(
preferences.getEmail(), "UTF-8") + "&"
+ "api_password=" + URLEncoder.encode(
preferences.getPassword(), "UTF-8") + "&"
+ "method=setSMS" + "&"
+ "did=" + URLEncoder.encode(preferences.getDid(),
"UTF-8") + "&"
+ "enable=1" + "&"
+ "url_callback_enable=1" + "&"
+ "url_callback=" + URLEncoder.encode(
"http://voipmssms-kourlas.rhcloud.com/"
+ "sms_callback?did={TO}", "UTF-8") + "&"
+ "url_callback_retry=0";
JSONObject result = Utils.getJson(url);
String status = result.optString("status");
return !(status == null || !status.equals("success"));
} catch (Exception ex) {
return false;
}
}
@Override
protected void onPostExecute(Boolean success) {
progressDialog.hide();
DialogInterface.OnClickListener fcmOnClickListener =
(dialog, which) -> registerForFcm(activity, preference,
true, true);
if (!success) {
Utils.showAlertDialog(
activity, null,
applicationContext.getString(
R.string.notifications_callback_fail),
applicationContext.getString(R.string.ok),
fcmOnClickListener, null, null);
} else {
Utils.showAlertDialog(
activity, null,
applicationContext.getString(
R.string.notifications_callback_success),
applicationContext.getString(R.string.ok),
fcmOnClickListener, null, null);
}
}
}.execute();
}
/**
* Registers for Firebase Cloud Messaging. Sends the registration token to
* the application servers.
*
* @param activity The activity that initiated the registration, if any.
* @param preference The switch preference that initiated the
* registration, if any.
* @param showFeedback If true, shows a dialog at the end of the
* registration process indicating the success or
* failure of the process.
* @param force If true, retrieves a new registration token even
* if one is already stored.
*/
public void registerForFcm(
final Activity activity,
final CustomSwitchPreference preference,
final boolean showFeedback,
boolean force)
{
if (!preferences.getPushNotificationsEnabled()) {
return;
}
if (preferences.getDid().equals("")) {
// Do not show an error; this method should never be called
// unless a DID is set
return;
}
if (!checkPlayServices(activity, showFeedback)) {
return;
}
final ProgressDialog progressDialog;
if (showFeedback) {
progressDialog = new ProgressDialog(activity);
progressDialog.setMessage(applicationContext.getString(
R.string.notifications_fcm_progress));
progressDialog.setCancelable(false);
progressDialog.show();
} else {
progressDialog = null;
}
if (preferences.getFcmToken().equals("") || force) {
new AsyncTask<Boolean, Void, Boolean>() {
@Override
protected Boolean doInBackground(Boolean... params) {
try {
String token = FirebaseInstanceId.getInstance()
.getToken();
String registrationBackendUrl =
"https://voipmssms-kourlas.rhcloud.com/register?" +
"did=" + URLEncoder
.encode(preferences.getDid(), "UTF-8") + "&" +
"reg_id=" + URLEncoder.encode(token, "UTF-8");
JSONObject result =
Utils.getJson(registrationBackendUrl);
String status = result.optString("status");
if (status == null || !status.equals("success")) {
return false;
}
preferences.setFcmToken(token);
return true;
} catch (Exception ex) {
return false;
}
}
@Override
protected void onPostExecute(Boolean success) {
if (showFeedback) {
progressDialog.hide();
if (!success) {
Utils.showInfoDialog(activity, applicationContext
.getResources().getString(
R.string.notifications_fcm_fail));
} else {
Utils.showInfoDialog(activity, applicationContext
.getResources().getString(
R.string.notifications_fcm_success));
}
}
if (!success && preference != null) {
preference.setChecked(false);
}
}
}.execute();
} else if (showFeedback) {
Utils.showInfoDialog(activity, applicationContext.getResources()
.getString(
R.string
.notifications_fcm_success));
}
}
/**
* Returns true if Google Play Services is set up properly on the device.
*
* @param activity The activity that initiated the check.
* @param showFeedback If true, shows a dialog at the end of the check
* indicating the success or failure of the
* process.
* @return True if Google Play Services is set up properly on the device.
*/
private boolean checkPlayServices(Activity activity, boolean showFeedback) {
int resultCode = GoogleApiAvailability.getInstance()
.isGooglePlayServicesAvailable(
applicationContext);
if (resultCode != ConnectionResult.SUCCESS) {
if (showFeedback) {
if (GoogleApiAvailability.getInstance()
.isUserResolvableError(resultCode))
{
GoogleApiAvailability.getInstance()
.getErrorDialog(activity, resultCode,
0).show();
} else {
Utils.showInfoDialog(activity,
applicationContext.getResources()
.getString(
R.string
.notifications_fcm_play_services));
}
}
return false;
}
return true;
}
}