|
|
|
|
@ -1,7 +1,6 @@ |
|
|
|
|
package com.fongmi.android.tv.ui.activity; |
|
|
|
|
|
|
|
|
|
import android.Manifest; |
|
|
|
|
import android.annotation.SuppressLint; |
|
|
|
|
import android.app.Activity; |
|
|
|
|
import android.content.Intent; |
|
|
|
|
import android.content.pm.PackageManager; |
|
|
|
|
@ -12,7 +11,6 @@ import android.speech.SpeechRecognizer; |
|
|
|
|
import android.text.Editable; |
|
|
|
|
import android.text.TextUtils; |
|
|
|
|
import android.view.View; |
|
|
|
|
import android.view.ViewGroup; |
|
|
|
|
import android.view.animation.Animation; |
|
|
|
|
import android.view.inputmethod.EditorInfo; |
|
|
|
|
|
|
|
|
|
@ -21,7 +19,6 @@ import androidx.activity.result.contract.ActivityResultContracts; |
|
|
|
|
import androidx.annotation.NonNull; |
|
|
|
|
import androidx.core.content.ContextCompat; |
|
|
|
|
import androidx.leanback.widget.ArrayObjectAdapter; |
|
|
|
|
import androidx.leanback.widget.HorizontalGridView; |
|
|
|
|
import androidx.leanback.widget.ItemBridgeAdapter; |
|
|
|
|
import androidx.viewbinding.ViewBinding; |
|
|
|
|
|
|
|
|
|
@ -33,11 +30,13 @@ import com.fongmi.android.tv.net.Callback; |
|
|
|
|
import com.fongmi.android.tv.net.OKHttp; |
|
|
|
|
import com.fongmi.android.tv.ui.custom.CustomKeyboard; |
|
|
|
|
import com.fongmi.android.tv.ui.custom.CustomListener; |
|
|
|
|
import com.fongmi.android.tv.ui.custom.SpaceItemDecoration; |
|
|
|
|
import com.fongmi.android.tv.ui.presenter.WordPresenter; |
|
|
|
|
import com.fongmi.android.tv.utils.ResUtil; |
|
|
|
|
import com.fongmi.android.tv.utils.Utils; |
|
|
|
|
|
|
|
|
|
import java.io.IOException; |
|
|
|
|
import java.util.Arrays; |
|
|
|
|
import java.util.List; |
|
|
|
|
|
|
|
|
|
import okhttp3.Call; |
|
|
|
|
@ -48,15 +47,12 @@ public class SearchActivity extends BaseActivity implements WordPresenter.OnClic |
|
|
|
|
private final ActivityResultLauncher<String> launcherString = registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> onVoice()); |
|
|
|
|
|
|
|
|
|
private ActivitySearchBinding mBinding; |
|
|
|
|
private ArrayObjectAdapter mHistoryAdapter; |
|
|
|
|
private ArrayObjectAdapter mWordAdapter; |
|
|
|
|
private SpeechRecognizer mRecognizer; |
|
|
|
|
private Animation mFlicker; |
|
|
|
|
private Handler mHandler; |
|
|
|
|
|
|
|
|
|
private boolean hasVoice() { |
|
|
|
|
return SpeechRecognizer.isRecognitionAvailable(this); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static void start(Activity activity) { |
|
|
|
|
activity.startActivity(new Intent(activity, SearchActivity.class)); |
|
|
|
|
} |
|
|
|
|
@ -71,7 +67,6 @@ public class SearchActivity extends BaseActivity implements WordPresenter.OnClic |
|
|
|
|
mFlicker = ResUtil.getAnim(R.anim.flicker); |
|
|
|
|
mHandler = new Handler(Looper.getMainLooper()); |
|
|
|
|
mRecognizer = SpeechRecognizer.createSpeechRecognizer(this); |
|
|
|
|
mBinding.voice.setVisibility(hasVoice() ? View.VISIBLE : View.GONE); |
|
|
|
|
CustomKeyboard.init(this, mBinding); |
|
|
|
|
mBinding.keyword.requestFocus(); |
|
|
|
|
setRecyclerView(); |
|
|
|
|
@ -80,7 +75,6 @@ public class SearchActivity extends BaseActivity implements WordPresenter.OnClic |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
protected void initEvent() { |
|
|
|
|
mBinding.voice.setOnClickListener(view -> onVoice()); |
|
|
|
|
mBinding.keyword.setOnEditorActionListener((textView, actionId, event) -> { |
|
|
|
|
if (actionId == EditorInfo.IME_ACTION_DONE) onSearch(); |
|
|
|
|
return true; |
|
|
|
|
@ -95,30 +89,49 @@ public class SearchActivity extends BaseActivity implements WordPresenter.OnClic |
|
|
|
|
mRecognizer.setRecognitionListener(new CustomListener() { |
|
|
|
|
@Override |
|
|
|
|
public void onResults(String result) { |
|
|
|
|
mBinding.voice.clearAnimation(); |
|
|
|
|
stopListening(); |
|
|
|
|
mBinding.keyword.setText(result); |
|
|
|
|
mBinding.keyword.setSelection(mBinding.keyword.length()); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@SuppressLint("RestrictedApi") |
|
|
|
|
private void setRecyclerView() { |
|
|
|
|
mBinding.word.setHorizontalSpacing(ResUtil.dp2px(16)); |
|
|
|
|
mBinding.word.setRowHeight(ViewGroup.LayoutParams.WRAP_CONTENT); |
|
|
|
|
mBinding.word.setFocusScrollStrategy(HorizontalGridView.FOCUS_SCROLL_ITEM); |
|
|
|
|
mBinding.word.setHasFixedSize(true); |
|
|
|
|
mBinding.history.setHasFixedSize(true); |
|
|
|
|
mBinding.word.addItemDecoration(new SpaceItemDecoration(1, 16)); |
|
|
|
|
mBinding.history.addItemDecoration(new SpaceItemDecoration(1, 16)); |
|
|
|
|
mBinding.word.setAdapter(new ItemBridgeAdapter(mWordAdapter = new ArrayObjectAdapter(new WordPresenter(this)))); |
|
|
|
|
mBinding.history.setAdapter(new ItemBridgeAdapter(mHistoryAdapter = new ArrayObjectAdapter(new WordPresenter(this)))); |
|
|
|
|
mHistoryAdapter.setItems(Arrays.asList("測試1測試1", "測試2測試2", "測試3"), null); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void onVoice() { |
|
|
|
|
if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { |
|
|
|
|
launcherString.launch(Manifest.permission.RECORD_AUDIO); |
|
|
|
|
} else { |
|
|
|
|
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); |
|
|
|
|
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); |
|
|
|
|
mBinding.voice.startAnimation(mFlicker); |
|
|
|
|
mRecognizer.startListening(intent); |
|
|
|
|
} |
|
|
|
|
private void getHot() { |
|
|
|
|
mBinding.hint.setText(R.string.search_hot); |
|
|
|
|
OKHttp.newCall("https://node.video.qq.com/x/api/hot_mobilesearch?channdlId=0").enqueue(new Callback() { |
|
|
|
|
@Override |
|
|
|
|
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { |
|
|
|
|
List<String> items = Hot.get(response.body().string()); |
|
|
|
|
mHandler.post(() -> mWordAdapter.setItems(items, null)); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void getSuggest(String text) { |
|
|
|
|
mBinding.hint.setText(R.string.search_suggest); |
|
|
|
|
OKHttp.newCall("https://suggest.video.iqiyi.com/?if=mobile&key=" + text).enqueue(new Callback() { |
|
|
|
|
@Override |
|
|
|
|
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { |
|
|
|
|
List<String> items = Suggest.get(response.body().string()); |
|
|
|
|
mHandler.post(() -> mWordAdapter.setItems(items, null)); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public void onItemClick(String text) { |
|
|
|
|
mBinding.keyword.setText(text); |
|
|
|
|
onSearch(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
@ -136,34 +149,50 @@ public class SearchActivity extends BaseActivity implements WordPresenter.OnClic |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public void onItemClick(String text) { |
|
|
|
|
mBinding.keyword.setText(text); |
|
|
|
|
onSearch(); |
|
|
|
|
public void onVoice() { |
|
|
|
|
if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { |
|
|
|
|
launcherString.launch(Manifest.permission.RECORD_AUDIO); |
|
|
|
|
} else { |
|
|
|
|
startListening(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void getHot() { |
|
|
|
|
OKHttp.newCall("https://node.video.qq.com/x/api/hot_mobilesearch?channdlId=0").enqueue(new Callback() { |
|
|
|
|
@Override |
|
|
|
|
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { |
|
|
|
|
List<String> items = Hot.get(response.body().string()); |
|
|
|
|
mHandler.post(() -> mWordAdapter.setItems(items, null)); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
private void startListening() { |
|
|
|
|
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); |
|
|
|
|
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); |
|
|
|
|
mBinding.keyboard.setVisibility(View.INVISIBLE); |
|
|
|
|
mBinding.voice.setVisibility(View.VISIBLE); |
|
|
|
|
mBinding.voice.startAnimation(mFlicker); |
|
|
|
|
mRecognizer.startListening(intent); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void getSuggest(String text) { |
|
|
|
|
OKHttp.newCall("https://suggest.video.iqiyi.com/?if=mobile&key=" + text).enqueue(new Callback() { |
|
|
|
|
@Override |
|
|
|
|
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { |
|
|
|
|
List<String> items = Suggest.get(response.body().string()); |
|
|
|
|
mHandler.post(() -> mWordAdapter.setItems(items, null)); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
private void stopListening() { |
|
|
|
|
mBinding.keyboard.setVisibility(View.VISIBLE); |
|
|
|
|
mBinding.voice.setVisibility(View.GONE); |
|
|
|
|
mBinding.voice.clearAnimation(); |
|
|
|
|
mRecognizer.stopListening(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void destroyRecognizer() { |
|
|
|
|
try { |
|
|
|
|
mRecognizer.destroy(); |
|
|
|
|
mRecognizer = null; |
|
|
|
|
} catch (Exception ignored) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public void onBackPressed() { |
|
|
|
|
if (mBinding.voice.getVisibility() == View.VISIBLE) { |
|
|
|
|
stopListening(); |
|
|
|
|
} else { |
|
|
|
|
super.onBackPressed(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
protected void onDestroy() { |
|
|
|
|
super.onDestroy(); |
|
|
|
|
mRecognizer.destroy(); |
|
|
|
|
destroyRecognizer(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|