0

I am doing some investigations with the GoogleTV and a Android tablet. I have managed to make an android application that can send control messages to the google tv from the main Activity, what I am trying to do is launch a new activity from the main Activity and continue using the AnymoteClientService Service with the new activity. In my main activity I get an anymoteSender handle which I use to send KeyEvent messages to the google tv, how do I transfer this to the new activity (SlidepuzzleActivity)? I could instantiate it all again, but that would mean having to go through the whole pairing process again.

From the code below you will see that I have an anymoteSender in my SlidepuzzleActivity class, this will throw an error, but illustrates where I need to reuse that variable.

Code: MainActivity.java:

package uk.co.myapp.gtvremote;
//imports removed for paste

public class MainActivity extends Activity implements ClientListener{

    private AnymoteSender anymoteSender;
    private TextView statusText;
    protected AnymoteClientService mAnymoteClientService;
    private static String statusPrefix = "Status: ";
    private Context mContext;
    private ProgressBar progressBar;

    private Handler handler;
    private TouchHandler touchPadHandler;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        progressBar = (ProgressBar) findViewById(R.id.a_progressbar);
        progressBar.setVisibility(View.VISIBLE);

        mContext = this;



        ImageButton upArrowButton = (ImageButton) findViewById(R.id.upArrow);
        ImageButton leftArrowButton = (ImageButton) findViewById(R.id.leftArrow);
        ImageButton centreButton = (ImageButton) findViewById(R.id.centreButton);
        ImageButton rightArrowButton = (ImageButton) findViewById(R.id.rightArrow);
        ImageButton downArrowButton = (ImageButton) findViewById(R.id.downArrow);
        ImageButton backButton = (ImageButton) findViewById(R.id.backButton);
        ImageButton homeButton = (ImageButton) findViewById(R.id.homeButton);
        Button testButton = (Button) findViewById(R.id.testButton);

        upArrowButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                sendKeyEvent(KeyEvent.KEYCODE_DPAD_UP);
            }
        });

        leftArrowButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                sendKeyEvent(KeyEvent.KEYCODE_DPAD_LEFT);
            }
        });

        centreButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                sendKeyEvent(KeyEvent.KEYCODE_DPAD_CENTER);
            }
        });

        rightArrowButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                sendKeyEvent(KeyEvent.KEYCODE_DPAD_RIGHT);
            }
        });

        downArrowButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                sendKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN);
            }
        });

        backButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                sendKeyEvent(KeyEvent.KEYCODE_BACK);

            }
        });

        homeButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                sendKeyEvent(KeyEvent.KEYCODE_HOME);

            }
        });

        testButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent myIntent = new Intent(MainActivity.this, SlidepuzzleActivity.class);
                MainActivity.this.startActivity(myIntent);
            }
        });

        handler = new Handler();

        // Bind to the AnymoteClientService
        Intent intent = new Intent(mContext, AnymoteClientService.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
        statusText = (TextView) findViewById(R.id.statusText);


    }

    /** Defines callbacks for service binding, passed to bindService() */
    private ServiceConnection mConnection = new ServiceConnection() {
        /*
         * ServiceConnection listener methods.
         */
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {

            mAnymoteClientService = ((AnymoteClientService.AnymoteClientServiceBinder) service)
                    .getService();
            mAnymoteClientService.attachClientListener(MainActivity.this);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mAnymoteClientService.detachClientListener(MainActivity.this);
            mAnymoteClientService = null;   
        }

    };

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public void onConnected(AnymoteSender anymoteSender) {
        if (anymoteSender != null) {
            // Send events to Google TV using anymoteSender.
            // save handle to the anymoteSender instance.
            this.anymoteSender = anymoteSender;
            attachTouchListnertoTouchPad();

        } else {
            statusText.setText(statusPrefix + "Connection attempt failed, cant find send handler");
            //attempt to connect again?
            //attemptToConnect();
        }

        // Hide the progressBar once connection to Google TV is established. Make the text display appropriately
        handler.post(new Runnable() {
            public void run() {
                progressBar.setVisibility(View.INVISIBLE);
                statusText.setText(statusPrefix + "Connected to GoogleTV");

            }
        });
    }

    @Override
    public void onDisconnected() {
        // show message to tell the user about disconnection.
        statusText.setText(statusPrefix + "Disconnected");
        // Try to connect again if needed. This may be need to be done via button
        attemptToConnect();
        this.anymoteSender = null;

    }

    @Override
    public void onConnectionError() {
        // show message to tell the user about disconnection.
        statusText.setText(statusPrefix + "Connection error encountered");
        // Try to connect again if needed.
        attemptToConnect();
        this.anymoteSender = null;

    }

    @Override
    protected void onDestroy() {
        if (mAnymoteClientService != null) {
            mAnymoteClientService.detachClientListener(this);
        }
        unbindService(mConnection);
        super.onDestroy();
    }

    private void attachTouchListnertoTouchPad()
    {
        // Attach touch handler to the touchpad view
        touchPadHandler = new TouchHandler(
                findViewById(R.id.touchPad), Mode.POINTER_MULTITOUCH, anymoteSender);
    }

    public void attemptToConnect()
    {
        //stub to invoke connection attempt
    }

    private void sendKeyEvent(final int keyEvent) {
        // create new Thread to avoid network operations on UI Thread
        if (anymoteSender == null) {
            Toast.makeText(MainActivity.this, "Waiting for connection",
                    Toast.LENGTH_LONG).show();
            return;
        }
        anymoteSender.sendKeyPress(keyEvent);
    }
}

SlidepuzzleActivity.java:

package uk.co.myapp.gtvremote;
//imports removed for paste

public class SlidepuzzleActivity extends Activity implements ClientListener{

    private AnymoteClientService mAnymoteClientService;
    private Context mContext;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.slidepuzzle);
        mContext = this;
        ImageButton piece1x1 = (ImageButton) findViewById(R.id.piece1x1);
        ImageButton piece1x2 = (ImageButton) findViewById(R.id.piece1x2);
        ImageButton piece1x3 = (ImageButton) findViewById(R.id.piece1x3);
        ImageButton piece2x1 = (ImageButton) findViewById(R.id.piece2x1);
        ImageButton piece2x2 = (ImageButton) findViewById(R.id.piece2x2);
        ImageButton piece2x3 = (ImageButton) findViewById(R.id.piece2x3);
        ImageButton piece3x1 = (ImageButton) findViewById(R.id.piece3x1);
        ImageButton piece3x2 = (ImageButton) findViewById(R.id.piece3x2);
        ImageButton piece3x3 = (ImageButton) findViewById(R.id.piece3x3);

        Intent intent = new Intent(mContext, AnymoteClientService.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);

        piece1x1.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {


            }
        });
    }

    private ServiceConnection mConnection = new ServiceConnection() {


        /*
         * ServiceConnection listener methods.
         */
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {

            mAnymoteClientService = ((AnymoteClientService.AnymoteClientServiceBinder) service)
                    .getService();
            mAnymoteClientService.attachClientListener(SlidepuzzleActivity.this);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mAnymoteClientService.detachClientListener(SlidepuzzleActivity.this);
            mAnymoteClientService = null;   
        }

    };

    private void sendKeyEvent(final int keyEvent) {
        // create new Thread to avoid network operations on UI Thread
        if (anymoteSender == null) {
            Toast.makeText(SlidepuzzleActivity.this, "Waiting for connection",
                    Toast.LENGTH_LONG).show();
            return;
        }
        anymoteSender.sendKeyPress(keyEvent);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.slidepuzzle, menu);
        return true;
    }

    @Override
    public void onConnected(AnymoteSender anymoteSender) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onDisconnected() {
        // TODO Auto-generated method stub

    }

    @Override
    public void onConnectionError() {
        // TODO Auto-generated method stub

    }

    @Override
    protected void onDestroy() {
        if (mAnymoteClientService != null) {
            mAnymoteClientService.detachClientListener(this);
        }
        unbindService(mConnection);
        super.onDestroy();
    }


}
MYR
  • 381
  • 1
  • 2
  • 12

1 Answers1

2

Just published an update to AnymoteLibrary for this.

In your MainActivity call both bindService() (already) and startService() for AnymoteClientService. The reason behind calling startService() is to keep the service and its anymoteSender instance around so that other Activitys in the same app can use it.

In the second Activity, implement ClientListener ( if you want to get onDisconnected() callback) and bind to the service and attachClientListener(). To get the AnymoteSender instance, call AnymoteClientService.getAnymoteSender(). Note that it can return null if the connection to Google TV is lost.

When all Activitys are done using AnymoteSender, remember to call stopService() for AnymoteClientService.

  • Thanks Megha Joshi, could you point to some tutorial examples of this for the completeness of this thread? I am assuming I will have to make use of a singleton pattern to make sure only one instance of the AnymoteService is instantiated? – MYR Jul 12 '12 at 12:40
  • you are right..I didn't think it through :) let me spend sometime on sample code and then I will post it here. – Megha Joshi - GoogleTV DevRel Jul 12 '12 at 17:50
  • Cheers Megha Joshi, appreciate the input and changes! – MYR Jul 13 '12 at 15:57