I am searching Exoplayer using with ViewPager in java but can not find the full tutorial.
I have issue for stopping and pausing exoplayer while swiping another video.
Is there any tutorial please suggest me.
Adapter.java
package com.daasuu.gpuvideoandroid.Adapter;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.databinding.DataBindingUtil;
import androidx.recyclerview.widget.RecyclerView;
import com.daasuu.gpuvideoandroid.Activity.OtherUser.OtherUserProfileActivity;
import com.daasuu.gpuvideoandroid.Model.MainVideoDataModel;
import com.daasuu.gpuvideoandroid.R;
import com.daasuu.gpuvideoandroid.Utils.VideoCache;
import com.daasuu.gpuvideoandroid.databinding.ItemMainVideoBinding;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
import com.google.android.exoplayer2.ui.PlayerView;
import com.google.android.exoplayer2.ui.StyledPlayerView;
import com.google.android.exoplayer2.upstream.DefaultHttpDataSource;
import com.google.android.exoplayer2.upstream.cache.CacheDataSource;
import java.util.List;
public class MainVideoAdapter2 extends RecyclerView.Adapter<MainVideoAdapter2.MyViewHolder> {
private Context context;
private List<MainVideoDataModel> data;
private boolean likeFlag = false;
private boolean followFlag = false;
private boolean isPlaying = false;
ExoPlayer exoplayer;
StyledPlayerView styledPlayerView;
public MainVideoAdapter2(Context context, List<MainVideoDataModel> data) {
this.context = context;
this.data = data;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
ItemMainVideoBinding binding = DataBindingUtil.inflate(LayoutInflater.from(context), R.layout.item_main_video, parent, false);
return new MyViewHolder(binding);
}
#Override
public void onBindViewHolder(MainVideoAdapter2.MyViewHolder holder, int position) {
MainVideoDataModel model = data.get(position);
holder.setExoplayerStyled(model.getVideo_url());
}
#Override
public int getItemCount() {
return data.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private ItemMainVideoBinding binding;
public MyViewHolder(ItemMainVideoBinding binding) {
super(binding.getRoot());
this.binding = binding;
binding.imageUserMainVideo.setOnClickListener(this);
binding.videoView.setOnClickListener(this);
}
// styled exoplayer with cache
void setExoplayerStyled(String video_url){
binding.progressCircular.setVisibility(View.VISIBLE);
exoplayer = new ExoPlayer.Builder(context).build();
styledPlayerView = binding.videoStyledPlayerView;
styledPlayerView.hideController();
styledPlayerView.setUseController(false);
ProgressiveMediaSource mediaSource = new ProgressiveMediaSource.Factory(
new CacheDataSource.Factory()
.setCache(VideoCache.getInstance2(context))
.setUpstreamDataSourceFactory(new DefaultHttpDataSource.Factory()
.setUserAgent("rgcache"))
.setFlags(CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR)
).createMediaSource(MediaItem.fromUri(video_url));
exoplayer.seekTo(0);
exoplayer.prepare();
exoplayer.pause();
styledPlayerView.setPlayer(exoplayer);
exoplayer.setPlayWhenReady(false);
binding.videoStyledPlayerView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
#Override
public void onViewAttachedToWindow(View view) {
styledPlayerView.setKeepScreenOn(true);
exoplayer.addMediaSource(mediaSource);
exoplayer.prepare();
exoplayer.setPlayWhenReady(true);
exoplayer.setRepeatMode(exoplayer.REPEAT_MODE_ONE);
if(binding.videoStyledPlayerView.getPlayer() != null) {
binding.videoStyledPlayerView.getPlayer().play();
}
}
#Override
public void onViewDetachedFromWindow(View view) {
binding.videoStyledPlayerView.getPlayer().stop();
binding.videoStyledPlayerView.getPlayer().clearMediaItems();
exoplayer.seekTo(0);
exoplayer.setPlayWhenReady(false);
exoplayer.stop();
if(binding.videoStyledPlayerView.getPlayer() != null) {
binding.videoStyledPlayerView.getPlayer().pause();
}
}
});
//buffering
exoplayer.addListener(new Player.Listener() {
#Override
public void onIsLoadingChanged(boolean isLoading) {
Player.Listener.super.onIsLoadingChanged(isLoading);
// Log.e("onIsLoadingChanged", String.valueOf(isLoading));
}
#Override
public void onPlaybackStateChanged(int playbackState) {
Player.Listener.super.onPlaybackStateChanged(playbackState);
Log.e("onPlaybackStateChanged", String.valueOf(playbackState));
binding.imgVideoStop.setVisibility(View.GONE);
if (playbackState == 3){
binding.progressCircular.setVisibility(View.GONE);
}
}
#Override
public void onPlayWhenReadyChanged(boolean playWhenReady, int reason) {
Player.Listener.super.onPlayWhenReadyChanged(playWhenReady, reason);
}
});
// touch listener play & pause
binding.videoStyledPlayerView.getVideoSurfaceView().setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (isPlaying == false){
binding.imgVideoStop.setVisibility(View.VISIBLE);
isPlaying = true;
exoplayer.setPlayWhenReady(false);
}else{
binding.imgVideoStop.setVisibility(View.GONE);
isPlaying = false;
styledPlayerView.setKeepScreenOn(true);
styledPlayerView.setPlayer(exoplayer);
exoplayer.addMediaSource(mediaSource);
exoplayer.prepare();
exoplayer.setPlayWhenReady(true);
exoplayer.setRepeatMode(exoplayer.REPEAT_MODE_ONE);
}
}
});
}
//on click event
#Override
public void onClick(View v) {
if (v == binding.imageUserMainVideo) {
context.startActivity(new Intent(context, OtherUserProfileActivity.class));
}
if (v == binding.videoView) {
Log.e("isPlaying = " , String.valueOf(isPlaying));
if (isPlaying) {
binding.videoView.pause();
// binding.imgVideoStop.setVisibility(View.VISIBLE);
isPlaying = false;
} else {
binding.videoView.start();
// binding.imgVideoStop.setVisibility(View.GONE);
isPlaying = true;
}
}
}
}
}
item.xml
<com.google.android.exoplayer2.ui.StyledPlayerView
android:id="#+id/videoStyledPlayerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="visible"
app:animation_enabled="true"/>
Issues:
After a specific position, it plays previous videos when swipe to next video.
Plays multiple videos on swipe
On swipe back(previous videos) don't stops previous video.
How to stop when to redirect another activity.
Please suggest the solution.
You can use addOnPageChangeListener for getting the user interaction for the view pager. add this code snippet in the onCreate method.In my project ,I handle it like this ::
binding!!.mediaViewPager.addOnPageChangeListener(object : OnPageChangeListener {
override fun onPageScrolled(
position: Int,
positionOffset: Float,
positionOffsetPixels: Int
) {
if (exoPlayer.isPlaying) {
exoPlayer.pause()
}
}
override fun onPageSelected(position: Int) {
if (exoPlayer.isPlaying) {
exoPlayer.pause()
}
}
override fun onPageScrollStateChanged(state: Int) {
exoPlayer.pause()
}
})
Play Exo Player With PageViwer
Link:
https://github.com/google/ExoPlayer/issues/7947
Example:
https://github.com/kakajika/PlayerPagerExample
Related
I implemented searchView in android which filters data. It works correctly But after filtering data, when I add new data it does not show in recyclerView when I restart the app then it shows, I am also able to view that item after again searching something and then backspace it.
Here is My Adapter Class
package com.example.keepnotes;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.cardview.widget.CardView;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
Context context;
ArrayList<Notes> arrNotes;
DatabaseHelper databaseHelper;
RecyclerViewAdapter(Context context, ArrayList<Notes> arrNotes, DatabaseHelper databaseHelper) {
this.context = context;
this.arrNotes = arrNotes;
this.databaseHelper = databaseHelper;
}
public void setFilteredList(ArrayList<Notes> filteredList) {
this.arrNotes = filteredList;
notifyDataSetChanged();
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.single_view, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, #SuppressLint("RecyclerView") int position) {
holder.title.setText(arrNotes.get(position).title);
holder.body.setText(arrNotes.get(position).text);
holder.index.setText(String.valueOf(position + 1));
holder.llView.setOnClickListener(view -> {
Intent iNext = new Intent(context, ViewActivity.class);
iNext.putExtra("title", arrNotes.get(position).title);
iNext.putExtra("text", arrNotes.get(position).text);
iNext.putExtra("id", arrNotes.get(position).id);
context.startActivity(iNext);
});
holder.llView.setOnLongClickListener(view -> {
showDeleteDialog(position);
return true;
});
}
#Override
public int getItemCount() {
return arrNotes.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView title, body, index;
CardView llView;
public ViewHolder(View itemView) {
super(itemView);
title = itemView.findViewById(R.id.text_title_view);
body = itemView.findViewById(R.id.text_text_view);
index = itemView.findViewById(R.id.index);
llView = itemView.findViewById(R.id.card_View);
databaseHelper = DatabaseHelper.getDatabase(context);
}
}
private void showDeleteDialog(int position) {
AlertDialog.Builder alert = new AlertDialog.Builder(context)
.setTitle("Delete view")
.setMessage("Are you sure to delete")
.setIcon(R.drawable.ic_baseline_delete_24)
.setPositiveButton("yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
databaseHelper.notesDao().deleteNotes(new Notes(arrNotes.get(position).getId(), arrNotes.get(position).getTitle(), arrNotes.get(position).getText()));
}
})
.setNegativeButton("No", (dialogInterface, i) -> {
});
alert.show();
}
}
Here is My filterable function
private void filterList(String text) {
ArrayList<Notes> filteredList = new ArrayList<>();
for (Notes notes : arrNotes) {
if (notes.title.toLowerCase().contains(text.toLowerCase()) || notes.text.toLowerCase().contains(text.toLowerCase())) {
filteredList.add(notes);
}
if (!(filteredList.isEmpty())) {
adapter.setFilteredList(filteredList);
}
}
}
Here I implemented SearchView
searchView = findViewById(R.id.searchView);
searchView.clearFocus();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
filterList(newText);
return false;
}
});
I updated data using live data using this
modelView = new ViewModelProvider(this).get(notesModelView.class);
modelView.getAllNotes().observe(this, new Observer<List<Notes>>() {
#Override
public void onChanged(List<Notes> notes) {
arrNotes.clear();
arrNotes.addAll(notes);
adapter.notifyDataSetChanged();
}
});
Modify your filterList() function like this -
private void filterList(String text) {
if (!text.trim().isEmpty()) {
ArrayList<Notes> filteredList = new ArrayList<>();
for (Notes notes : arrNotes) {
if (notes.title.toLowerCase().contains(text.toLowerCase()) || notes.text.toLowerCase().contains(text.toLowerCase())) {
filteredList.add(notes);
}
adapter.setFilteredList(filteredList);
}
}else{
adapter.setFilteredList(arrNotes);
}
}
I am creating a document arrangement activity with RecyclerView. I want to arrange the document with drag and drop. It was done by using ItemTouchHelper.Callbackbut after that I can't set the page number after the OnItemMove callback. what should I do?
EDIT: added code snippet
package adapters;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.pdf.PdfRenderer;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.RecyclerView;
import com.mobilix.docscanner.R;
import java.util.ArrayList;
import java.util.Collections;
import helper.ItemTouchHelperAdapter;
import helper.ItemTouchHelperViewHolder;
import helper.OnStartDragListener;
import helper.SimpleItemTouchHelperCallback;
public class PageAjdustAdapter extends RecyclerView.Adapter<PageAjdustAdapter.PageAdjustHolder> implements ItemTouchHelperAdapter, OnStartDragListener {
private final String TAG = getClass().getName();
Context mContext;
ArrayList<PdfPage> pdfPages = new ArrayList<>();
private ItemTouchHelper itemTouchHelper;
public PageAjdustAdapter(Context context, ArrayList<PdfPage> pages) {
this.mContext = context;
pdfPages = pages;
ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(this);
itemTouchHelper = new ItemTouchHelper(callback);
itemTouchHelper.attachToRecyclerView(((Activity) context).findViewById(R.id.rcvPageArrange));
}
#NonNull
#Override
public PageAdjustHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.item_page_adajustment, parent, false);
return new PageAdjustHolder(view);
}
#Override
public void onBindViewHolder(#NonNull PageAdjustHolder holder, int position) {
Log.d(TAG, "onBindViewHolder: ");
holder.ivPage.setImageBitmap(pdfPages.get(position).bitmap);
holder.cbPage.setChecked(pdfPages.get(position).isSelected);
holder.tvPageNo.setText(String.valueOf(position + 1));
holder.cbPage.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
pdfPages.get(holder.getAdapterPosition()).isSelected = isChecked;
}
});
holder.ivRotate.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int pos = holder.getAdapterPosition();
pdfPages.get(pos).bitmap = Bitmap.createBitmap(//
pdfPages.get(pos).bitmap, 0, 0, pdfPages.get(pos).bitmap.getWidth(),//
pdfPages.get(pos).bitmap.getHeight(), pdfPages.get(pos).matrix, true);//
notifyItemChanged(pos);
}
});
}
#Override
public int getItemCount() {
return pdfPages.size();
}
#Override
public boolean onItemMove(int fromPosition, int toPosition) {
Log.d(TAG, "onItemMove: ->fp " + (fromPosition + 1) + " tp-> " + (toPosition + 1));
Collections.swap(pdfPages, fromPosition, toPosition);
notifyItemMoved(fromPosition, toPosition);
return false;
}
#Override
public void onItemDismiss(int position) {
pdfPages.remove(position);
notifyItemRemoved(position);
}
#Override
public void onStartDrag(RecyclerView.ViewHolder viewHolder) {
itemTouchHelper.startDrag(viewHolder);
}
public static class PageAdjustHolder extends RecyclerView.ViewHolder implements
ItemTouchHelperViewHolder {
ImageView ivPage, ivRotate;
CheckBox cbPage;
TextView tvPageNo;
public PageAdjustHolder(#NonNull View itemView) {
super(itemView);
ivPage = itemView.findViewById(R.id.ivPage);
ivRotate = itemView.findViewById(R.id.ivRotate);
cbPage = itemView.findViewById(R.id.cbPage);
tvPageNo = itemView.findViewById(R.id.tvPageNo);
}
#Override
public void onItemSelected() {
}
#Override
public void onItemClear() {
}
}
public static class PdfPage {
PdfRenderer.Page page;
Bitmap bitmap;
boolean isSelected;
Matrix matrix;
int rotate = 0;
public PdfPage(PdfRenderer.Page page, Bitmap bitmap) {
this.page = page;
this.bitmap = bitmap;
matrix = new Matrix();
rotate += 90;
matrix.postRotate(90);//martix work on +=90
}
}
}
You have to call notifyDataSetChanged() when an item position is changed. The easiest way it to used onItemClear(), it will be called when an item is de-selected. Add it like following.
#Override
public void onItemClear() {
notifyDataSetChanged();
}
One thing you have to add is check weather the position is actually changed after the drag operation or not other wise it will always update the whole dataset whenever an item is selected and than de-selected.
Edit
Create a local variable in view-holder class. Than you just have to set it in onItemSelected() and check it in onItemClear();
#Override
public void onItemSelected() {
lastpos = getAdapterPosition();
}
#Override
public void onItemClear() {
if(lastpos != getAdapterPosition())
notifyDataSetChanged();
}
I'm using recycleview in google cloud speech api.
And I would like to put the strings in the recycleview into a single edit text.
How do I move a string from a recycleview into a single text?
enter code here
/*
* Copyright 2016 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.cloud.android.speech;
import android.Manifest;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.icu.util.ValueIterator;
import android.os.Bundle;
import android.os.IBinder;
import android.sax.Element;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.res.ResourcesCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity implements
MessageDialogFragment.Listener {
static EditText edit1;
static EditText edit2;
static EditText edit3;
static String a1,a2;
static String[] b1,b2;
static int count=0;
Button btn;
private static final String FRAGMENT_MESSAGE_DIALOG = "message_dialog";
private static final String STATE_RESULTS = "results";
private static final int REQUEST_RECORD_AUDIO_PERMISSION = 1;
private SpeechService mSpeechService;
private VoiceRecorder mVoiceRecorder;
private final VoiceRecorder.Callback mVoiceCallback = new
VoiceRecorder.Callback() {
#Override
public void onVoiceStart() {
showStatus(true);
if (mSpeechService != null) {
mSpeechService.startRecognizing(mVoiceRecorder.getSampleRate());
}
}
#Override
public void onVoice(byte[] data, int size) {
if (mSpeechService != null) {
mSpeechService.recognize(data, size);
}
}
#Override
public void onVoiceEnd() {
showStatus(false);
if (mSpeechService != null) {
mSpeechService.finishRecognizing();
}
}
};
// Resource caches
private int mColorHearing;
private int mColorNotHearing;
// View references
private TextView mStatus;
private TextView mText;
private ResultAdapter mAdapter;
private RecyclerView mRecyclerView;
private final ServiceConnection mServiceConnection = new
ServiceConnection()
{
#Override
public void onServiceConnected(ComponentName componentName, IBinder
binder) {
mSpeechService = SpeechService.from(binder);
mSpeechService.addListener(mSpeechServiceListener);
mStatus.setVisibility(View.VISIBLE);
}
#Override
public void onServiceDisconnected(ComponentName componentName) {
mSpeechService = null;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
edit1=(EditText) findViewById(R.id.edit1);
edit2=(EditText) findViewById(R.id.edit2);
edit3=(EditText) findViewById(R.id.edit3);
btn=(Button)findViewById(R.id.button);
final Resources resources = getResources();
final Resources.Theme theme = getTheme();
mColorHearing = ResourcesCompat.getColor(resources,
R.color.status_hearing, theme);
mColorNotHearing = ResourcesCompat.getColor(resources,
R.color.status_not_hearing, theme);
setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
mStatus = (TextView) findViewById(R.id.status);
mText = (TextView) findViewById(R.id.text);
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
final ArrayList<String> results = savedInstanceState == null ? null :
savedInstanceState.getStringArrayList(STATE_RESULTS);
mAdapter = new ResultAdapter(results);
mRecyclerView.setAdapter(mAdapter);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
}
});
}
#Override
protected void onStart() {
super.onStart();
// Prepare Cloud Speech API
bindService(new Intent(this, SpeechService.class), mServiceConnection,
BIND_AUTO_CREATE);
// Start listening to voices
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.RECORD_AUDIO)
== PackageManager.PERMISSION_GRANTED) {
startVoiceRecorder();
} else if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.RECORD_AUDIO)) {
showPermissionMessageDialog();
} else {
ActivityCompat.requestPermissions(this, new String[]
{Manifest.permission.RECORD_AUDIO},
REQUEST_RECORD_AUDIO_PERMISSION);
}
}
#Override
protected void onStop() {
// Stop listening to voice
stopVoiceRecorder();
// Stop Cloud Speech API
mSpeechService.removeListener(mSpeechServiceListener);
unbindService(mServiceConnection);
mSpeechService = null;
super.onStop();
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (mAdapter != null) {
outState.putStringArrayList(STATE_RESULTS, mAdapter.getResults());
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[]
permissions,
#NonNull int[] grantResults) {
if (requestCode == REQUEST_RECORD_AUDIO_PERMISSION) {
if (permissions.length == 1 && grantResults.length == 1
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
startVoiceRecorder();
} else {
showPermissionMessageDialog();
}
} else {
super.onRequestPermissionsResult(requestCode, permissions,
grantResults);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_file:
mSpeechService.recognizeInputStream
(getResources().openRawResource(R.raw.audio));
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void startVoiceRecorder() {
if (mVoiceRecorder != null) {
mVoiceRecorder.stop();
}
mVoiceRecorder = new VoiceRecorder(mVoiceCallback);
mVoiceRecorder.start();
}
private void stopVoiceRecorder() {
if (mVoiceRecorder != null) {
mVoiceRecorder.stop();
mVoiceRecorder = null;
}
}
private void showPermissionMessageDialog() {
MessageDialogFragment
.newInstance(getString(R.string.permission_message))
.show(getSupportFragmentManager(), FRAGMENT_MESSAGE_DIALOG);
}
private void showStatus(final boolean hearingVoice) {
runOnUiThread(new Runnable() {
#Override
public void run() {
mStatus.setTextColor(hearingVoice ? mColorHearing :
mColorNotHearing);
}
});
}
#Override
public void onMessageDialogDismissed() {
ActivityCompat.requestPermissions(this, new String[]
{Manifest.permission.RECORD_AUDIO},
REQUEST_RECORD_AUDIO_PERMISSION);
}
private final SpeechService.Listener mSpeechServiceListener =
new SpeechService.Listener() {
#Override
public void onSpeechRecognized(final String text, final boolean
isFinal) {
if (isFinal) {
mVoiceRecorder.dismiss();
}
if (mText != null && !TextUtils.isEmpty(text)) {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (isFinal) {
mText.setText(null);
mAdapter.addResult(text);
mRecyclerView.smoothScrollToPosition(0);
} else {
mText.setText(text);
}
}
});
}
}
};
private static class ViewHolder extends RecyclerView.ViewHolder {
TextView text;
ViewHolder(LayoutInflater inflater, ViewGroup parent) {
super(inflater.inflate(R.layout.item_result, parent, false));
text = (TextView) itemView.findViewById(R.id.text);
}
}
private static class ResultAdapter extends
RecyclerView.Adapter<ViewHolder> {
private final ArrayList<String> mResults = new ArrayList<>();
ResultAdapter(ArrayList<String> results) {
if (results != null) {
mResults.addAll(results);
}
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(parent.getContext()),
parent);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.text.setText(mResults.get(position));
}
#Override
public int getItemCount() {
return mResults.size();
}
void addResult(String result) {
mResults.add(0, result);
notifyItemInserted(0);
}
public ArrayList<String> getResults() {
return mResults;
}
}
}
here is java code.
if you know the answer, let me know..
I tried but it doesn't work. The editview doesn't show all of texts in reclycleview...
Create a TextView element outside of that recycle view. Then initialize it onCreate() method.
You need to extract text from that recycle view. I have no idea about that u hold data. Anyhow get a text from that.
Then updateText using textView.setText(...) when that recycleText updated
Define TextView like this in mainActivity and initalize it in onCreate
static TextView recyText;
in
oncreate(){
....
recyText=(TextView) findViewById(R.id.recyText);
}
the update it in below code segment
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.text.setText(mResults.get(position));
recyText.setText(recyText.getText()+ " " +mResults.get(position))
}
I have implemented the Player and now there is a problem. When the video is playing and if the app is closed and resumed, the video screen freezes. I even saw the ExoPlayer Demo Activity from Google for better understanding but I could not get through it for implementing in my app. I have attached the Player Activity here and for the full code, I am sharing the GitHub repository for all files.
RecipeStepDetailFragment.java
package com.example.android.recipe.ui;
import android.content.Context;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.example.android.recipe.R;
import com.example.android.recipe.pojo.Recipe;
import com.example.android.recipe.pojo.Step;
import com.google.android.exoplayer2.LoadControl;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
import com.google.android.exoplayer2.ui.SimpleExoPlayerView;
import java.util.ArrayList;
import java.util.List;
import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.trackselection.AdaptiveVideoTrackSelection;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.util.Util;
import com.squareup.picasso.Picasso;
import static com.example.android.recipe.ui.RecipeActivity.SELECTED_INDEX;
import static com.example.android.recipe.ui.RecipeActivity.SELECTED_RECIPES;
import static com.example.android.recipe.ui.RecipeActivity.SELECTED_STEPS;
public class RecipeStepDetailFragment extends Fragment {
private SimpleExoPlayerView simpleExoPlayerView;
private SimpleExoPlayer player;
private BandwidthMeter bandwidthMeter;
private ArrayList<Step> steps = new ArrayList<>();
private int selectedIndex;
private Handler mainHandler;
ArrayList<Recipe> recipe;
String recipeName;
public RecipeStepDetailFragment() { }
private ListItemClickListener itemClickListener;
public interface ListItemClickListener {
void onListItemClick(List<Step> allSteps,int Index,String recipeName);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
TextView textView;
mainHandler = new Handler();
bandwidthMeter = new DefaultBandwidthMeter();
itemClickListener =(RecipeDetailActivity)getActivity();
recipe = new ArrayList<>();
if(savedInstanceState != null) {
steps = savedInstanceState.getParcelableArrayList(SELECTED_STEPS);
selectedIndex = savedInstanceState.getInt(SELECTED_INDEX);
recipeName = savedInstanceState.getString("Title");
}
else {
steps =getArguments().getParcelableArrayList(SELECTED_STEPS);
if (steps!=null) {
steps =getArguments().getParcelableArrayList(SELECTED_STEPS);
selectedIndex=getArguments().getInt(SELECTED_INDEX);
recipeName=getArguments().getString("Title");
}
else {
recipe =getArguments().getParcelableArrayList(SELECTED_RECIPES);
steps=(ArrayList<Step>)recipe.get(0).getSteps();
selectedIndex=0;
}
}
View rootView = inflater.inflate(R.layout.recipe_step_detail_fragment_body_part, container, false);
textView = (TextView) rootView.findViewById(R.id.recipe_step_detail_text);
textView.setText(steps.get(selectedIndex).getDescription());
textView.setVisibility(View.VISIBLE);
simpleExoPlayerView = (SimpleExoPlayerView) rootView.findViewById(R.id.playerView);
simpleExoPlayerView.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FIT);
String videoURL = steps.get(selectedIndex).getVideoURL();
if (rootView.findViewWithTag("sw600dp-port-recipe_step_detail")!=null) {
recipeName=((RecipeDetailActivity) getActivity()).recipeName;
((RecipeDetailActivity) getActivity()).getSupportActionBar().setTitle(recipeName);
}
String imageUrl=steps.get(selectedIndex).getThumbnailURL();
if (imageUrl!="") {
Uri builtUri = Uri.parse(imageUrl).buildUpon().build();
ImageView thumbImage = (ImageView) rootView.findViewById(R.id.thumbImage);
Picasso.with(getContext()).load(builtUri).into(thumbImage);
}
if (!videoURL.isEmpty()) {
initializePlayer(Uri.parse(steps.get(selectedIndex).getVideoURL()));
if (rootView.findViewWithTag("sw600dp-land-recipe_step_detail")!=null) {
getActivity().findViewById(R.id.fragment_container2).setLayoutParams(new LinearLayout.LayoutParams(-1,-2));
simpleExoPlayerView.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FIXED_WIDTH);
}
else if (isInLandscapeMode(getContext())){
textView.setVisibility(View.GONE);
}
}
else {
player=null;
simpleExoPlayerView.setForeground(ContextCompat.getDrawable(getContext(), R.drawable.ic_visibility_off_white_36dp));
simpleExoPlayerView.setLayoutParams(new LinearLayout.LayoutParams(300, 300));
}
Button mPrevStep = (Button) rootView.findViewById(R.id.previousStep);
Button mNextstep = (Button) rootView.findViewById(R.id.nextStep);
mPrevStep.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
if (steps.get(selectedIndex).getId() > 0) {
if (player!=null){
player.stop();
}
itemClickListener.onListItemClick(steps,steps.get(selectedIndex).getId() - 1,recipeName);
}
else {
Toast.makeText(getActivity(),"You already are in the First step of the recipe", Toast.LENGTH_SHORT).show();
}
}});
mNextstep.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
int lastIndex = steps.size()-1;
if (steps.get(selectedIndex).getId() < steps.get(lastIndex).getId()) {
if (player!=null){
player.stop();
}
itemClickListener.onListItemClick(steps,steps.get(selectedIndex).getId() + 1,recipeName);
}
else {
Toast.makeText(getContext(),"You already are in the Last step of the recipe", Toast.LENGTH_SHORT).show();
}
}});
return rootView;
}
private void initializePlayer(Uri mediaUri) {
if (player == null) {
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveVideoTrackSelection.Factory(bandwidthMeter);
DefaultTrackSelector trackSelector = new DefaultTrackSelector(mainHandler, videoTrackSelectionFactory);
LoadControl loadControl = new DefaultLoadControl();
player = ExoPlayerFactory.newSimpleInstance(getContext(), trackSelector, loadControl);
simpleExoPlayerView.setPlayer(player);
String userAgent = Util.getUserAgent(getContext(), "Baking App");
MediaSource mediaSource = new ExtractorMediaSource(mediaUri, new DefaultDataSourceFactory(getContext(), userAgent), new DefaultExtractorsFactory(), null, null);
player.prepare(mediaSource);
player.setPlayWhenReady(true);
}
}
#Override
public void onSaveInstanceState(Bundle currentState) {
super.onSaveInstanceState(currentState);
currentState.putParcelableArrayList(SELECTED_STEPS,steps);
currentState.putInt(SELECTED_INDEX,selectedIndex);
currentState.putString("Title",recipeName);
}
public boolean isInLandscapeMode( Context context ) {
return (context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE);
}
#Override
public void onDetach() {
super.onDetach();
if (player!=null) {
player.stop();
player.release();
}
}
#Override
public void onDestroyView() {
super.onDestroyView();
if (player!=null) {
player.stop();
player.release();
player=null;
}
}
#Override
public void onStop() {
super.onStop();
if (player!=null) {
player.stop();
player.release();
}
}
#Override
public void onPause() {
super.onPause();
if (player!=null) {
player.stop();
player.release();
}
}
}
Complete Project Repository: https://github.com/mtp2697/Udacity-AndroidDeveloperNanodegree-BakingApp
Help with the restoring of the state of video player for onPause() and onResume()
Thanks,
Praveen Thirumurugan.
I faced the same problem in my submission for the baking app and I did something like this:
private void initPlayer() {
// Exoplayer
// 1. Create a default TrackSelector
// Handler mainHandler = new Handler();
videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
RenderersFactory render = new DefaultRenderersFactory(getContext());
mainHandler = new Handler();
if (CookieHandler.getDefault() != DEFAULT_COOKIE_MANAGER) {
CookieHandler.setDefault(DEFAULT_COOKIE_MANAGER);
}
// 2. Create a default LoadControl
LoadControl loadControl = new DefaultLoadControl();
// 3. Create the player
recipeVideoPlayer = ExoPlayerFactory.newSimpleInstance(render, trackSelector, loadControl);
// exoPlayerView = (SimpleExoPlayerView) v.findViewById(R.id.exoplayer_recipe);
// Set media controller
mExoplayer.setUseController(true);
mExoplayer.setControllerVisibilityListener(this);
mExoplayer.requestFocus();
// Bind the player to the view.
mExoplayer.setPlayer(recipeVideoPlayer);
if (TextUtils.isEmpty(mSteps.getVideoURL())) {
mExoplayer.setVisibility(View.GONE);
} else {
mExoplayer.setVisibility(View.VISIBLE);
Uri video = Uri.parse(mSteps.getVideoURL());
DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(getContext(), Util.getUserAgent(getContext(), "recipes"), null);
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
MediaSource videoSource = new ExtractorMediaSource(video, dataSourceFactory, extractorsFactory, mainHandler, null);
boolean haveResumePosition = resumeWindow != C.INDEX_UNSET;
if (haveResumePosition) {
recipeVideoPlayer.seekTo(resumeWindow, resumePosition);
}
recipeVideoPlayer.prepare(videoSource, !haveResumePosition, false);
recipeVideoPlayer.setPlayWhenReady(true);
recipeVideoPlayer.addListener(new ExoPlayer.EventListener() {
#Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
}
#Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
// Toast.makeText(getContext(), "Track changed" + trackSelections.length, Toast.LENGTH_SHORT).show();
//
}
#Override
public void onLoadingChanged(boolean isLoading) {
}
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
}
#Override
public void onPlayerError(ExoPlaybackException error) {
clearResumePosition();
}
#Override
public void onPositionDiscontinuity() {
// updateResumePosition();
}
#Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
}
});
}
}
private void releasePlayer() {
if (recipeVideoPlayer != null) {
updateResumePosition();
recipeVideoPlayer.stop();
recipeVideoPlayer.release();
recipeVideoPlayer = null;
}
}
#Override
public void onResume() {
super.onResume();
if (recipeVideoPlayer == null) {
initPlayer();
}
}
#Override
public void onPause() {
super.onPause();
releasePlayer();
}
you can refer my project here
Base on this instructions I've created RecyclerView filtering in my app. Almost everything works fine but there are 2 strange things.
When I input text into search view and there is only one item which meets requirements until I hide keyboard I can't see this item.
Second problem is more complicated because it occurs from time to time. My item in RecyclerView has an image in background and not always when filtering image is loaded properly.
Because I now my description might be unclear here is an gif which shows the problem:
Here is my adapter class:
package com.ostojan.x360.view;
import android.support.v7.util.SortedList;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.ostojan.x360.R;
import com.ostojan.x360.model.Game;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class GameAdapter extends RecyclerView.Adapter<GameViewHolder> {
private SortedList<Game> games;
private ArrayList<Game> allGames;
private View.OnClickListener onClickListener;
public GameAdapter(View.OnClickListener onClickListener, List<Game> games) {
this(onClickListener);
this.games.addAll(games);
this.allGames.addAll(games);
}
public GameAdapter(View.OnClickListener onClickListener) {
this.onClickListener = onClickListener;
this.games = new SortedList<Game>(Game.class, new GamesSortedListCallback(this));
this.allGames = new ArrayList<>();
}
#Override
public GameViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_game, parent, false);
view.setOnClickListener(onClickListener);
return new GameViewHolder(view);
}
#Override
public void onBindViewHolder(GameViewHolder holder, int position) {
Game game = games.get(position);
holder.title.setText(game.getTitle());
Picasso.with(holder.itemView.getContext())
.load(game.getCoverLink().toString())
.placeholder(R.drawable.ic_loading)
.fit()
.centerCrop()
.error(R.drawable.ic_error)
.into(holder.coverImage);
}
#Override
public int getItemCount() {
return games.size();
}
public void add(Game game) {
this.games.add(game);
this.allGames.add(game);
notifyDataSetChanged();
}
public void addAll(Collection<Game> games) {
this.games.addAll(games);
this.allGames.addAll(games);
notifyDataSetChanged();
}
public void remove(Game game) {
games.beginBatchedUpdates();
games.remove(game);
allGames.remove(game);
games.endBatchedUpdates();
}
public void replaceAll(Collection<Game> games) {
this.games.beginBatchedUpdates();
List<Game> gamesToRemove = new ArrayList<>();
for (int i = 0; i < this.games.size(); i++) {
Game game = this.games.get(i);
if (!games.contains(game)) {
gamesToRemove.add(game);
}
}
for (Game game : gamesToRemove) {
this.games.remove(game);
}
this.games.addAll(games);
this.games.endBatchedUpdates();
}
public Game get(int index) {
return this.games.get(index);
}
public Collection<Game> getGames() {
return allGames;
}
public void clear() {
this.games.clear();
notifyDataSetChanged();
}
public void search(String query) {
replaceAll(filterGames(query));
}
private Collection<Game> filterGames(String query) {
query = query.toLowerCase();
List<Game> filteredGames = new ArrayList<>();
for (Game game : allGames) {
String gameTitle = game.getTitle().toLowerCase();
if (gameTitle.contains(query)) {
filteredGames.add(game);
}
}
return filteredGames;
}
}
View holder:
package com.ostojan.x360.view;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.ostojan.x360.R;
import butterknife.BindView;
import butterknife.ButterKnife;
public class GameViewHolder extends RecyclerView.ViewHolder {
#BindView(R.id.text_title)
TextView title;
#BindView(R.id.image_cover)
ImageView coverImage;
public GameViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
SortedList callback:
package com.ostojan.x360.view;
import android.support.v7.util.SortedList;
import android.support.v7.widget.RecyclerView;
import com.ostojan.x360.model.Game;
import java.util.Comparator;
public class GamesSortedListCallback extends SortedList.Callback<Game> {
private static final Comparator<Game> GAMES_COMPARATOR = new Comparator<Game>() {
#Override
public int compare(Game o1, Game o2) {
return o1.getId().compareTo(o2.getId());
}
};
private RecyclerView.Adapter<GameViewHolder> adapter;
public GamesSortedListCallback(RecyclerView.Adapter<GameViewHolder> adapter) {
this.adapter = adapter;
}
#Override
public int compare(Game o1, Game o2) {
return GAMES_COMPARATOR.compare(o1, o2);
}
#Override
public void onChanged(int position, int count) {
adapter.notifyItemRangeChanged(position, count);
}
#Override
public boolean areContentsTheSame(Game oldItem, Game newItem) {
return oldItem.equals(newItem);
}
#Override
public boolean areItemsTheSame(Game item1, Game item2) {
return item1.getId() == item1.getId();
}
#Override
public void onInserted(int position, int count) {
adapter.notifyItemRangeInserted(position, count);
}
#Override
public void onRemoved(int position, int count) {
adapter.notifyItemRangeRemoved(position, count);
}
#Override
public void onMoved(int fromPosition, int toPosition) {
adapter.notifyItemMoved(fromPosition, toPosition);
}
}
And here how I call filtering from activity:
RecyclerView gamesList;
GameAdapter gamesAdapter;
#Override
public boolean onQueryTextSubmit(String query) {
onQueryTextChange(query);
return true;
}
#Override
public boolean onQueryTextChange(String newText) {
gamesAdapter.search(newText);
gamesList.scrollToPosition(0);
return true;
}