> *Refer to* [*README*](../README.md) *for main instruction file* # MCOP - MCPTT App Development ## What is MCOP? **MCOP** (Mission Critical Open Platform) is a project that defines the first prototype of open source **MCPTT** (Mission Critical Push-To-Talk) client. This client allows the interoperability among different vendors thanks to a multilevel API. ## Architecture Three main modules define the architecture: * **MCOP SDK**: This module contains all the MCPTT logic, and allows the use of other additional modules that increase its functionality. * **MCOP Integration Plugins**: Additional modules or Android services with their own API, known by the MCOP SDK module, offering device specific or MCPTT network required functionalities. * **End User Interface**: GUI (Graphical User Interface) that uses the MCOP SDK services without having to develop the whole MCPTT logic. *(Min. level of Android SDK: API 17)*. ![ThreMainModules](../images/threemainmodules.png) ## App Developing Steps * **0. MCOP SDK and AIDLs**: The SDK defines two AIDLs and one Constant class: * **IMCOPsdk**: From Client to SDK. * **IMCOPCallBack**: From SDK to Client. * **ConstantsMCOP**: defines the constants to use in the AIDLs. * **1. Configure Manifest**: Indicate the necessary permissions for the application. <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.WRITE_SETTINGS" /> <uses-permission android:name="android.permission.DISABLE_KEYGUARD" /> <uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.WRITE_CONTACTS" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" /> <uses-permission android:name="android.permission.CALL_PHONE" /> <uses-permission android:name="android.permission.RAISED_THREAD_PRIORITY" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> * **2. Require the explicit acceptance of some of the permissions.** The client should explicitly accept some permissions: * Manifest.permission.ACCESS\_FINE\_LOCATION * Manifest.permission.READ\_PHONE\_STATE * Manifest.permission.ACCESS\_COARSE\_LOCATION * Manifest.permission.CAMERA * Manifest.permission.RECORD\_AUDIO ![Allow audio](../images/images_allow1RecordAudio.png) * **3. Bind to MCOP SDK**: In this version of MCOP SDK, it is necessary to send **“currentProfile”** to the service: Intent serviceIntent = new Intent() .setComponent(new ComponentName( "org.mcopenplatform.muoapi", "org.mcopenplatform.muoapi.MCOPsdk"));
 serviceIntent.putExtra("PROFILE_SELECT",currentProfile); try{ ComponentName componentName; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { componentName = this.startForegroundService(serviceIntent); } else { 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()); } Wait for the service to bind: * Save the return value from the Service (this is the AIDL Interface to be used by the Client to communicate with the Service). * Register the callback for asynchronous communication from the Service to the Client: mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { mService = IMCOPsdk.Stub.asInterface(service); try { mService.registerCallback(mMCOPCallback); } catch (RemoteException e) { e.printStackTrace(); } isConnect=true; // Auto Registration if (autoRegister) { final Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { register(); } }, DEFAULT_REGISTER_DELAY); } } * Definition of the registered callback: * This is the point where communications from the Server to the Client will be received: 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())){ ... } }catch (Exception ex){ Log.e(TAG,"Event Action Error: "+action.getAction()+" error:"+ex.getMessage()); } } } }); } }; * **4. Perform any action in the MCOP SDK and receive the result**. Example: if(mService!=null) mService.makeCall( selGroup, //DEFAULT_GROUP, ConstantsMCOP.CallEventExtras.CallTypeEnum.Audio.getValue()| ConstantsMCOP.CallEventExtras.CallTypeEnum.WithFloorCtrl.getValue()| ConstantsMCOP.CallEventExtras.CallTypeEnum.PrearrangedGroup.getValue() );