/*
* Copyright (C) 2010 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.
*/
package com.google.android.apps.tvremote;
import java.util.ArrayList;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.speech.RecognizerIntent;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageButton;
import android.widget.Toast;
import com.google.android.apps.tvremote.TouchHandler.Mode;
import com.google.android.apps.tvremote.layout.SlidingLayout;
import com.google.android.apps.tvremote.util.Action;
import com.google.android.apps.tvremote.widget.HighlightView;
import com.google.android.apps.tvremote.widget.KeyCodeButton;
import com.google.android.apps.tvremote.widget.SoftDpad;
import com.google.anymote.Key;
/**
* Main screen of the remote controller activity.
*/
public class MainActivity extends BaseActivity
implements KeyCodeButton.KeyCodeHandler {
private static final String LOG_TAG = "RemoteActivity";
private HighlightView surface;
private final Handler handler;
/**
* The enum represents modes of the remote controller with
* {@link SlidingLayout} screens assignment. In conjunction with
* {@link ModeSelector} allows sliding between the screens.
*/
private enum RemoteMode {
TV(0, R.drawable.icon_04_touchpad_selector),
TOUCHPAD(1, R.drawable.icon_04_buttons_selector);
private final int screenId;
private final int switchButtonId;
RemoteMode(int screenId, int switchButtonId) {
this.screenId = screenId;
this.switchButtonId = switchButtonId;
}
}
/**
* Mode selector allow sliding across the modes, keeps currently selected mode
* information, and slides among the modes.
*/
private static final class ModeSelector {
private final SlidingLayout slidingLayout;
private final ImageButton imageButton;
private RemoteMode mode;
ModeSelector(
RemoteMode initialMode, SlidingLayout slidingLayout, ImageButton imageButton) {
mode = initialMode;
this.slidingLayout = slidingLayout;
this.imageButton = imageButton;
applyMode();
}
void slideNext() {
setMode(RemoteMode.TOUCHPAD.equals(mode) ? RemoteMode.TV : RemoteMode.TOUCHPAD);
}
void setMode(RemoteMode newMode) {
mode = newMode;
applyMode();
}
void applyMode() {
slidingLayout.snapToScreen(mode.screenId);
imageButton.setImageResource(mode.switchButtonId);
}
}
public MainActivity() {
handler = new Handler();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_touchpad_top);
surface = (HighlightView) findViewById(R.id.HighlightView);
LayoutInflater inflater = LayoutInflater.from(getBaseContext());
SlidingLayout slidingLayout = (SlidingLayout) findViewById(R.id.slider);
slidingLayout.addView(
inflater.inflate(R.layout.subview_playcontrol_tv, null), 0);
slidingLayout.addView(
inflater.inflate(R.layout.subview_touchpad, null), 1);
slidingLayout.setCurrentScreen(0);
ImageButton nextButton = (ImageButton) findViewById(R.id.button_next_page);
ImageButton keyboardButton =
(ImageButton) findViewById(R.id.button_keyboard);
ImageButton voiceButton = (ImageButton) findViewById(R.id.button_voice);
ImageButton searchButton = (ImageButton) findViewById(R.id.button_search);
ImageButton shortcutsButton =
(ImageButton) findViewById(R.id.button_shortcuts);
ImageButton liveTvButton = (ImageButton) findViewById(R.id.button_livetv);
final ModeSelector current =
new ModeSelector(RemoteMode.TV, slidingLayout, nextButton);
nextButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
current.slideNext();
}
});
liveTvButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
current.setMode(RemoteMode.TV);
}
});
keyboardButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
showActivity(KeyboardActivity.class);
}
});
voiceButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
showVoiceSearchActivity();
}
});
searchButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Action.NAVBAR.execute(getCommands());
showActivity(KeyboardActivity.class);
}
});
shortcutsButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
showActivity(ShortcutsActivity.class);
}
});
SoftDpad softDpad = (SoftDpad) findViewById(R.id.SoftDpad);
softDpad.setDpadListener(getDefaultDpadListener());
// Attach touch handler to the touchpad
new TouchHandler(
findViewById(R.id.touch_pad), Mode.POINTER_MULTITOUCH, getCommands());
flingIntent(getIntent());
}
@Override
protected void onDestroy() {
super.onDestroy();
}
public HighlightView getHighlightView() {
return surface;
}
// KeyCode handler implementation.
public void onRelease(Key.Code keyCode) {
getCommands().key(keyCode, Key.Action.UP);
}
public void onTouch(Key.Code keyCode) {
playClick();
getCommands().key(keyCode, Key.Action.DOWN);
}
private void playClick() {
((AudioManager) getSystemService(Context.AUDIO_SERVICE)).playSoundEffect(
AudioManager.FX_KEY_CLICK);
}
private void flingIntent(Intent intent) {
if (intent != null) {
if (Intent.ACTION_SEND.equals(intent.getAction())) {
String text = intent.getStringExtra(Intent.EXTRA_TEXT);
if (text != null) {
Uri uri = Uri.parse(text);
if (uri != null && ("http".equals(uri.getScheme())
|| "https".equals(uri.getScheme()))) {
getCommands().flingUrl(text);
} else {
Toast.makeText(
this, R.string.error_could_not_send_url, Toast.LENGTH_SHORT)
.show();
}
} else {
Log.w(LOG_TAG, "No URI to fling");
}
}
}
}
@Override
protected void onKeyboardOpened() {
showActivity(KeyboardActivity.class);
}
// SUBACTIVITIES
/**
* The activities that can be launched from the main screen.
* <p>
* These codes should not conflict with the request codes defined in
* {@link BaseActivity}.
*/
private enum SubActivity {
VOICE_SEARCH,
UNKNOWN;
public int code() {
return BaseActivity.FIRST_USER_CODE + ordinal();
}
public static SubActivity fromCode(int code) {
for (SubActivity activity : values()) {
if (code == activity.code()) {
return activity;
}
}
return UNKNOWN;
}
}
@Override
protected void onActivityResult(
int requestCode, int resultCode, Intent data) {
SubActivity activity = SubActivity.fromCode(requestCode);
switch (activity) {
case VOICE_SEARCH:
onVoiceSearchResult(resultCode, data);
break;
default:
super.onActivityResult(requestCode, resultCode, data);
break;
}
}
// VOICE SEARCH
private void showVoiceSearchActivity() {
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
startActivityForResult(intent, SubActivity.VOICE_SEARCH.code());
}
private void onVoiceSearchResult(int resultCode, Intent data) {
String searchQuery;
if ((resultCode == RESULT_CANCELED) || (data == null)) {
return;
}
ArrayList<String> queryResults =
data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
if ((queryResults == null) || (queryResults.isEmpty())) {
Log.d(LOG_TAG, "No results from VoiceSearch server.");
return;
} else {
searchQuery = queryResults.get(0);
if (TextUtils.isEmpty(searchQuery)) {
Log.d(LOG_TAG, "Empty result from VoiceSearch server.");
return;
}
}
showVoiceSearchDialog(searchQuery);
}
private void showVoiceSearchDialog(final String query) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder
.setNeutralButton(
R.string.voice_send, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
getCommands().string(query);
}
})
.setPositiveButton(
R.string.voice_search_send, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
getCommands().keyPress(Key.Code.KEYCODE_SEARCH);
// Send query delayed
handler.postDelayed(new Runnable() {
public void run() {
getCommands().string(query);
}
}, getResources().getInteger(R.integer.search_query_delay));
}
})
.setNegativeButton(
R.string.pairing_cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
})
.setCancelable(true)
.setTitle(R.string.voice_dialog_label)
.setMessage(query);
builder.create().show();
}
}