Java tutorial
package com.pixplicity.castdemo; /* * Copyright (C) 2014 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import org.json.JSONException; import org.json.JSONObject; import android.accounts.Account; import android.accounts.AccountManager; import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.os.Handler; import android.speech.RecognizerIntent; import android.support.v4.view.MenuItemCompat; import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBarActivity; import android.support.v7.app.MediaRouteActionProvider; import android.util.Log; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.widget.BaseAdapter; import android.widget.EditText; import android.widget.ImageButton; import android.widget.ListView; import android.widget.TextView; import android.widget.TextView.OnEditorActionListener; import android.widget.Toast; import com.google.android.gms.cast.Cast; import com.google.android.gms.cast.CastDevice; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.common.api.ResultCallback; import com.google.android.gms.common.api.Status; /** * Main activity to send messages to the receiver. */ public class MainActivity extends ActionBarActivity { private static final String TAG = MainActivity.class.getSimpleName(); private static final int REQUEST_SPEECH_RECOGNITION = 101; private EditText mEtMessage; private ImageButton mBtSend; private ImageButton mBtSpeak; private ListView mLvMessages; private ViewGroup mVgLogo; private String mUsername; // private ArrayList<Message> mMessageList = new ArrayList<Message>(); private ArrayList<String> mMessageListMessages = new ArrayList<String>(); private ArrayList<String> mMessageListUsernames = new ArrayList<String>(); private BaseAdapter mMessageAdapter; private final Handler mHandler = new Handler(); public class Message { public final String username; public final String message; public Message(String username, String message) { this.username = username; this.message = message; } } /** * Custom message channel */ public class HelloWorldChannel implements CastProxy.CastChannel { public final Context mApplicationContext; public HelloWorldChannel(Context applicationContext) { mApplicationContext = applicationContext; } /** * @return Custom namespace over which the channel is communicated */ @Override public String getNamespace() { return mApplicationContext.getString(R.string.namespace); } @Override public void onConnected() { Log.d(TAG, "onConnected"); // Set the initial instructions on the receiver sendMessage(null); setConnected(true); } @Override public void onReconnected() { Log.d(TAG, "onReconnected"); setConnected(true); } @Override public void onDisconnected() { Log.d(TAG, "onDisconnected"); setConnected(false); } @Override public void onMessageReceived(CastDevice castDevice, String namespace, String message) { Log.d(TAG, "onMessageReceived: " + message); try { JSONObject json = new JSONObject(message); String name = json.getString("name"); mMessageListUsernames.add(name); String msg = json.getString("msg"); mMessageListMessages.add(msg); updateMessages(); mMessageAdapter.notifyDataSetChanged(); } catch (JSONException e) { throw new RuntimeException(e); } } /** * Send a text message to the receiver * * @param message */ @Override public boolean sendMessage(String message) { JSONObject json = new JSONObject(); try { if (message != null) { if (message.length() == 0) { return false; } json.put("code", 2); json.put("msg", message); } else { json.put("code", 1); } json.put("name", getUsername()); } catch (JSONException e) { throw new RuntimeException(e); } GoogleApiClient apiClient = CastProxy.getApiClient(); if (apiClient == null) { Toast.makeText(mApplicationContext, R.string.failed_no_connection, Toast.LENGTH_SHORT).show(); } else { try { Log.d(TAG, "sending: " + message); Cast.CastApi.sendMessage(apiClient, getNamespace(), json.toString()) .setResultCallback(new ResultCallback<Status>() { @Override public void onResult(Status result) { if (!result.isSuccess()) { Log.e(TAG, "Sending message failed"); } } }); return true; } catch (Exception e) { Log.e(TAG, "Exception while sending message", e); Toast.makeText(mApplicationContext, R.string.failed_unknown, Toast.LENGTH_SHORT).show(); } } return false; } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); CastProxy.init(getApplicationContext(), new HelloWorldChannel(getApplicationContext())); ActionBar actionBar = getSupportActionBar(); actionBar.setBackgroundDrawable(new ColorDrawable(android.R.color.transparent)); // Sends the message over the channel mBtSend = (ImageButton) findViewById(R.id.bt_send); mBtSend.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { sendTextMessage(mEtMessage); } }); // When the user clicks on the "speak" button, use Android voice recognition to get text mBtSpeak = (ImageButton) findViewById(R.id.bt_speak); mBtSpeak.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { startVoiceRecognitionActivity(); } }); mEtMessage = (EditText) findViewById(R.id.et_message); mEtMessage.setOnEditorActionListener(new OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { switch (actionId) { case EditorInfo.IME_ACTION_SEND: sendTextMessage(mEtMessage); return true; } return false; } }); mLvMessages = (ListView) findViewById(R.id.lv_messages); mVgLogo = (ViewGroup) findViewById(R.id.vg_logo); setConnected(false); } private void setConnected(boolean connected) { mBtSend.setEnabled(connected); mBtSpeak.setEnabled(connected); mEtMessage.setEnabled(connected); if (connected) { mEtMessage.requestFocus(); // Implicity request a soft input mode InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.showSoftInput(mEtMessage, InputMethodManager.SHOW_IMPLICIT); } } private void updateMessages() { if (mMessageListMessages.size() > 0) { mVgLogo.setVisibility(View.INVISIBLE); } if (mMessageAdapter == null) { mMessageAdapter = new BaseAdapter() { @SuppressLint("InflateParams") @Override public View getView(int position, View convertView, ViewGroup parent) { View row; if (convertView == null) { LayoutInflater inflater = (LayoutInflater) getApplicationContext() .getSystemService(Context.LAYOUT_INFLATER_SERVICE); row = inflater.inflate(R.layout.list_messages, null); } else { row = convertView; } /* TODO Message msg = getItem(position); row.getText1().setText(msg.username); row.getText2().setText(msg.message); */ ((TextView) row.findViewById(R.id.tv_username)).setText(mMessageListUsernames.get(position)); ((TextView) row.findViewById(R.id.tv_message)).setText(mMessageListMessages.get(position)); return row; } @Override public int getCount() { return mMessageListMessages.size(); } @Override public Message getItem(int position) { // TODO return mMessageList.get(position); return null; } @Override public long getItemId(int position) { return 0; } }; mLvMessages.setAdapter(mMessageAdapter); } } /** * Android voice recognition */ private void startVoiceRecognitionActivity() { Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_PREFERENCE, "en-US"); intent.putExtra(RecognizerIntent.EXTRA_PROMPT, getString(R.string.message_to_cast)); startActivityForResult(intent, REQUEST_SPEECH_RECOGNITION); } /* * Handle the voice recognition response * * @see android.support.v4.app.FragmentActivity#onActivityResult(int, int, * android.content.Intent) */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_SPEECH_RECOGNITION && resultCode == RESULT_OK) { ArrayList<String> matches = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS); if (matches.size() > 0) { String message = matches.get(0); if (!CastProxy.getChannel().sendMessage(message)) { mEtMessage.setText(message); } } } super.onActivityResult(requestCode, resultCode, data); } @Override protected void onStart() { super.onStart(); CastProxy.registerInstance(); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putStringArrayList("usernames", mMessageListUsernames); outState.putStringArrayList("messages", mMessageListMessages); } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); mLvMessages.setAdapter(null); mMessageListUsernames = savedInstanceState.getStringArrayList("usernames"); mMessageListMessages = savedInstanceState.getStringArrayList("messages"); updateMessages(); } @Override protected void onStop() { // Unregister with a delay to cope with orientation changes mHandler.postDelayed(new Runnable() { @Override public void run() { CastProxy.unregisterInstance(true); } }, 2000); super.onStop(); } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); getMenuInflater().inflate(R.menu.main, menu); MenuItem mediaRouteMenuItem = menu.findItem(R.id.media_route_menu_item); MediaRouteActionProvider mediaRouteActionProvider = (MediaRouteActionProvider) MenuItemCompat .getActionProvider(mediaRouteMenuItem); // Set the MediaRouteActionProvider selector for device discovery. mediaRouteActionProvider.setRouteSelector(CastProxy.getMediaRouteSelector()); return true; } private void sendTextMessage(final EditText textField) { if (CastProxy.getChannel().sendMessage(textField.getText().toString())) { textField.setText(null); } } public String getUsername() { if (mUsername == null) { mUsername = "anonymous"; // Default username AccountManager manager = AccountManager.get(this); Account[] accounts = manager.getAccountsByType("com.google"); List<String> possibleEmails = new LinkedList<String>(); for (Account account : accounts) { possibleEmails.add(account.name); } if (!possibleEmails.isEmpty() && possibleEmails.get(0) != null) { String email = possibleEmails.get(0); String[] parts = email.split("@"); if (parts.length > 0 && parts[0] != null) { mUsername = parts[0]; } } } return mUsername; } }