What I have
My app has only one activity and all other are fragments
One of the fragment displays a listview that is populated from datbase through a cursor adapter.
My Problem
Everytime the screen rotates or i return back to the app after pressing home button, what i see is that I have another listview that lies over another one i.e another same listview is also populated over pre existing one.
Here is my code
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.tasks_list_frag, container, false);
Log.d("HirakDebug", "tasksListFrag View Created");
tasks_Database_Operations tasksDatabaseOperations = new tasks_Database_Operations(getActivity());
Cursor cursor = tasksDatabaseOperations.readData();
taskslist = (SwipeListView) view.findViewById(R.id.tasks_list);
adapter = new tasksCursorAdapter(getActivity(), cursor, CursorAdapter.FLAG_AUTO_REQUERY);
taskslist.setAdapter(adapter);
delete = (Button) view.findViewById(R.id.deleteAll);
delete.setOnClickListener(this);
taskslist.setSwipeListViewListener(new BaseSwipeListViewListener() {
#Override
public void onOpened(int position, boolean toRight) {
}
#Override
public void onClosed(int position, boolean fromRight) {
}
#Override
public void onListChanged() {
}
#Override
public void onMove(int position, float x) {
}
#Override
public void onStartOpen(int position, int action, boolean right) {
Log.d("swipe", String.format("onStartOpen %d - action %d", position, action));
}
#Override
public void onStartClose(int position, boolean right) {
Log.d("swipe", String.format("onStartClose %d", position));
}
#Override
public void onClickBackView(int position) {
Log.d("swipe", String.format("onClickBackView %d", position));
taskslist.closeAnimate(position);//when you touch back view it will close
}
#Override
public void onDismiss(int[] reverseSortedPositions) {
}
});
taskslist.setSwipeMode(SwipeListView.SWIPE_MODE_RIGHT); // there are five swiping modes
// there are four swipe actions
taskslist.setSwipeActionRight(SwipeListView.SWIPE_ACTION_REVEAL);
taskslist.setOffsetRight(convertDpToPixel(80f)); // right side offset
taskslist.setAnimationTime(500); // Animation time
// enable or disable SwipeOpenOnLongPress
Log.d("HirakDebug", "tasksListFrag Adapter set");
return view;
}
public int convertDpToPixel(float dp) {
DisplayMetrics metrics = getResources().getDisplayMetrics();
float px = dp * (metrics.densityDpi / 160f);
return (int) px;
}
#Override
public void onResume() {
super.onResume();
Log.d("HirakDebug", "taskListFrag resumed");
getRetainInstance();
}
#Override
public void setRetainInstance(boolean retain) {
super.setRetainInstance(true);
}
#Override
public void onPause() {
super.onPause();
Log.d("LifeCycle", "tLF Pause");
}
#Override
public void onStop() {
super.onStop();
Log.d("LifeCycle", "tLF Stop");
}
#Override
public void onDestroyView() {
super.onDestroyView();
Log.d("LifeCycle", "tLF DestroyView");
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d("LifeCycle", "tLF Destroy");
}
#Override
public void onDetach() {
super.onDetach();
Log.d("LifeCycle", "tLF Detach");
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
Log.d("LifeCycle", "tLF Attach");
}
#Override
public void onStart() {
super.onStart();
Log.d("LifeCycle", "tLF Start");
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.d("LifeCycle", "tLF saveInstance State");
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onClick(View v) {
if (v == delete) {
Log.d("HirakDebug", "Delete Button Pressed");
tasks_Database_Operations tasksDatabaseOperations = new tasks_Database_Operations(getActivity());
SQLiteDatabase sqLiteDatabase = tasksDatabaseOperations.getWritableDatabase();
sqLiteDatabase.delete(tasksDatabaseOperations.ASSIS_TASK_TABLE_NAME, null, null);
Log.d("HirakDebug", "tLF All Data Deleted");
adapter.notifyDataSetChanged();
Log.d("HirakDebug", "tLF ArrayList Cleared");
sqLiteDatabase.close();
}
}
Just check inside your activity onCreate method
if (saveInstance == null) {
mFragment = new Fragment();
fm.beginTransaction().replace(mFragment, TAG_TASK_FRAGMENT).commit();
}
Related
First, none of the solution worked provided on stackoverflow because of either change in the Android or my problem was totally different.
What I want to achive - I want to detect when my view (for example - ThirdFragment) comes in focus and becomes visible to user. Also, it should detect when user swipes away from the current view to next view or previous view.
Why I want to do that? - Well, I am creating a media player in one of the view as shown in the example fragment code and user can play any music listed in the view by tapping on the music in the list but when user swipes to next screen it should stop.
What is the problem? - The problem is mediaplayer doesn't stop right after switching from the view but [***] if I swipe two step away, it stops but not cleanly, it jitters in the background.
What I have tried before - I have tried this setUserVisibleHint but it wasn't working because it has been depricated. onPause, onDetach, onStop none is working as mentioned here[***]
/*------Home ViewPager----- */
public class HomeFragment extends Fragment {
private ViewPager viewPager;
private String[] titles = {"First","Second","Third","Fourth"};
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
TextView subtitle = getActivity().findViewById(R.id.toolbar_right_subtitle);
subtitle.setText(titles[0]);
return inflater.inflate(R.layout.fragment_home, container, false);
}
#Override
public void onViewCreated(#NonNull final View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
/* pages */
viewPager = view.findViewById(R.id.interfaces);
InterfaceAdapter interfacePagerAdapter = new InterfaceAdapter(getActivity().getSupportFragmentManager(),0);
viewPager.setAdapter(interfacePagerAdapter);
viewPager.setCurrentItem(0);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
TextView subtitle = getActivity().findViewById(R.id.toolbar_right_subtitle);
subtitle.setText(titles[position]);
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
}
}
/*---------- My Fragment Adapter --------- */
public class InterfaceAdapter extends FragmentStatePagerAdapter {
public InterfaceAdapter(#NonNull FragmentManager fm, int behavior) {
super(fm, behavior);
}
#NonNull
#Override
public Fragment getItem(int position) {
switch (position){
case 0:
return new FirstFragment();
case 1:
return new SecondFragment();
case 2:
return new ThirdFragment();
case 3:
return new FourthFragment();
default:
return null;
}
}
#Override
public int getCount() {
return 4;
}
}
/*---------- One of my Fragment --------- */
public class ThirdFragment extends Fragment {
//------Media Player ----------
private MusicAdapter musicAdapter;
private List<SongData> songsList;
private ListView listView;
private static MediaPlayer mediaPlayer;
private Handler handler = new Handler();
private Runnable runnable;
private ImageView playButton, prevButton, nextButton;
private SeekBar seekbarPayer;
private TextView playerTime,songTitle;
private int pos = 0;
public ThirdFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
eventViewModels = new ViewModelProvider((FragmentActivity) getContext()).get(EventViewModels.class);
mediaPlayer = new MediaPlayer();
getAllSongs();
return inflater.inflate(R.layout.fragment_focus, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//--------Music Player---------------
mediaPlayer = new MediaPlayer();
playButton = view.findViewById(R.id.playpause_player);
prevButton = view.findViewById(R.id.prev_player);
nextButton = view.findViewById(R.id.next_player);
seekbarPayer = view.findViewById(R.id.seekbar_player);
playerTime = view.findViewById(R.id.playertime);
songTitle = view.findViewById(R.id.songname);
songTitle.setSelected(true);
songsList = new ArrayList<>();
musicAdapter = new MusicAdapter(getActivity(), songsList);
listView = view.findViewById(R.id.songList);
listView.setAdapter(musicAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
pos = position;
playMusicFile(songsList.get(position).getUri(),songsList.get(position).getTitle());
}
});
//play or pause music
playButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
playPause();
}
});
//next music
nextButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (pos < songsList.size() - 1) {
pos++;
} else {
pos = 0;
}
playMusicFile(songsList.get(pos).getUri(),songsList.get(pos).getTitle());
}
});
//next music
prevButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (pos > 0) {
pos--;
} else {
pos = songsList.size() - 1;
}
playMusicFile(songsList.get(pos).getUri(),songsList.get(pos).getTitle());
}
});
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
eventViewModels.getTrigger().observe((LifecycleOwner) getContext(), new Observer<Integer>() {
#Override
public void onChanged(#Nullable final Integer val) {
assert val!=null;
Log.d("ObserverValue",val+"");
}
});
}
#Override
public void onStart() {
super.onStart();
getAllSongs();
Log.d("SystemStatus","Start");
}
#Override
public void onResume() {
super.onResume();
getAllSongs();
Log.d("SystemStatus","Resume");
}
#Override
public void onStop() {
super.onStop();
stopPlayer();
Log.d("SystemStatus","Stop");
}
#Override
public void onDetach() {
super.onDetach();
stopPlayer();
Log.d("SystemStatus","Detach");
}
#Override
public void onPause() {
super.onPause();
stopPlayer();
Log.d("SystemStatus","Pause");
if (eventViewModels != null && eventViewModels.getTrigger().hasObservers()) {
eventViewModels.getTrigger().removeObservers(this);
}
}
//---Media Player-----
private void getAllSongs() {
/*
* get all songs and add it into songlist
*/
}
private void playMusicFile(String filePath,final String title){
if(mediaPlayer!=null) {
mediaPlayer.reset();
try {
mediaPlayer.setDataSource(filePath);
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
stopPlayer();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void playPause() {
if (!mediaPlayer.isPlaying()) {
mediaPlayer.start();
}else {
mediaPlayer.pause();
}
}
private void stopPlayer() {
if(mediaPlayer.isPlaying()){
mediaPlayer.stop();
mediaPlayer.reset();
}
}
}
Edit:
Thanks to #ianhanniballake for providing the solution.
It solved my problem "partially". I can stop the mediaplayer but I can't stop my observer observing the event on pause. code update
You're passing in 0 as the behavior, which corresponds to the deprecated BEHAVIOR_SET_USER_VISIBLE_HINT. By using that behavior, setUserVisibleHint() will be called with true when your fragment becomes the current page and false when it is not.
If you switch to the not deprecated BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT, then only the current page will get onResume(). When the page changes, that Fragment will get a callback to onPause() and the newly active fragment will get a call to onResume().
I have created an ExoPlayer inside a fragment. If during the playback I press the Home button, and get back to the player, the player seems to be empty, the play/pause button does not work anymore. The video is gone. The video player view seems to be completely empty.
public class PlaybackFragment extends Fragment implements View.OnClickListener, EventListener, PlaybackControlView.VisibilityListener {
private static final String TAG = PlaybackFragment.class.getSimpleName();
Video mVideo; //Video object passed in for playback
SimpleExoPlayerView mExoPlayerView;
private TextView mVideoTitle;
private SimpleExoPlayer mExoPlayer;
private FrameLayout mFullScreenButton; //Holds the fullscreen icon
private Dialog mFullScreenDialog;
private ImageView mFullScreenIcon;
private boolean mExoPlayerFullScreen; //full-screen dialog
private static final String LOG_TAG = PlaybackFragment.class.getSimpleName();
/**
* Root ViewGroup holding the fragment
*/
private ViewGroup mPlayerViewContainer;
/**
* Context used across the class
*/
private Context mContext;
/**
* Activity to which the fragment is added
*/
private Activity mActivity;
/**
* Uri received from calling activity containing Uri to the video to be played
*/
private Uri mUri;
public PlaybackFragment() {
super();
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
Log.d(TAG, "onCreate: ");
super.onCreate(savedInstanceState);
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
Log.d(TAG, "onCreateView: ");
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment_playback, container, false);
mVideoTitle = root.findViewById(R.id.playback_video_title);
mExoPlayerView = root.findViewById(R.id.exoPlayerView);
mPlayerViewContainer = (ViewGroup) mExoPlayerView.getParent();
return root;
}
/**
* Sets the Uri to video to be played
* #param mediaUri
*/
public void playUri(Uri mediaUri) {
mUri = mediaUri;
}
#Override
public void onViewStateRestored(#Nullable Bundle savedInstanceState) {
Log.d(TAG, "onViewStateRestored: ");
super.onViewStateRestored(savedInstanceState);
}
private void preparePlayback() {
mExoPlayerView.setControllerVisibilityListener(this);
mExoPlayerView.requestFocus();
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory trackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector =
new DefaultTrackSelector(trackSelectionFactory);
mExoPlayer =
ExoPlayerFactory.newSimpleInstance(getContext(), trackSelector);
mExoPlayerView.setPlayer(mExoPlayer);
DataSource.Factory dsFactory = new DefaultDataSourceFactory(mContext,
com.google.android.exoplayer2.util.Util.getUserAgent(mContext, mActivity.getApplicationInfo().processName), null);
// Produces Extractor instances for parsing the media data.
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
MediaSource videoSource = new ExtractorMediaSource(mUri,
dsFactory, extractorsFactory, null, null);
// Prepare the player with the source.
mExoPlayer.prepare(videoSource);
//start player
mExoPlayer.setPlayWhenReady(true);
mExoPlayer.addListener(this);
// initFullscreenDialog();
initFullscreenButton();
}
#Override
public void onVisibilityChange(int visibility) {
}
#Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
Log.d(TAG, "onActivityCreated: ");
super.onActivityCreated(savedInstanceState);
mContext = mActivity = getActivity();
preparePlayback();
}
#Override
public void onStart() {
super.onStart();
Log.d(TAG, "onStart: ");
}
#Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
}
#Override
public void onLoadingChanged(boolean isLoading) {
}
#Override
public void onClick(View v) {
}
public void pause() {
mExoPlayer.stop();
}
//Interface to trigger playback-finish event in the parent activity
public interface OnPlayStateListener {
void onPlayFinish();
}
OnPlayStateListener mCallback;
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if(playbackState == Player.STATE_ENDED) {
quitFullScreen(); //Leave fullscreen after playback finished
mCallback.onPlayFinish();
Log.i(LOG_TAG,"onPlayFinish() triggered");
}
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
mCallback = (OnPlayStateListener) context;
} catch (ClassCastException e){
throw new ClassCastException(context.toString() + " must implement OnPlayStateListener");
}
}
#Override
public void onRepeatModeChanged(int repeatMode) {
}
#Override
public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
}
#Override
public void onPlayerError(ExoPlaybackException error) {
Toast.makeText(mContext,error.getLocalizedMessage(),Toast.LENGTH_SHORT).show();
}
#Override
public void onPositionDiscontinuity(int reason) {
}
#Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
}
#Override
public void onSeekProcessed() {
}
private void goFullScreen() {
Util.showFullScreen(mActivity, mExoPlayerView);
// ((ViewGroup) mExoPlayerView.getParent()).removeView(mExoPlayerView);
// mFullScreenDialog.addContentView(mExoPlayerView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
mFullScreenIcon.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_fullscreen_exit));
mExoPlayerFullScreen = true;
// mFullScreenDialog.show();
}
private void quitFullScreen() {
Util.quitFullScreen(mActivity, mPlayerViewContainer, mExoPlayerView);
// ((ViewGroup) mExoPlayerView.getParent()).removeView(mExoPlayerView);
// FrameLayout frame = mActivity.findViewById(R.id.main_media_frame);
// frame.addView(mExoPlayerView);
mExoPlayerFullScreen = false;
// mFullScreenDialog.dismiss();
mFullScreenIcon.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_fullscreen_expand));
}
private void initFullscreenButton() {
PlaybackControlView controlView = mExoPlayerView.findViewById(R.id.exo_controller);
mFullScreenIcon = controlView.findViewById(R.id.exo_fullscreen_icon);
mFullScreenButton = controlView.findViewById(R.id.exo_fullscreen_button);
mFullScreenButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!mExoPlayerFullScreen) {
goFullScreen();
}
else {
quitFullScreen();
}
}
});
}
private void initFullscreenDialog() {
//The following uses anonymous class to create a custom dialog
mFullScreenDialog = new Dialog(mContext, android.R.style.Theme_DeviceDefault_NoActionBar_Fullscreen) {
#Override
public void onBackPressed() {
if(mExoPlayerFullScreen) {
quitFullScreen();
}
super.onBackPressed();
}
};
}
#Override
public void onDestroy() {
super.onDestroy();
if(mExoPlayer != null) mExoPlayer.release();
Log.d(TAG, "onDestroy: ");
}
/**
* Moves forward or backward by step milliseconds <br/>
* #param step specifies step size. It is a positive or negative integer for moving forward and
* backward, respectively.
*/
public void movePlayPos(int step) {
mExoPlayer.seekTo(mExoPlayer.getCurrentPosition() + step);
}
#Override
public void onSaveInstanceState(#NonNull Bundle outState) {
Log.d(TAG, "onSaveInstanceState: ");
super.onSaveInstanceState(outState);
outState.putLong("position", mExoPlayer.getCurrentPosition());
}
}
I have checked the fragment lifecycle in Logcat, but it seems that after I get back to the player activity, only the fragment's onStart() is called. So, there is no way to restore the state. Any ideas how I can save a video playback position upon pause and resume playback on the activity's onResume?
You can save the current position of exoplayer in onPause() and then seek to that position in onResume().
try this:
long position;
#Override
protected void onPause() {
super.onPause();
if(mExoPlayerView != null && mExoPlayerView.getPlayWhenReady()) {
position = mExoPlayerView.getCurrentPosition();
mExoPlayerView.setPlayWhenReady(false);
}
}
#Override
protected void onResume() {
super.onResume();
if(mExoPlayerView != null) {
mExoPlayerView.seekTo(position);
mExoPlayerView.setPlayWhenReady(true);
}
}
Here's my code:
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create_route);
SetupButton();
}
private void SetupButton()
{
Button createNewMessage = (Button) findViewById(R.id.button);
createNewMessage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ListenForNewMessage();
}
});
}
private void ListenForNewMessage()
{
final SpeechRecognizer newDeliverySpeech = SpeechRecognizer.createSpeechRecognizer(this);
RecognitionListener newDeliveryRecognitionListener = new RecognitionListener() {
#Override
public void onReadyForSpeech(Bundle params) {
Log.d("SpeechListening","onReadyForSpeech");
}
#Override
public void onBeginningOfSpeech() {
Log.d("SpeechListening","onBeginningOfSpeech");
}
#Override
public void onRmsChanged(float rmsdB) {
//do nothing
}
#Override
public void onBufferReceived(byte[] buffer) {
//do nothing
}
#Override
public void onEndOfSpeech() {
Log.d("SpeechListening","onEndOfSpeech");
}
#Override
public void onError(int error) {
//do nothing
}
#Override
public void onResults(Bundle results) {
ArrayList<String> userMessage;
userMessage = results.getStringArrayList(RESULTS_RECOGNITION);
PushNewDelivery(userMessage);
}
#Override
public void onPartialResults(Bundle partialResults) {
//do nothing
}
#Override
public void onEvent(int eventType, Bundle params) {
//do nothing
}
};
newDeliverySpeech.setRecognitionListener(newDeliveryRecognitionListener);
if (newDeliverySpeech.isRecognitionAvailable(getApplicationContext()))
{
Log.d("SpeechListening","started listening hopefully");
newDeliverySpeech.startListening(new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH));
}
}
}
The problem is, only the started listening hopefully is logged, the RecognitionListener never has onReadyForSpeech() or any of its methods called.
details
details
details
details
Can someone please tell me what I'm doing wrong here?
You are basically creating a new SpeechRecognizer object and register a new listener each time you click on the button. On top of that you create the SpeechRecognizer using the current Activity Context but you are actually using the Application context when calling: isRecognitionAvailable();
Try to create the SpeechRecognizer as a member object and register your listener when onCreate() is called. Also try to avoid using the Application context to avoid memory leaks.
Here is an example of how you should do it.
private SpeechRecognizer mDeliverySpeech;
private Intent mSpeechIntent;
private boolean mListening = false;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create_route);
SetupButton();
SetupSpeechRecognizer();
mSpeechIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
mSpeechIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_PREFERENCE, "en");
mSpeechIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, this.getPackageName());
mSpeechIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
mSpeechIntent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 3);
}
private void SetupButton()
{
Button createNewMessage = (Button) findViewById(R.id.button);
createNewMessage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ListenForNewMessage();
}
});
}
private void SetupSpeechRecognizer()
{
mDeliverySpeech = SpeechRecognizer.createSpeechRecognizer(this);
RecognitionListener newDeliveryRecognitionListener = new RecognitionListener() {
#Override
public void onReadyForSpeech(Bundle params) {
Log.d("SpeechListening","onReadyForSpeech");
}
#Override
public void onBeginningOfSpeech() {
Log.d("SpeechListening","onBeginningOfSpeech");
}
#Override
public void onRmsChanged(float rmsdB) {
//do nothing
}
#Override
public void onBufferReceived(byte[] buffer) {
//do nothing
}
#Override
public void onEndOfSpeech() {
Log.d("SpeechListening","onEndOfSpeech");
}
#Override
public void onError(int error) {
//do nothing
}
#Override
public void onResults(Bundle results) {
ArrayList<String> userMessage;
userMessage = results.getStringArrayList(RESULTS_RECOGNITION);
PushNewDelivery(userMessage);
}
#Override
public void onPartialResults(Bundle partialResults) {
//do nothing
}
#Override
public void onEvent(int eventType, Bundle params) {
//do nothing
}
};
mDeliverySpeech.setRecognitionListener(newDeliveryRecognitionListener);
}
private void ListenForNewMessage()
{
if (mDeliverySpeech.isRecognitionAvailable(this) && !mListening)
{
Log.d("SpeechListening","started listening hopefully");
mListening = true;
mDeliverySpeech.startListening(mSpeechIntent);
new CountDownTimer(5000, 5000) {
public void onTick(long millisUntilFinished) {}
public void onFinish() {
mDeliverySpeech.stopListening();
mListening = false;
}
}.start();
}
}
Do not forget to properly handle the activity life cycle when working with listener to avoid memory leak.
I have a fragment with a thread inside it, starting in its onCreate method.
After thread finishes his work i need to send a message to the activity (myActivity) through the "clickButtonOperation".
This is the onCreate() method of my fragment:
public class HolderFragment extends My_Fragment{
private Thread myThread;
.
.
.
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
printf("MyActivity attached is: "+myActivity);
myThread=new Thread(new Runnable(){
#Override
public void run() {
int i=0;
while (i<3){
printf("Working...");
try {
Thread.sleep(2000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
i++;
}
myActivity.clickButtonOperation(new Object[]{
HolderFragment.this.toString()
});
}
});
myThread.start();
}
onCreateView returns NULL.
My question is:
Is it guaranteed that my "clickButonOperation" gets called after the new activity has been attached? or could this method be called before this process?
TEMPORARY SOLUTION:
I created a custom Thread class:
public abstract class My_Thread extends Thread {
private boolean runnable=true;
private boolean paused=false;
private Object[] arguments;
private My_ThreadHolder myHolder;
protected void onPostExecute(Object[] arguments){
while(paused);
runnable=false;
}
protected abstract void execute(Object[] arguments);
protected void notifyUpdate(){
while (paused);
}
protected boolean isRunnable(){
return runnable;
}
public void setArguments(Object[] arguments){
this.arguments=arguments;
}
public Object[] getArguments() {
return arguments;
}
public final void run(){
while (runnable){
execute(arguments);
onPostExecute(arguments);
}
}
public void attach(My_ThreadHolder holder){
myHolder=holder;
}
public My_ThreadHolder getHolder() {
return myHolder;
}
public void startThread(){
runnable=true;
start();
}
public void stopThread(){
runnable=false;
}
public void pauseThread(){
paused=true;
printf("Thread paused");
}
public void resumeThread(){
paused=false;
printf("Thread resumed");
}
}
And created these two:
public class My_ThreadHolder extends My_Fragment{
private TestThread myThread;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
printf("MyActivity attached is: "+myActivity);
myThread=new TestThread();
myThread.attach(this);
myThread.startThread();
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (myThread!=null)myThread.resumeThread();
}
#Override
public void onDetach() {
super.onDetach();
myThread.pauseThread();
}
protected void onNotifyUpdateReceived(Object[] arguments){
myActivity.clickButtonOperation(arguments);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {return null;}
#Override
protected void setGraphics(View view, Bundle savedInstanceState) {}
}
class TestThread extends My_Thread{
#Override
protected void onPostExecute(Object[] arguments) {
super.onPostExecute(arguments);
printf("Thread finished");
}
#Override
protected void execute(Object[] arguments) {
int i=0;
while(i<3){
printf("Working...");
try {
Thread.sleep(2000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
i++;
Object[] myArguments= new Object[2];
myArguments[0]=0;
myArguments[1]=i;
setArguments(myArguments);
notifyUpdate();
}
}
#Override
protected void notifyUpdate() {
super.notifyUpdate();
getHolder().onNotifyUpdateReceived(getArguments());
}
}
You cannot touch the UI from a background thread.. you need to use runOnUiThread method from Activity class, something like this
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
printf("MyActivity attached is: "+myActivity);
myThread = new Thread(new Runnable() {
#Override
public void run() {
int i = 0;
while (i < 3) {
printf("Working...");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
}
myActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
myActivity.clickButtonOperation(new Object[]{
HolderFragment.this.toString()
});
}
});
}
});
myThread.start();
}
I have been successfully using YouTubePlayerSupportFragment to play YouTube videos.
But I still need to continue playing in the background, when the back button is pressed.
If you have any ideas, please share with me. Thanks!
Here is my code -
YoutubePlayerFragment class
public class YoutubePlayerFragment {
public static String DEVELOPER_KEY = "DEVELOPER_KEY";
public static boolean isFullScreen;
public static void setYoutubePlayerFragment(final Fragment fragment) {
MainFragment.youtubePlayerFragment = new YouTubePlayerSupportFragment();
MainFragment.youtubePlayerFragment.initialize(DEVELOPER_KEY, new OnInitializedListener() {
#Override
public void onInitializationFailure(Provider arg0, YouTubeInitializationResult arg1) {
}
#Override
public void onInitializationSuccess(Provider arg0, YouTubePlayer player,
boolean paramBoolean) {
PlayerService.youTubePlayer = player;
PlayerService.youTubePlayer.setPlayerStyle(YouTubePlayer.PlayerStyle.DEFAULT);
setListener(fragment.getActivity());
}
});
replaceFragment(fragment);
}
public static void replaceFragment(final Fragment fragment) {
if (fragment == null)
return;
FragmentManager fragmentManager = fragment.getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.youtubeplayerFrameLayout,
MainFragment.youtubePlayerFragment);
fragmentTransaction.commit();
}
public static void setListener(final Activity activity) {
PlayerService.youTubePlayer.setOnFullscreenListener(new OnFullscreenListener() {
#Override
public void onFullscreen(boolean isFullScreen) {
YoutubePlayerFragment.isFullScreen = isFullScreen;
Log.d(App.tagName, "setOnFullscreenListener : onFullscreen");
}
});
PlayerService.youTubePlayer.setPlayerStateChangeListener(new PlayerStateChangeListener() {
#Override
public void onAdStarted() {
Log.d(App.tagName, "setPlayerStateChangeListener : onAdStarted");
}
#Override
public void onError(ErrorReason arg0) {
Log.d(App.tagName, "setPlayerStateChangeListener : onError : " + arg0);
}
#Override
public void onLoaded(String arg0) {
Log.d(App.tagName, "setPlayerStateChangeListener : onLoaded");
}
#Override
public void onLoading() {
Log.d(App.tagName, "setPlayerStateChangeListener : onLoading");
}
#Override
public void onVideoEnded() {
Log.d(App.tagName, "setPlayerStateChangeListener : onVideoEnded");
}
#Override
public void onVideoStarted() {
Log.d(App.tagName, "setPlayerStateChangeListener : onVideoStarted");
}
});
PlayerService.youTubePlayer.setPlaybackEventListener(new PlaybackEventListener() {
#Override
public void onBuffering(boolean arg0) {
Log.d(App.tagName, "setPlaybackEventListener : onBuffering");
if (MainActivity.isBack && PlayerService.youTubePlayer != null) {
PlayerService.youTubePlayer.play();
}
}
#Override
public void onPaused() {
Log.d(App.tagName, "setPlaybackEventListener : onPaused");
PlayerFrameLayout.ibPlay.setImageResource(R.drawable.ic_play_arrow_white_36dp);
if (MainActivity.isBack && PlayerService.youTubePlayer != null) {
PlayerService.youTubePlayer.play();
}
}
#Override
public void onPlaying() {
Log.d(App.tagName, "setPlaybackEventListener : onPlaying");
PlayerFrameLayout.ibPlay.setImageResource(R.drawable.ic_pause_white_36dp);
}
#Override
public void onSeekTo(int arg0) {
Log.d(App.tagName, "setPlaybackEventListener : onSeekTo");
}
#Override
public void onStopped() {
Log.d(App.tagName, "setPlaybackEventListener : onStopped");
}
});
}}
Using Service to play Youtube video.
public class PlayerService extends Service {
public static YouTubePlayer youTubePlayer = null;
private int MSG;
#Override
public void onCreate() {
super.onCreate();
Log.d(App.tagName, "PlayerService : onCreate");
YoutubePlayerFragment.setYoutubePlayerFragment(MainFragment.mainFragment);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(App.tagName, "PlayerService : onStartCommand");
MediaInfo mediaInfo = MusicListFragment.getCurrentMp3Info();
youTubePlayer.loadVideo(mediaInfo.video_id);
youTubePlayer.play();
return super.onStartCommand(intent, flags, startId);
} }