/* * * Copyright (C) 2018 Ander Nieva Anza * Copyright (C) 2018, University of the Basque Country (UPV/EHU) * * Contact for licensing options: <licensing-mcpttclient(at)mcopenplatform(dot)com> * * This file is part of MCOP MCPTT Client * * This is free software: you can redistribute it and/or modify it under the terms of * the GNU General Public License as published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. * * This is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.test.client.mcopclient; import android.Manifest; import android.annotation.TargetApi; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.PackageManager; import android.media.AudioManager; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.provider.Settings; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.SwitchCompat; import android.telephony.TelephonyManager; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.CompoundButton; import android.widget.Spinner; import android.widget.TextView; import org.mcopenplatform.muoapi.IMCOPCallback; import org.mcopenplatform.muoapi.IMCOPsdk; import org.test.client.mcopclient.datatype.UserData; import org.test.client.mcopclient.preference.PreferencesManagerDefault; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; public class MainActivity extends AppCompatActivity { private final static String TAG = MainActivity.class.getCanonicalName(); private ServiceConnection mConnection; private IMCOPsdk mService; private IMCOPCallback mMCOPCallback; private boolean isConnect=false; private static final int ERROR_CODE_DEFAULT=-1; private static final int AUTHETICATION_RESULT=101; private static final int GET_PERMISSION = 102; private static final boolean VALUE_BOOLEAN_DEFAULT=false; private static UserData userData; private static final int DEFAULT_REGISTER_DELAY = 4000; private static final String ACTION_BUTTON_PTT_DOWN_BITTIUM="com.elektrobit.pttbutton.PTTBUTTON_DOWN"; private static final String ACTION_BUTTON_PTT_UP_BITTIUM="com.elektrobit.pttbutton.PTTBUTTON_UP"; private static final String ACTION_BUTTON_PTT_LONG_PRESS_BITTIUM="com.elektrobit.pttbutton.PTTBUTTON_LONG_PRESS"; private BroadcastReceiver mButtonPTTBroadCastRecvMCPTT; private Button btn_register; private Button btn_unregister; private TextView text_info; private TextView text_error; private TextView text_affiliation; private TextView text_status; private Button btn_hangup; private DialogMenu mDialogIds; private Button btn_accept; private Button reg_status; private Button btn_call; private Button btn_speaker; private Button btn_aux2; private TextView text_talking; private TextView text_callingid; private TextView switch_private; private TextView switch_group; private PreferencesManagerDefault preferencesManager; private static final String PARAMETER_PROFILE = "parameters"; private static final String PARAMETER_SAVE_PROFILE = TAG+".PARAMETER_SAVE_PROFILE"; private Map<String, String> clients; private DialogMenu mDialogMenu; private String currentProfile; private SwitchCompat switchCompat; private Spinner spinnerGroups; private Spinner spinnerUsers; private Boolean isSpeakerphoneOn; private ArrayList<String> groupsCurrent; private Intent serviceIntent; private enum State { GRANTED, IDLE, TAKEN, NONE } private State mState = State.NONE; private enum CallType { PRIVATE, GROUP } private CallType mCallType = CallType.GROUP; private String selGroup = "sip:groupA@organization.org"; private String selUser = "sip:mcptt_id_clientA@organization.org"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); setPermissions(); btn_register=(Button)findViewById(R.id.btn_register); btn_unregister=(Button)findViewById(R.id.btn_unregister); text_info=(TextView)findViewById(R.id.text_info); text_error=(TextView)findViewById(R.id.text_error); text_affiliation=(TextView)findViewById(R.id.text_affiliation); text_status=(TextView)findViewById(R.id.text_status); btn_hangup=(Button)findViewById(R.id.btn_hangup); btn_accept=(Button)findViewById(R.id.btn_accept); reg_status=(Button)findViewById(R.id.reg_status); btn_call=(Button)findViewById(R.id.btn_call); btn_speaker=(Button)findViewById(R.id.btn_speaker); btn_aux2=(Button)findViewById(R.id.btn_aux2); text_talking=(TextView)findViewById(R.id.text_talking); text_callingid=(TextView)findViewById(R.id.text_callingid); switch_private=(TextView)findViewById(R.id.switch_private); switch_group=(TextView)findViewById(R.id.switch_group); switchCompat=(SwitchCompat)findViewById(R.id.switch_call); spinnerGroups=(Spinner)findViewById(R.id.spinnerGroups); spinnerUsers=(Spinner)findViewById(R.id.spinnerUsers); btn_unregister.setEnabled(false); btn_call.setEnabled(false); btn_call.setBackgroundResource(R.drawable.token_inactive); btn_register.setEnabled(false); btn_accept.setEnabled(false); btn_hangup.setEnabled(false); reg_status.setEnabled(false); btn_speaker.setEnabled(false); btn_aux2.setEnabled(false); text_talking.setVisibility((View.INVISIBLE)); text_callingid.setVisibility((View.INVISIBLE)); switchCompat.setEnabled(false); switch_group.setTextColor(ContextCompat.getColor(this, R.color.background)); switch_private.setTextColor(ContextCompat.getColor(this, R.color.background)); spinnerGroups.setEnabled(false); spinnerGroups.setAdapter(null); spinnerUsers.setEnabled(false); spinnerUsers.setAdapter(null); spinnerUsers.setVisibility((View.GONE)); spinnerGroups.setVisibility((View.VISIBLE)); isSpeakerphoneOn = false; AudioManager mAudioManager; mAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE); mAudioManager.setSpeakerphoneOn(isSpeakerphoneOn); //Dissable logging messages. Enable just for debugging text_info.setVisibility((View.GONE)); text_error.setVisibility((View.GONE)); text_affiliation.setVisibility((View.GONE)); preferencesManager=new PreferencesManagerDefault(); clients = new HashMap<>(); if(clients==null || clients.isEmpty()){ clients.put("TESTA", "TESTA"); clients.put("TESTB", "TESTB"); clients.put("TESTC", "TESTC"); clients.put("TESTD", "TESTD"); clients.put("TESTE", "TESTE"); } List<String> usersCurrent = new ArrayList<String>(); if(usersCurrent.isEmpty()){ usersCurrent.add("sip:mcptt_id_test_A@organization.org"); usersCurrent.add("sip:mcptt_id_test_B@organization.org"); usersCurrent.add("sip:mcptt_id_test_C@organization.org"); usersCurrent.add("sip:mcptt_id_test_D@organization.org"); usersCurrent.add("sip:mcptt_id_test_E@organization.org"); } //Group list groupsCurrent = new ArrayList<String>(); groupsCurrent.add("sip:tets_group@organization.org"); groupsCurrent.add("sip:groupTest2@organization.org"); //Adapter por User Spinner ArrayAdapter<String> userAdaptor = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_spinner_item, usersCurrent); // Drop down layout style - list view with radio button userAdaptor.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinnerUsers.setAdapter(userAdaptor); loadGroups(); ArrayList<String> strings=getIntent().getStringArrayListExtra(PARAMETER_PROFILE); Map<String, String> parameterClients= getProfilesParameters(strings); if(parameterClients!=null && !parameterClients.isEmpty()) clients=parameterClients; if(userData==null); userData=new UserData(); mMCOPCallback=new IMCOPCallback.Stub() { @Override public void handleOnEvent(final List<Intent> actionList) throws RemoteException { runOnUiThread(new Runnable() { @Override public void run() { for(Intent action:actionList){ int codeError=-1; int eventTypeInt=-1; String stringError=null; String sessionID=null; if(action!=null && action.getAction()!=null && !action.getAction().trim().isEmpty()) try { switch (ConstantsMCOP.ActionsCallBack.fromString(action.getAction())){ case none: break; case authorizationRequestEvent: codeError=-1; if((codeError=action.getIntExtra(ConstantsMCOP.AuthorizationRequestExtras.ERROR_CODE,ERROR_CODE_DEFAULT))!=ERROR_CODE_DEFAULT){ //Error in authorizationRequestEvent stringError=action.getStringExtra(ConstantsMCOP.AuthorizationRequestExtras.ERROR_STRING); showLastError("authorizationRequestEvent",codeError,stringError); }else { //No error String requestUri=null; String redirect=null; if((requestUri=action.getStringExtra(ConstantsMCOP.AuthorizationRequestExtras.REQUEST_URI))!=null && (redirect=action.getStringExtra(ConstantsMCOP.AuthorizationRequestExtras.REDIRECT_URI))!=null ){ if(BuildConfig.DEBUG)Log.d(TAG,"onAuthentication URI: "+requestUri+ " redirectionURI: "+redirect); } } break; case loginEvent: codeError=-1; if((codeError=action.getIntExtra(ConstantsMCOP.LoginEventExtras.ERROR_CODE,ERROR_CODE_DEFAULT))!=ERROR_CODE_DEFAULT){ //Error in LoginEvent stringError=action.getStringExtra(ConstantsMCOP.LoginEventExtras.ERROR_STRING); showLastError("LoginEvent",codeError,stringError); }else { //No error boolean success=false; String mcptt_id=null; String displayName=null; if((success=action.getBooleanExtra(ConstantsMCOP.LoginEventExtras.SUCCESS,VALUE_BOOLEAN_DEFAULT))==true && (mcptt_id=action.getStringExtra(ConstantsMCOP.LoginEventExtras.MCPTT_ID))!=null ){ if(BuildConfig.DEBUG)Log.d(TAG,"Login success: "+success+ " mcptt_id: "+mcptt_id); displayName=action.getStringExtra(ConstantsMCOP.LoginEventExtras.DISPLAY_NAME); isRegisted(success,mcptt_id,displayName); }else{ Log.e(TAG,"Error: Registration process"); } } break; case unLoginEvent: codeError=-1; if((codeError=action.getIntExtra(ConstantsMCOP.UnLoginEventExtras.ERROR_CODE,ERROR_CODE_DEFAULT))!=ERROR_CODE_DEFAULT){ //Error in unLoginEvent stringError=action.getStringExtra(ConstantsMCOP.UnLoginEventExtras.ERROR_STRING); showLastError("unLoginEvent",codeError,stringError); }else { //No error boolean success=false; if((success=action.getBooleanExtra(ConstantsMCOP.UnLoginEventExtras.SUCCESS,VALUE_BOOLEAN_DEFAULT))==true){ unRegisted(success); }else{ Log.e(TAG,"Error: Unregistration process"); } } break; case configurationUpdateEvent: break; case callEvent: codeError=-1; eventTypeInt=action.getIntExtra(ConstantsMCOP.CallEventExtras.EVENT_TYPE,ERROR_CODE_DEFAULT); ConstantsMCOP.CallEventExtras.CallEventEventTypeEnum eventTypeCall=null; if(eventTypeInt!=ERROR_CODE_DEFAULT && (eventTypeCall=ConstantsMCOP.CallEventExtras.CallEventEventTypeEnum.fromInt(eventTypeInt))!=null ){ switch (eventTypeCall) { case NONE: break; case INCOMING: Log.e(TAG,"STATE: INCOMING"); stringError=action.getStringExtra(ConstantsMCOP.CallEventExtras.ERROR_STRING); sessionID=action.getStringExtra(ConstantsMCOP.CallEventExtras.SESSION_ID); String callerID=action.getStringExtra(ConstantsMCOP.CallEventExtras.CALLER_USERID); if(sessionID!=null)userData.addSessionID(sessionID); showData("callEvent ("+sessionID+")","INCOMING "+"-> "+callerID); text_talking.setVisibility((View.VISIBLE)); text_callingid.setVisibility((View.VISIBLE)); text_callingid.setText(callerID); spinnerGroups.setEnabled(false); spinnerUsers.setEnabled(false); switchCompat.setEnabled(false); showIdsAcceptCall(getApplicationContext(), sessionID); break; case RINGING: Log.e(TAG,"STATE: RINGING"); sessionID=action.getStringExtra(ConstantsMCOP.CallEventExtras.SESSION_ID); spinnerGroups.setEnabled(false); spinnerUsers.setEnabled(false); switchCompat.setEnabled(false); showData("callEvent ("+sessionID+")","RINGING"); if(sessionID!=null)userData.addSessionID(sessionID); break; case INPROGRESS: Log.e(TAG,"STATE: INPROGRESS"); sessionID=action.getStringExtra(ConstantsMCOP.CallEventExtras.SESSION_ID); spinnerGroups.setEnabled(false); spinnerUsers.setEnabled(false); switchCompat.setEnabled(false); showData("callEvent ("+sessionID+")","INPROGRESS"); if(sessionID!=null)userData.addSessionID(sessionID); break; case CONNECTED: Log.e(TAG,"STATE: CONNECTED"); sessionID=action.getStringExtra(ConstantsMCOP.CallEventExtras.SESSION_ID); showData("callEvent ("+sessionID+")","CONNECTED"); break; case TERMINATED: Log.e(TAG,"STATE: TERMINATED"); sessionID=action.getStringExtra(ConstantsMCOP.CallEventExtras.SESSION_ID); spinnerGroups.setEnabled(true); spinnerUsers.setEnabled(true); switchCompat.setEnabled(true); switch_group.setTextColor(ContextCompat.getColor(getBaseContext(), R.color.white)); switch_private.setTextColor(ContextCompat.getColor(getBaseContext(), R.color.white)); showData("callEvent ("+sessionID+")","TERMINATED"); if(sessionID!=null)userData.removeSessionID(sessionID); btn_call.setBackgroundResource(R.drawable.token_default); mState = State.NONE; btn_call.setEnabled(true); btn_hangup.setEnabled(false); text_talking.setVisibility((View.INVISIBLE)); text_callingid.setVisibility((View.INVISIBLE)); break; case ERROR: Log.e(TAG,"STATE: ERROR"); if((codeError=action.getIntExtra(ConstantsMCOP.CallEventExtras.ERROR_CODE,ERROR_CODE_DEFAULT))!=ERROR_CODE_DEFAULT){ //Error in callEvent stringError=action.getStringExtra(ConstantsMCOP.CallEventExtras.ERROR_STRING); sessionID=action.getStringExtra(ConstantsMCOP.CallEventExtras.SESSION_ID); showLastError("callEvent ("+sessionID+")",codeError,stringError); } if(sessionID!=null)userData.addSessionID(sessionID); break; case UPDATE: Log.e(TAG,"STATE: UPDATE"); sessionID=action.getStringExtra(ConstantsMCOP.CallEventExtras.SESSION_ID); int updateCallType=action.getIntExtra(ConstantsMCOP.CallEventExtras.CALL_TYPE,ERROR_CODE_DEFAULT); showData("callEvent ("+sessionID+")","UPDATE "+"-> CallType: "+updateCallType); if(sessionID!=null)userData.addSessionID(sessionID); break; default: showLastError("callEvent:",999,"RECEIVE EVENT NO VALID"); break; } }else{ showLastError("callEvent:",999,"RECEIVE EVENT NO VALID"); } break; case floorControlEvent: codeError=-1; if((codeError=action.getIntExtra(ConstantsMCOP.FloorControlEventExtras.ERROR_CODE,ERROR_CODE_DEFAULT))!=ERROR_CODE_DEFAULT){ //Error in unLoginEvent sessionID=action.getStringExtra(ConstantsMCOP.FloorControlEventExtras.SESSION_ID); stringError=action.getStringExtra(ConstantsMCOP.UnLoginEventExtras.ERROR_STRING); showLastError("floorControlEvent("+sessionID+")",codeError,stringError); }else { //No error boolean success=false; String eventFloorControl=action.getStringExtra(ConstantsMCOP.FloorControlEventExtras.FLOOR_CONTROL_EVENT); String causeString=null; int causeInt=-1; try{ sessionID=action.getStringExtra(ConstantsMCOP.CallEventExtras.SESSION_ID); switch (ConstantsMCOP.FloorControlEventExtras.FloorControlEventTypeEnum.fromString(eventFloorControl)) { case none: break; case granted: Log.e(TAG,"TOKEN GRANTED"); int durationGranted=action.getIntExtra(ConstantsMCOP.FloorControlEventExtras.DURATION_TOKEN,ERROR_CODE_DEFAULT); showData("floorControl ("+sessionID+")"," granted "+"-> Duration: "+durationGranted); btn_call.setBackgroundResource(R.drawable.token_green); mState = State.GRANTED; btn_call.setEnabled(true); btn_hangup.setEnabled(true); break; case idle: Log.e(TAG,"TOKEN IDLE"); showData("floorControl ("+sessionID+")"," idle"); btn_call.setBackgroundResource(R.drawable.token_gray); mState = State.IDLE; btn_call.setEnabled(true); btn_hangup.setEnabled(true); text_talking.setVisibility((View.INVISIBLE)); text_callingid.setVisibility((View.INVISIBLE)); break; case taken: Log.e(TAG,"TOKEN TAKEN"); String userIDTaken=action.getStringExtra(ConstantsMCOP.FloorControlEventExtras.USER_ID); String displayNameTaken=action.getStringExtra(ConstantsMCOP.FloorControlEventExtras.DISPLAY_NAME); boolean allow_request=action.getBooleanExtra(ConstantsMCOP.FloorControlEventExtras.ALLOW_REQUEST,VALUE_BOOLEAN_DEFAULT); showData("floorControl ("+sessionID+")"," granted "+"-> userIDTaken(allowRequest="+allow_request+"):("+userIDTaken+":"+displayNameTaken+")"); mState = State.TAKEN; btn_call.setEnabled(false); btn_hangup.setEnabled(true); btn_call.setBackgroundResource(R.drawable.token_red); text_talking.setVisibility((View.VISIBLE)); text_callingid.setVisibility((View.VISIBLE)); text_callingid.setText(userIDTaken); break; case denied: Log.e(TAG,"TOKEN DENIED"); causeString=action.getStringExtra(ConstantsMCOP.FloorControlEventExtras.CAUSE_STRING); causeInt=action.getIntExtra(ConstantsMCOP.FloorControlEventExtras.CAUSE_CODE,ERROR_CODE_DEFAULT); showData("floorControl ("+sessionID+")"," denied "+"-> cause("+causeInt+":"+causeString+")"); break; case revoked: Log.e(TAG,"TOKEN REVOKED"); causeString=action.getStringExtra(ConstantsMCOP.FloorControlEventExtras.CAUSE_STRING); causeInt=action.getIntExtra(ConstantsMCOP.FloorControlEventExtras.CAUSE_CODE,ERROR_CODE_DEFAULT); showData("floorControl ("+sessionID+")"," revoked "+"-> cause("+causeInt+":"+causeString+")"); break; default: break; } }catch (Exception e){ } } break; case groupInfoEvent: break; case groupAffiliationEvent: codeError=-1; eventTypeInt=action.getIntExtra(ConstantsMCOP.GroupAffiliationEventExtras.EVENT_TYPE,ERROR_CODE_DEFAULT); ConstantsMCOP.GroupAffiliationEventExtras.GroupAffiliationEventTypeEnum eventTypeAffiliation=null; if(eventTypeInt!=ERROR_CODE_DEFAULT && (eventTypeAffiliation=ConstantsMCOP.GroupAffiliationEventExtras.GroupAffiliationEventTypeEnum.fromInt(eventTypeInt))!=null ){ switch (eventTypeAffiliation) { case GROUP_AFFILIATION_UPDATE: Map<String, Integer> groups=(HashMap<String, Integer>)action.getSerializableExtra(ConstantsMCOP.GroupAffiliationEventExtras.GROUPS_LIST); if(groups!=null) showGroups(groups); break; case GROUP_AFFILIATION_ERROR: if((codeError=action.getIntExtra(ConstantsMCOP.GroupAffiliationEventExtras.ERROR_CODE,ERROR_CODE_DEFAULT))!=ERROR_CODE_DEFAULT){ //Error in unLoginEvent stringError=action.getStringExtra(ConstantsMCOP.GroupAffiliationEventExtras.ERROR_STRING); String groupID=action.getStringExtra(ConstantsMCOP.GroupAffiliationEventExtras.GROUP_ID); showLastError("groupAffiliationEvent ("+groupID+")",codeError,stringError); } break; case REMOTE_AFFILIATION: break; default: showLastError("groupAffiliationEvent:",999,"INVALID RECEIVE EVENT"); break; } }else{ showLastError("groupAffiliationEvent:",999,"INVALID RECEIVE EVENT"); } break; case selectedContactChangeEvent: break; case eMBMSNotificationEvent: break; } }catch (Exception ex){ Log.e(TAG,"Event Action Error: "+action.getAction()+" error:"+ex.getMessage()); } } } }); } }; btn_register.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //test try { if(mService!=null) mService.authorizeUser(null); } catch (RemoteException e) { e.printStackTrace(); } /*try { if(mService!=null) mService.loginMCOP(); } catch (RemoteException e) { e.printStackTrace(); }*/ } }); btn_unregister.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { try { if(mService!=null) mService.unLoginMCOP(); } catch (RemoteException e) { e.printStackTrace(); } } }); btn_hangup.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { showIds(getApplicationContext()); } }); btn_accept.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //Auto-accept used //showIdsAcceptCall(getApplicationContext()); } }); btn_speaker.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { AudioManager mAudioManager; mAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE); if(isSpeakerphoneOn){ isSpeakerphoneOn=false; Log.d(TAG, "Speaker false"); btn_speaker.setText(R.string.btn_speaker_off); }else{ isSpeakerphoneOn=true; Log.d(TAG, "Speaker true"); btn_speaker.setText(R.string.btn_speaker_on); } mAudioManager.setSpeakerphoneOn(isSpeakerphoneOn); } }); switchCompat.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if(isChecked){ // Switch is on. Private Call mCallType = CallType.PRIVATE; //Toast.makeText(getBaseContext(), "Selected: " + mCallType, Toast.LENGTH_SHORT).show(); spinnerGroups.setVisibility((View.GONE)); spinnerUsers.setVisibility((View.VISIBLE)); spinnerGroups.setEnabled(false); spinnerUsers.setEnabled(true); } else { // Switch is off. Group Call mCallType = CallType.GROUP; //Toast.makeText(getBaseContext(), "Selected: " + mCallType, Toast.LENGTH_SHORT).show(); spinnerUsers.setVisibility((View.GONE)); spinnerGroups.setVisibility((View.VISIBLE)); spinnerUsers.setEnabled(false); spinnerGroups.setEnabled(true); } } }); spinnerUsers.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { selUser = parent.getItemAtPosition(position).toString(); //Toast.makeText(parent.getContext(), "Selected: " + selUser, Toast.LENGTH_LONG).show(); } @Override public void onNothingSelected(AdapterView<?> parent) { } }); spinnerGroups.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { selGroup = parent.getItemAtPosition(position).toString(); //Toast.makeText(parent.getContext(), "Selected: " + selGroup, Toast.LENGTH_LONG).show(); } @Override public void onNothingSelected(AdapterView<?> parent) { } }); btn_call.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if(mState != State.NONE && event.getAction() == MotionEvent.ACTION_DOWN) { if (mState == State.IDLE) { //Request token Log.e(TAG,"TOKEN REQUEST"); showIdsOperationFloorControl(getApplicationContext(), true); } }else if (mState != State.NONE && event.getAction() == MotionEvent.ACTION_UP) { if (mState == State.GRANTED) { //Release token Log.e(TAG,"TOKEN RELEASE"); showIdsOperationFloorControl(getApplicationContext(),false); } } else if (event.getAction() == MotionEvent.ACTION_DOWN){ makeCall(); } return true; } }); //PTT button on Bittium Devices mButtonPTTBroadCastRecvMCPTT=new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Log.d(TAG,"PTT button"); final String action = intent.getAction(); if(action.compareTo(ACTION_BUTTON_PTT_DOWN_BITTIUM)==0 ){ Log.d(TAG,"PTT button Down"); if(mState==State.IDLE && !showIdsOperationFloorControl(getApplicationContext(), true)){ Log.e(TAG,"Error: the device can´t request the Token now"); }else if(mState==null || mState==State.NONE){ makeCall(); } }else if(action.compareTo(ACTION_BUTTON_PTT_UP_BITTIUM)==0 && mState==State.GRANTED){ Log.d(TAG,"PTT button Up"); if(!showIdsOperationFloorControl(getApplicationContext(), false)){ Log.e(TAG,"Error: the device can´t release the Token now"); } }else if(action.compareTo(ACTION_BUTTON_PTT_LONG_PRESS_BITTIUM)==0){ Log.d(TAG,"Long PTT button press"); } } }; final IntentFilter intentFilter2 = new IntentFilter(); intentFilter2.addAction(ACTION_BUTTON_PTT_DOWN_BITTIUM); intentFilter2.addAction(ACTION_BUTTON_PTT_UP_BITTIUM); intentFilter2.addAction(ACTION_BUTTON_PTT_LONG_PRESS_BITTIUM); if(mConnection==null) mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { Log.e(TAG,"Service binded! "+className.getPackageName()+"\n"); mService = IMCOPsdk.Stub.asInterface(service); try { Log.d(TAG,"execute "+"registerCallback"+mMCOPCallback); mService.registerCallback(mMCOPCallback); } catch (RemoteException e) { e.printStackTrace(); } isConnect=true; //AUTO Register final Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { try { if(mService!=null) mService.authorizeUser(null); } catch (RemoteException e) { e.printStackTrace(); } } }, DEFAULT_REGISTER_DELAY); } @Override public void onServiceDisconnected(ComponentName className) { mService = null; // This method is only invoked when the service quits from the other end or gets killed // Invoking exit() from the AIDL interface makes the Service kill itself, thus invoking this. Log.e(TAG,"Service disconnected.\n"); isConnect=false; } }; if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) { TelephonyManager tm = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE); if(tm!=null) { String imei = tm.getDeviceId(); String client=clients.get(imei); if(client!=null){ this.currentProfile=client; Log.i(TAG,"currentProfile: " +currentProfile); connectService(currentProfile); }else{ showOptionsProfiles(clients, this); } } }else{ showOptionsProfiles(clients, this); } } private void loadGroups(){ //Adapter por Group Spinner ArrayAdapter<String> groupAdaptor = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_spinner_item, groupsCurrent); // Drop down layout style - list view with radio button groupAdaptor.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinnerGroups.setAdapter(groupAdaptor); } private void makeCall(){ if (mCallType == CallType.GROUP) { //Group Call try { Log.e(TAG,"Call type: "+mCallType); if(mService!=null) mService.makeCall( selGroup, //DEFAULT_GROUP, ConstantsMCOP.CallEventExtras.CallTypeEnum.Audio.getValue() | ConstantsMCOP.CallEventExtras.CallTypeEnum.WithFloorCtrl.getValue() | ConstantsMCOP.CallEventExtras.CallTypeEnum.PrearrangedGroup.getValue() ); } catch (RemoteException e) { e.printStackTrace(); } } else if (mCallType == CallType.PRIVATE) { //Private Call try { Log.e(TAG,"Call type: "+mCallType); if(mService!=null) mService.makeCall( selUser, //DEFAULT_PRIVATE_CALL, ConstantsMCOP.CallEventExtras.CallTypeEnum.Audio.getValue() | ConstantsMCOP.CallEventExtras.CallTypeEnum.WithFloorCtrl.getValue() | ConstantsMCOP.CallEventExtras.CallTypeEnum.Private.getValue() ); } catch (RemoteException e) { e.printStackTrace(); } } btn_hangup.setEnabled(true); } private void showIds(final Context context){ if(userData.getSessionIDs()==null)return; final String[] strings=userData.getSessionIDs().toArray(new String[userData.getSessionIDs().size()]); if(strings==null || strings.length==0)return; if(strings.length==1) { try { if (mService != null) mService.hangUpCall(strings[0]); } catch (RemoteException e) { e.printStackTrace(); } } else { mDialogIds = DialogMenu.newInstance(strings, null); mDialogIds.setOnClickItemListener(new DialogMenu.OnClickListener() { @Override public void onClickItem(int item) { if (item >= 0 && strings.length > item) { try { if (mService != null) mService.hangUpCall(strings[item]); } catch (RemoteException e) { e.printStackTrace(); } } } }); mDialogIds.show(getSupportFragmentManager(), "SimpleDialog"); } } private boolean showIdsOperationFloorControl(final Context context, final boolean request){ Log.i(TAG,"Send floor control operation : "+((request)?"request":"release")); if(userData.getSessionIDs()==null)return false; final String[] strings=userData.getSessionIDs().toArray(new String[userData.getSessionIDs().size()]); if(strings==null || strings.length==0)return false; if(strings.length==1) { try { if (mService != null){ mService.floorControlOperation( strings[0], request ? ConstantsMCOP.FloorControlEventExtras.FloorControlOperationTypeEnum.MCPTT_Request.getValue() : ConstantsMCOP.FloorControlEventExtras.FloorControlOperationTypeEnum.MCPTT_Release.getValue(), null); } Log.i(TAG,"Send floor control operation 2: "+((request)?"request":"release")); } catch (RemoteException e) { e.printStackTrace(); } } else { mDialogIds = DialogMenu.newInstance(strings, null); mDialogIds.setOnClickItemListener(new DialogMenu.OnClickListener() { @Override public void onClickItem(int item) { if (item >= 0 && strings.length > item) { try { if (mService != null){ mService.floorControlOperation( strings[item], request ? ConstantsMCOP.FloorControlEventExtras.FloorControlOperationTypeEnum.MCPTT_Request.getValue() : ConstantsMCOP.FloorControlEventExtras.FloorControlOperationTypeEnum.MCPTT_Release.getValue(), null); Log.i(TAG,"Send floor control operation 3: "+((request)?"request":"release")); } } catch (RemoteException e) { e.printStackTrace(); } } } }); mDialogIds.show(getSupportFragmentManager(), "SimpleDialog"); } return true; } private void showIdsAcceptCall(final Context context, String sessionID){ if(userData.getSessionIDs()==null)return; final String[] strings=userData.getSessionIDs().toArray(new String[userData.getSessionIDs().size()]); if(strings==null)return; try { if(mService!=null) mService.acceptCall(sessionID); btn_call.setBackgroundResource(R.drawable.token_red); } catch (RemoteException e) { e.printStackTrace(); } } @Override protected void onDestroy(){ if(BuildConfig.DEBUG)Log.i(TAG,"onDestroy"); super.onDestroy(); isConnect=false; if(mConnection!=null && isConnect) try{ unbindService(mConnection); }catch (Exception e){ Log.e(TAG,"Error in unbind Service"); } if(serviceIntent!=null); /* try{ stopService(serviceIntent); }catch (Exception e){ Log.e(TAG,"Error in stop Service"); } */ mConnection=null; } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode){ } } //START GUI private void unRegisted(boolean success){ userData.setRegisted(false); userData.setDisplayName(null); userData.setMcpttID(null); text_info.setText("UNREGISTEREDD"); text_status.setText(getString(R.string.text_status)); btn_call.setEnabled(false); btn_call.setBackgroundResource(R.drawable.token_inactive); btn_unregister.setEnabled(false); btn_register.setEnabled(true); reg_status.setEnabled(false); switchCompat.setEnabled(false); switch_group.setTextColor(ContextCompat.getColor(this, R.color.background)); switch_private.setTextColor(ContextCompat.getColor(this, R.color.background)); spinnerGroups.setEnabled(false); spinnerUsers.setEnabled(false); btn_speaker.setEnabled(false); isSpeakerphoneOn=false; btn_speaker.setText(R.string.btn_speaker_off); } private void isRegisted(boolean success,String mcpttID,String displayName){ userData.setRegisted(success); if(mcpttID!=null) userData.setMcpttID(mcpttID); if(displayName!=null){ userData.setDisplayName(displayName); } text_info.setText("REGISTERED "+"MCPTT ID: "+mcpttID+" DISPLAY NAME: "+displayName); text_status.setText(displayName); btn_unregister.setEnabled(true); btn_register.setEnabled(false); btn_call.setBackgroundResource(R.drawable.token_default); reg_status.setEnabled(true); btn_call.setEnabled(true); switchCompat.setEnabled(true); switchCompat.setChecked(false); switch_group.setTextColor(ContextCompat.getColor(this, R.color.white)); switch_private.setTextColor(ContextCompat.getColor(this, R.color.white)); spinnerGroups.setEnabled(true); spinnerUsers.setEnabled(false); spinnerUsers.setVisibility((View.GONE)); spinnerGroups.setVisibility((View.VISIBLE)); btn_speaker.setEnabled(true); } private void showData(String eventType,String data){ text_info.setText(eventType+": "+data); } private void showLastError(String from,int code,String errorString){ Log.e(TAG,"ERROR "+from+": "+code+" "+errorString); text_info.setText("ERROR "+from+": "+code+" "+errorString); } private void showGroups(Map<String, Integer> groups){ String result=""; if(groups!=null){ groupsCurrent=new ArrayList<>(); for (String groupID:groups.keySet()){ String type=""; switch (ConstantsMCOP.GroupAffiliationEventExtras.GroupAffiliationStateEnum.fromInt(groups.get(groupID))){ case notaffiliated: type="notaffiliated"; break; case affiliating: type="affiliating"; break; case affiliated: type="affiliated"; groupsCurrent.add(groupID); break; case deaffiliating: type="deaffiliating"; break; } result=result+"groupID:"+groupID+":"+type+"\n"; } loadGroups(); } text_affiliation.setText("List Affiliation Groups: \n"+result); } /** * Set permissions for Android 6.0 or above */ protected void setPermissions(){ //Set permissions //READ_PHONE_STATE if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED ) { if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.RECORD_AUDIO)) { //Show an explanation to the user *asynchronously* -- don't block //this thread waiting for the user's response! After the user //sees the explanation, request the permission again. ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO,Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.CAMERA,Manifest.permission.READ_PHONE_STATE}, GET_PERMISSION); } else { //No explanation needed, we can request the permission. ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO,Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.CAMERA,Manifest.permission.READ_PHONE_STATE}, GET_PERMISSION); //MY_PERMISSIONS_REQUEST_READ_CONTACTS is an //app-defined int constant. The callback method gets the //result of the request. } } } @Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions,grantResults); switch (requestCode) { case GET_PERMISSION: { //If request is cancelled, result arrays are empty. if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { //Permission was granted, yay! Do the //contacts-related task you need to do. //API>22 setPermissionsWriteSetting(); } else { setPermissions(); //Permission denied, boo! Disable the //functionality that depends on this permission. } return; } default: break; //other 'case' lines to check for other //permissions this app might request } } /** * API>22 */ @TargetApi(Build.VERSION_CODES.M) protected void setPermissionsWriteSetting(){ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (Settings.System.canWrite(this) ){ //Do stuff here } else { Intent intent = new Intent(android.provider.Settings.ACTION_MANAGE_WRITE_SETTINGS); intent.setData(Uri.parse("package:" + this.getPackageName())); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } } } //END GUI private Map<String,String> getProfilesParameters(List<String> parameters){ Map<String,String> parametersMap=new HashMap<>(); if(parameters!=null && !parameters.isEmpty()){ Log.i(TAG,"we external parameters"); }else{ Log.i(TAG,"we don´t have external parameters"); parameters=loadParameters(); } if(parameters!=null && !parameters.isEmpty()) for (String parameter:parameters){ Log.i(TAG,"parameter: "+parameter); String[] parametersSplit=parameter.split(":"); if(parametersSplit!=null && parametersSplit.length==2){ parametersMap.put(parametersSplit[0],parametersSplit[1]); } } if(parametersMap!=null && !parametersMap.isEmpty()){ saveParameters(parameters); } return parametersMap; } private boolean saveParameters(List<String> parameters){ if(preferencesManager!=null){ return preferencesManager.putStringSet(this,PARAMETER_SAVE_PROFILE,new HashSet<String>(parameters)); } return false; } private ArrayList<String> loadParameters(){ if(preferencesManager!=null){ Set<String> stringSet=preferencesManager.getStringSet(this,PARAMETER_SAVE_PROFILE); if(stringSet!=null){ return (new ArrayList<String>(stringSet)); } } return null; } private void showOptionsProfiles(Map<String,String> stringsList,final Context context){ if(stringsList==null)return; final String[] strings=stringsList.values().toArray(new String[stringsList.size()]); if(strings==null || strings.length==0)return; mDialogMenu = DialogMenu.newInstance(strings,null); mDialogMenu.setOnClickItemListener(new DialogMenu.OnClickListener() { @Override public void onClickItem(int item) { if(item>=0 && strings.length>item){ Log.d(TAG,"Select profile: "+strings[item]); connectService(strings[item]); } } }); mDialogMenu.show(getSupportFragmentManager(), "SimpleDialog"); } private void connectService(String client){ if(!isConnect){ serviceIntent = new Intent() .setComponent(new ComponentName( "org.mcopenplatform.muoapi", "org.mcopenplatform.muoapi.MCOPsdk")); Log.i(TAG,"Current profile: "+currentProfile); serviceIntent.putExtra("PROFILE_SELECT", currentProfile!=null?currentProfile:client); try{ ComponentName componentName=this.startService(serviceIntent); if(componentName==null){ Log.e(TAG,"Starting Error: "+componentName.getPackageName()); }else if(serviceIntent==null){ Log.e(TAG,"serviceIntent Error: "+componentName.getPackageName()); }else if(mConnection==null){ Log.e(TAG,"mConnection Error: "+componentName.getPackageName()); }else{ } }catch (Exception e){ if(BuildConfig.DEBUG)Log.w(TAG,"Error in start service: "+e.getMessage()); } Log.i(TAG,"Bind Service: "+bindService(serviceIntent, mConnection, BIND_AUTO_CREATE)); } } }