Skip to content

Instantly share code, notes, and snippets.

@homanp
Created July 5, 2016 12:38
Show Gist options
  • Save homanp/b50a3ac559d3ffa768c1c325dc0ff36a to your computer and use it in GitHub Desktop.
Save homanp/b50a3ac559d3ffa768c1c325dc0ff36a to your computer and use it in GitHub Desktop.
package com.bitcallproject.RNPlivo;
import com.bitcallproject.MainActivity;
import com.bitcallproject.RNPlivo.ServiceCallbacks;
import java.lang.Exception;
import java.lang.Error;
import java.util.Timer;
import java.util.TimerTask;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import android.os.SystemClock;
import android.app.Service;
import android.os.IBinder;
import android.os.Binder;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.ComponentName;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.util.Log;
import android.view.Window;
import android.view.WindowManager;
import android.app.ActivityManager;
import android.app.ActivityManager.*;
import android.telephony.TelephonyManager;
import android.app.KeyguardManager;
import android.app.KeyguardManager.KeyguardLock;
import android.app.PendingIntent;
import android.app.AlarmManager;
import com.plivo.endpoint.Endpoint;
import com.plivo.endpoint.EventListener;
import com.plivo.endpoint.Incoming;
import com.plivo.endpoint.Outgoing;
import java.lang.*;
public class PlivoService extends Service implements EventListener{
KeyguardLock keyguardLock;
private BroadcastReceiver receiver;
private boolean isAppBinded;
private Endpoint endpoint;
private Outgoing outCall;
private Incoming inCall;
public final static String PLIVO_PASSWORD = "sip_user";
private ServiceCallbacks serviceCallbacks;
private String username;
private static final String ACTION_WAKEUP = "com.bitcallproject.WAKEUP";
private static final String STATUS = "com.bitcallproject.STATUS";
private static final String SLEEP = "com.bitcallproject.SLEEP";
private static final String READY = "com.bitcallproject.READY";
private static final String RELEASE_LOCK = "com.bitcallproject.RELEASE_LOCK";
private static final String KEEP_ALIVE = "com.bitcallproject.KEEP_ALIVE";
private static final String ACTION_LOGIN = "com.bitcallproject.ACTION_LOGIN";
private static final String ACTION_INCOMING_CALL = "com.bitcallproject.ACTION_INCOMING_CALL";
private static final String ACTION_BIND_APP = "com.bitcallproject.ACTION_BIND_APP";
private static final String EVENT_SERVICE_STARTED = "com.bitcallproject.EVENT_SERVICE_STARTED";
private static final String EVENT_END_CALL = "com.bitcallproject.EVENT_END_CALL";
private static final String ACTION_REJECT_CALL = "com.bitcallproject.ACTION_REJECT_CALL";
private static final String EVENT_REJECT_CALL = "com.bitcallproject.EVENT_REJECT_CALL";
private static final String EVENT_HANG_UP = "com.bitcallproject.EVENT_HANG_UP";
private static final String ACTION_HANG_UP = "com.bitcallproject.ACTION_HANG_UP";
private Intent currIntent;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
currIntent = intent;
initService();
username = intent.getStringExtra("username");
Log.v("ReactNativeJS", "Starting service with username = " + username);
if (endpoint != null){
Log.v("ReactNativeJS", "Resettimng endpoint");
endpoint.resetEndpoint();
endpoint = null;
endpoint = Endpoint.newInstance(true, this);
}
login(username);
return START_NOT_STICKY;
//return START_REDELIVER_INTENT;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
public void call(final String number, final String user, final String fromNumber){
TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
String countryCode = tm.getNetworkCountryIso().toUpperCase();
String formatedNumber = formatOutboundNumber(number, getCountryCode(countryCode));
Log.v("ReactNativeJS", "Country code: " + getCountryCode(countryCode));
Log.v("ReactNativeJS", "Formated number: " + formatedNumber);
Map extraArgs = new HashMap();
extraArgs.put("X-PH-User", user);
extraArgs.put("X-PH-Number", fromNumber);
extraArgs.put("X-PH-RawNumber", number.replace("+", ""));
if (endpoint == null){
Log.v("ReactNativeJS", "Endpoint is null");
return;
}
outCall = new Outgoing(endpoint);
outCall = endpoint.createOutgoingCall();
if (outCall == null){
Log.v("ReactNativeJS", "Outgoing call is null");
return;
}
outCall.callH(formatedNumber, extraArgs);
}
private void handleIncomingCall() {
Log.v("ReactNativeJS", "Handling incoming call!!!");
broadcastEvent(KEEP_ALIVE);
int sipLen = "sip:".length();
Intent payload = new Intent();
payload.setAction(ACTION_INCOMING_CALL);
String fromContact = inCall.getFromSip();
Map<String, String> header = inCall.getHeaderDict();
HashMap<String, String> hashHeader = new HashMap<String, String>(header);
payload.putExtra("header", hashHeader);
payload.putExtra("fromContact", fromContact.substring(sipLen, fromContact.length()));
sendBroadcast(payload);
}
/*@Override
public void onCreate()*/public void initService(){
//super.onCreate();
IntentFilter filter = new IntentFilter();
filter.addAction(READY);
filter.addAction(SLEEP);
filter.addAction(ACTION_LOGIN);
filter.addAction(ACTION_BIND_APP);
filter.addAction(ACTION_REJECT_CALL);
filter.addAction(ACTION_HANG_UP);
receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//set true to avoid start app, just wake up
Log.v("ReactNativeJS", "Service intent received: " + intent.getAction() + " incCall = " + Boolean.toString(inCall != null));
if (intent.getAction().equals(ACTION_BIND_APP)) {
isAppBinded = true;
} else if (intent.getAction().equals(READY) && inCall != null) {
handleIncomingCall();
} else if (intent.getAction().equals(SLEEP)) {
broadcastEvent(ACTION_WAKEUP);
//don't login if username from broadcast equals to username from startservice
} /*else if (intent.getAction().equals(ACTION_LOGIN)) {
String currUsername = intent.getStringExtra("username");
if (username != currUsername) {
username = currUsername;
login(username);
}
} */else if (intent.getAction().equals(ACTION_REJECT_CALL)) {
reject();
} else if (intent.getAction().equals(ACTION_HANG_UP)) {
hangup();
}
}
};
registerReceiver(receiver, filter);
broadcastEvent(EVENT_SERVICE_STARTED);
}
@Override
public void onDestroy(){
if (receiver != null) {
unregisterReceiver(receiver);
receiver = null;
}
super.onDestroy();
}
private void launchActivity() {
KeyguardManager keyguardManager = (KeyguardManager)getSystemService(KEYGUARD_SERVICE);
keyguardLock = keyguardManager.newKeyguardLock("TAG");
keyguardLock.disableKeyguard();
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
}
public void login(final String username) {
if (endpoint == null) {
Log.v("ReactNativeJS", "Creating endpoint instance!!!");
try {
endpoint = Endpoint.newInstance(true, this);
}
catch (Exception e) {
e.printStackTrace();
Log.v("ReactNativeJS", "exception" + e.getMessage());
}
}
Log.v("ReactNativeJS", "After reset before login");
try {
endpoint.login(username, PLIVO_PASSWORD);
} catch (Exception e) {
e.printStackTrace();
Log.v("ReactNativeJS", "exception" + e.getMessage());
}
}
public void reject(){
inCall.reject();
broadcastEvent(EVENT_REJECT_CALL);
}
public void hangup(){
outCall.hangup();
broadcastEvent(EVENT_HANG_UP);
}
public void onLogin(){
Log.v("ReactNativeJS", "Logged in");
broadcastEvent(RELEASE_LOCK);
}
public void onLogout() {
}
public void onLoginFailed() {
Log.v("ReactNativeJS", "Failed to login");
}
@Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
endpoint.resetEndpoint();
Log.v("ReactNativeJS", "Application has gone, and never return with rootusername = " + currIntent.getStringExtra("username"));
PendingIntent pintent = PendingIntent.getService(PlivoService.this, 0, currIntent, 0);
AlarmManager alarm = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarm.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 6000, pintent);
}
public void onIncomingCall(Incoming incoming) {
Log.v("ReactNativeJS", "Incoming call has come. isAppBinded = " + Boolean.toString(isAppBinded));
inCall = incoming;
if (isAppBinded == true){
broadcastEvent(STATUS);
} else {
Log.v("ReactNativeJS", "Launching new activity");
launchActivity();
}
}
private void broadcastEvent(final String eventName){
Intent i = new Intent();
i.setAction(eventName);
sendBroadcast(i);
Log.v("ReactNativeJS", "Service intent sent: " + i.getAction());
}
public void onIncomingCallHangup(Incoming incoming) {
broadcastEvent(EVENT_HANG_UP);
}
public void onIncomingCallRejected(Incoming incoming) {
broadcastEvent(EVENT_REJECT_CALL);
}
public void onOutgoingCall(Outgoing outgoing) {
broadcastEvent(KEEP_ALIVE);
}
public void onOutgoingCallAnswered(Outgoing outgoing) {
}
public void onOutgoingCallHangup(Outgoing outgoing) {
Log.v("ReactNativeJS", "Trigger onOutgoingCallHangup");
broadcastEvent(RELEASE_LOCK);
}
public void onOutgoingCallRejected(Outgoing outgoing) {
Log.v("ReactNativeJS", "Trigger onOutgoingCallRejected");
broadcastEvent(RELEASE_LOCK);
}
public void onOutgoingCallInvalid(Outgoing outgoing) {
Log.v("ReactNativeJS", "Trigger onOutgoingCallInvalid");
broadcastEvent(RELEASE_LOCK);
}
private String getCountryCode(String countryCode){
Map<String, String> countryCodes = new HashMap<String, String>() {{
put("IL", "972"); put("AF", "93"); put("AL", "355"); put("DZ", "213"); put("AS", "1");
put("AD", "376"); put("AO", "244"); put("AI", "1"); put("AG", "1"); put("AR", "54");
put("AM", "374"); put("AW", "297"); put("AU", "61"); put("AT", "43"); put("AZ", "994");
put("BS", "1"); put("BH", "973"); put("BD", "880"); put("BB", "1"); put("BY", "375");
put("BE", "32"); put("BZ", "501"); put("BJ", "229"); put("BM", "1"); put("BT", "975");
put("BA", "387"); put("BW", "267"); put("BR", "55"); put("IO", "246"); put("BG", "359");
put("BF", "226"); put("BI", "257"); put("KH", "855"); put("CM", "237"); put("CA", "1");
put("CV", "238"); put("KY", "345"); put("CF", "236"); put("TD", "235"); put("CL", "56");
put("CN", "86"); put("CX", "61"); put("CO", "57"); put("KM", "269"); put("CG", "242");
put("CK", "682"); put("CR", "506"); put("HR", "385"); put("CU", "53"); put("CY", "537");
put("CZ", "420"); put("DK", "45"); put("DJ", "253"); put("DM", "1"); put("DO", "1");
put("EC", "593"); put("EG", "20"); put("SV", "503"); put("GQ", "240"); put("ER", "291");
put("EE", "372"); put("ET", "251"); put("FO", "298"); put("FJ", "679"); put("FI", "358");
put("FR", "33"); put("GF", "594"); put("PF", "689"); put("GA", "241"); put("GM", "220");
put("GE", "995"); put("DE", "49"); put("GH", "233"); put("GI", "350"); put("GR", "30");
put("GL", "299"); put("GD", "1"); put("GP", "590"); put("GU", "1"); put("GT", "502");
put("GN", "224"); put("GW", "245"); put("GY", "595"); put("HT", "509"); put("HN", "504");
put("HU", "36"); put("IS", "354"); put("IN", "91"); put("ID", "62"); put("IQ", "964");
put("IE", "353"); put("IL", "972"); put("IT", "39"); put("JM", "1"); put("JP", "81");
put("JO", "962"); put("KZ", "77"); put("KE", "254"); put("KI", "686"); put("KW", "965");
put("KG", "996"); put("LV", "371"); put("LB", "961"); put("LS", "266"); put("LR", "231");
put("LI", "423"); put("LT", "370"); put("LU", "352"); put("MG", "261"); put("MW", "265");
put("MY", "60"); put("MV", "960"); put("ML", "223"); put("MT", "356"); put("MH", "692");
put("MQ", "596"); put("MR", "222"); put("MU", "230"); put("YT", "262"); put("MX", "52");
put("MC", "377"); put("MN", "976"); put("ME", "382"); put("MS", "1"); put("MA", "212");
put("MM", "95"); put("NA", "264"); put("NR", "674"); put("NP", "977"); put("NL", "31");
put("AN", "599"); put("NC", "687"); put("NZ", "64"); put("NI", "505"); put("NE", "227");
put("NG", "234"); put("NU", "683"); put("NF", "672"); put("MP", "1"); put("NO", "47");
put("OM", "968"); put("PK", "92"); put("PW", "680"); put("PA", "507"); put("PG", "675");
put("PY", "595"); put("PE", "51"); put("PH", "63"); put("PL", "48"); put("PT", "351");
put("PR", "1"); put("QA", "974"); put("RO", "40"); put("RW", "250"); put("WS", "685");
put("SM", "378"); put("SA", "966"); put("SN", "221"); put("RS", "381"); put("SC", "248");
put("SL", "232"); put("SG", "65"); put("SK", "421"); put("SI", "386"); put("SB", "677");
put("ZA", "27"); put("GS", "500"); put("ES", "34"); put("LK", "94"); put("SD", "249");
put("SR", "597"); put("SZ", "268"); put("SE", "46"); put("CH", "41"); put("TJ", "992");
put("TH", "66"); put("TG", "228"); put("TK", "690"); put("TO", "676"); put("TT", "1");
put("TN", "216"); put("TR", "90"); put("TM", "993"); put("TC", "1"); put("TV", "688");
put("UG", "256"); put("UA", "380"); put("AE", "971"); put("GB", "44"); put("US", "1");
put("UY", "598"); put("UZ", "998"); put("VU", "678"); put("WF", "681"); put("YE", "967");
put("ZM", "260"); put("ZW", "263"); put("BO", "591"); put("BN", "673"); put("CC", "61");
put("CD", "243"); put("CI", "225"); put("FK", "500"); put("GG", "44"); put("VA", "379");
put("HK", "852"); put("IR", "98"); put("IM", "44"); put("JE", "44"); put("KP", "850");
put("KR", "82"); put("LA", "856"); put("LY", "218"); put("MO", "853"); put("MK", "389");
put("FM", "691"); put("MD", "373"); put("MZ", "258"); put("PS", "970"); put("PN", "872");
put("RE", "262"); put("RU", "7"); put("BL", "590"); put("SH", "290"); put("KN", "1");
put("LC", "1"); put("MF", "590"); put("PM", "508"); put("VC", "1"); put("ST", "239");
put("SO", "252"); put("SJ", "47"); put("SY", "963"); put("TW", "886"); put("TZ", "255");
put("TL", "670"); put("VE", "58"); put("VN", "84"); put("VG", "1"); put("VI", "1");
}};
return countryCodes.get(countryCode);
}
private String formatOutboundNumber(String number, String countryCode){
String cleanNumber = number.replaceAll("[^A-Za-z0-9]", "");
int len = cleanNumber.length();
if (cleanNumber.startsWith("00")){
return "+" + countryCode + cleanNumber.substring(2, len);
}
if (cleanNumber.startsWith("0")){
return "+" + countryCode + cleanNumber.substring(1, len);
}
return "+" + cleanNumber;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment