> *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.QUERY_ALL_PACKAGES"/>
    	<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    	<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

	Define the activities to be used:

		<application
			android:allowBackup="true"
			android:icon="@mipmap/ic_launcher"
			android:label="@string/app_name"
			android:roundIcon="@mipmap/ic_launcher_round"
			android:supportsRtl="true"
			android:theme="@style/AppTheme" >
			<activity android:name=".MainActivity"
				android:screenOrientation="portrait">
				<intent-filter>
					<action android:name="android.intent.action.MAIN" />
					<category android:name="android.intent.category.LAUNCHER" />
				</intent-filter>
			</activity>
		</application>
		<queries>
    	</queries>

* **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/allow_audio.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")); 
		//This is only for tresting
		serviceIntent.putExtra("PROFILE_SELECT",currentProfile);
		
		ComponentName componentName=startService(serviceIntent);
		bindService(serviceIntent, mConnection, BIND_AUTO_CREATE);

	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 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);
			}

	* 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.CallSubtypeAudio.getValue()|
				ConstantsMCOP.CallEventExtras.CallTypeEnum.CallSubtypeWithCtrlMech.getValue()| 
				ConstantsMCOP.CallEventExtras.CallTypeEnum.CallSubtypePrearrangedGroup.getValue()
			);
			





