package net.trentgardner.cordova.galaxygear; import java.io.IOException; import java.util.ArrayList; import java.util.List; import net.trentgardner.cordova.galaxygear.GearMessageApi; import net.trentgardner.cordova.galaxygear.GearMessageListener; import android.content.Context; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; import android.util.SparseArray; import com.samsung.android.sdk.SsdkUnsupportedException; import com.samsung.android.sdk.accessory.SA; import com.samsung.android.sdk.accessory.SAAgent; import com.samsung.android.sdk.accessory.SAPeerAgent; import com.samsung.android.sdk.accessory.SASocket; public class GearProviderService extends SAAgent { public static final String TAG = GearProviderService.class.getSimpleName(); public Context mContext = null; public static final int SERVICE_CONNECTION_RESULT_OK = 0; public static final int GALAXY_GEAR_CHANNEL_ID = 104; private SparseArray<GalaxyGearProviderConnection> mConnectionsMap = new SparseArray<GalaxyGearProviderConnection>(); private List<GearMessageListener> listeners = new ArrayList<GearMessageListener>(); private final GearMessageApi.Stub apiEndpoint = new GearMessageApi.Stub() { @Override public void sendData(int connectionId, String data) throws RemoteException { Log.d(TAG, "GearMessageApi.sendData"); final byte[] message = data.getBytes(); synchronized (mConnectionsMap) { final GalaxyGearProviderConnection connection = mConnectionsMap.get(connectionId); if (connection == null) { Log.e(TAG, "Connection handler not found!"); return; } new Thread(new Runnable() { public void run() { try { connection.send(GALAXY_GEAR_CHANNEL_ID, message); } catch (IOException e) { e.printStackTrace(); } } }).start(); } } @Override public void removeListener(GearMessageListener listener) throws RemoteException { Log.d(TAG, "GearMessageApi.removeListener"); synchronized (listeners) { listeners.remove(listener); } } @Override public void addListener(final GearMessageListener listener) throws RemoteException { Log.d(TAG, "GearMessageApi.addListener"); synchronized (listeners) { listeners.add(listener); } // Tell the new listener of any existing connections synchronized (mConnectionsMap) { int key = 0; for (int i = 0; i < mConnectionsMap.size(); i++) { key = mConnectionsMap.keyAt(i); Log.d(TAG, Integer.toString(key)); listener.onConnect(key); } } } }; public GearProviderService() { super(TAG, GalaxyGearProviderConnection.class); } public class GalaxyGearProviderConnection extends SASocket { private int mConnectionId; private final String CONNECTION_TAG = TAG + "." + GalaxyGearProviderConnection.class.getSimpleName(); public GalaxyGearProviderConnection() { super(GalaxyGearProviderConnection.class.getName()); } @Override public void onError(int channelId, String errorString, int error) { final String message = "Connection is not alive ERROR: " + errorString + " " + error; onError(message); } @Override public void onReceive(int channelId, byte[] data) { Log.d(CONNECTION_TAG, "onReceive"); String sData = new String(data); synchronized (listeners) { for (GearMessageListener listener : listeners) { try { listener.onDataReceived(mConnectionId, sData); } catch (RemoteException e) { Log.w(TAG, "Failed to notify listener " + listener, e); } } } } @Override protected void onServiceConnectionLost(int errorCode) { final String message = "onServiceConectionLost for peer = " + mConnectionId + "error code =" + errorCode; onError(message); if (mConnectionsMap != null) { mConnectionsMap.remove(mConnectionId); } } private void onError(String data) { Log.e(CONNECTION_TAG, data); synchronized (listeners) { for (GearMessageListener listener : listeners) { try { listener.onError(mConnectionId, data); } catch (RemoteException e) { Log.w(TAG, "Failed to notify listener " + listener, e); } } } } } @Override public void onCreate() { super.onCreate(); Log.i(TAG, "onCreate"); SA mAccessory = new SA(); try { mAccessory.initialize(this); } catch (SsdkUnsupportedException e) { // Error Handling } catch (Exception e1) { Log.e(TAG, "Cannot initialize Accessory package."); e1.printStackTrace(); /* * Your application can not use Accessory package of Samsung Mobile * SDK. You application should work smoothly without using this SDK, * or you may want to notify user and close your app gracefully * (release resources, stop Service threads, close UI thread, etc.) */ stopSelf(); } } @Override public IBinder onBind(Intent intent) { Log.d(TAG, "onBind"); return apiEndpoint; } @Override protected void onServiceConnectionRequested(SAPeerAgent peerAgent) { Log.d(TAG, "acceptServiceConnectionRequest"); acceptServiceConnectionRequest(peerAgent); } @Override protected void onFindPeerAgentResponse(SAPeerAgent arg0, int arg1) { Log.d(TAG, "onFindPeerAgentResponse arg1 =" + arg1); } @Override protected void onServiceConnectionResponse(SASocket thisConnection, int result) { if (result == CONNECTION_SUCCESS) { if (thisConnection != null) { GalaxyGearProviderConnection myConnection = (GalaxyGearProviderConnection) thisConnection; if (mConnectionsMap == null) { mConnectionsMap = new SparseArray<GalaxyGearProviderConnection>(); } myConnection.mConnectionId = (int) (System.currentTimeMillis() & 255); Log.d(TAG, "onServiceConnection connectionID = " + myConnection.mConnectionId); mConnectionsMap.put(myConnection.mConnectionId, myConnection); Log.i(TAG, "Connection Success"); synchronized (listeners) { for (GearMessageListener listener : listeners) { try { listener.onConnect(myConnection.mConnectionId); } catch (RemoteException e) { Log.w(TAG, "Failed to notify listener " + listener, e); } } } } else { Log.e(TAG, "SASocket object is null"); } } else if (result == CONNECTION_ALREADY_EXIST) { Log.e(TAG, "onServiceConnectionResponse, CONNECTION_ALREADY_EXIST"); } else { Log.e(TAG, "onServiceConnectionResponse result error =" + result); } } }