I am trying to send a search value after complete searching for example after 10 sec as the below code for onTextChanged method:
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
// searchEditText.setImeOptions(EditorInfo.IME_ACTION_SEARCH);
timer.schedule(new TimerTask() {
#Override
public void run() {
try {
Config.sendToMixpanel(Config.MIXPANEL_EVENT_SEARCH + charSequence, mMixpanel);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, 10000);
}
it send to the mixpanel multiple times, I want send to mix panel after finishing search the complete searched word and it sent to the mix panel as the below image:
I need to send one time only..
This is the below sendToMixPanel():
//Send the Event to Mix Panel Method
public static void sendToMixpanel(String logEventName, MixpanelAPI mMixpanelApi) throws JSONException {
JSONObject props = new JSONObject();
props.put("source", "Pat's affiliate site");
props.put("Opted out of email", true);
mMixpanelApi.track(logEventName, props);
}
and this is the below search activity:
package com.quantatil.ikhair.UILayer.Activities;
import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import com.mixpanel.android.mpmetrics.MixpanelAPI;
import com.quantatil.ikhair.App.Config;
import com.quantatil.ikhair.R;
import com.quantatil.ikhair.UILayer.Fragments.SearchQueryFragment;
import org.json.JSONException;
import java.util.Timer;
import java.util.TimerTask;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class SearchActivity extends BaseActivity {
#BindView(R.id.search_input)
EditText searchEditText;
#BindView(R.id.delete_search_query)
View deleteSearchQuery;
SearchQueryFragment searchQueryFragment;
private MixpanelAPI mMixpanel;
private Timer timer = new Timer();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);
mMixpanel = MixpanelAPI.getInstance(this, Config.MIXPANEL_API_TOKEN);
ButterKnife.bind(this);
searchQueryFragment = new SearchQueryFragment();
showFragment(searchQueryFragment);
setupSearchTextWatcher();
}
private void setupSearchTextWatcher() {
searchEditText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
// searchEditText.setImeOptions(EditorInfo.IME_ACTION_SEARCH);
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
// searchEditText.setImeOptions(EditorInfo.IME_ACTION_SEARCH);
timer.schedule(new TimerTask() {
#Override
public void run() {
try {
Config.sendToMixpanel(Config.MIXPANEL_EVENT_SEARCH + charSequence, mMixpanel);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, 10000);
}
#Override
public void afterTextChanged(Editable editable) {
String query = searchEditText.getText().toString().trim();
if (deleteSearchQuery.getVisibility() != View.INVISIBLE && TextUtils.isEmpty(query)) {
deleteSearchQuery.setVisibility(View.INVISIBLE);
deleteSearchQuery.setClickable(false);
searchQueryFragment.clear();
} else if (!TextUtils.isEmpty(query)) {
if (deleteSearchQuery.getVisibility() != View.VISIBLE) {
deleteSearchQuery.setVisibility(View.VISIBLE);
deleteSearchQuery.setClickable(true);
}
searchQueryFragment.search(searchQueryFragment, query);
}
}
});
}
#OnClick(R.id.delete_search_query)
void deleteSearchQuery() {
searchEditText.setText("");
}
#OnClick(R.id.back_icon)
void backClicked() {
onBackPressed();
}
}
the timer works fine but send the value multiple times, want just send one time only..
#Edited
I tried to add the timer method in the button I need as the below code:
private Timer timer = new Timer();
CharSequence charSequence;
#OnClick(R.id.search_icon)
void startSearch(){
startActivity(new Intent(getApplicationContext() , SearchActivity.class));
timer.schedule(new TimerTask() {
#Override
public void run() {
try {
Config.sendToMixpanel(Config.MIXPANEL_EVENT_SEARCH + charSequence, mMixpanel);
} catch (JSONException e) {
e.printStackTrace();
}
}
},10000);
It gives me with a search value with null but it sends it one time only as the below image:
You can use Handler's postDelayed() method, and pass in a Runnable task. Example:
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
//Do your work here after 10s
}
}, 10000);
EDIT:
In your code it would be something like this:
public class SearchActivity extends BaseActivity {
#BindView(R.id.search_input)
EditText searchEditText;
...
private MixpanelAPI mMixpanel;
private CharSequence myCharSequence;
private final Handler handler;
#Override
protected void onCreate(Bundle savedInstanceState) {
...
}
...
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
myCharSequence = charSequence;
}
...
#OnClick(R.id.search_icon)
void startSearch(){
handler.removeCallbacksAndMessages();
handler.postDelayed(new Runnable() {
#Override
public void run() {
try {
Config.sendToMixpanel(Config.MIXPANEL_EVENT_SEARCH + myCharSequence, mMixpanel);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, 10000);
startActivity(new Intent(getApplicationContext() , SearchActivity.class));
}
}
Related
I am trying to use the Android Camera2 api to create a preview, however my code does not execute the cameraCaptureSession.StateCallback. My code executes through cameraDevice.createCaptureSession(camConfig). Upon executing this, it should execute the StateCallback however from what I can tell it does not. I was wondering if anyone knows why this callback did not executed? And how to fix it.
import android.content.Context;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.params.OutputConfiguration;
import android.hardware.camera2.params.SessionConfiguration;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import android.util.Log;
import android.util.Size;
import android.view.LayoutInflater;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Toast;
import com.example.atlas2.R;
import com.example.atlas2.Util.BackgroundThreadFactory;
import java.util.Arrays;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import static android.hardware.camera2.CameraMetadata.LENS_FACING_FRONT;
import static android.hardware.camera2.params.SessionConfiguration.SESSION_REGULAR;
public class ProfilePhotoFragment extends Fragment implements SurfaceHolder.Callback2, ThreadFactory
{
Button capture;
CameraManager cameraManager;
String[] cameraIDs;
String frontCamera;
String cameraId;
SurfaceView camPreview;
SurfaceHolder camHolder;
Size surfaceSize;
CameraDevice cameraDevice;
SessionConfiguration camConfig;
CameraCaptureSession cameraCaptureSessions;
CaptureRequest.Builder captureRequestBuilder;
CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
#Override
public void onOpened(#NonNull CameraDevice camera) {
cameraDevice = camera;
previewSetUp();
}
#Override
public void onDisconnected(#NonNull CameraDevice camera) {
}
#Override
public void onError(#NonNull CameraDevice camera, int error) {
}
};
public ProfilePhotoFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View profilePhotoView = inflater.inflate(R.layout.fragment_profile_photo, container, false);
cameraManager = (CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE);
try {
cameraIDs = cameraManager.getCameraIdList();
Log.v("cameraIDs", cameraIDs[1]);
} catch (CameraAccessException e) {
e.printStackTrace();
}
camPreview = profilePhotoView.findViewById(R.id.camOutput);
camHolder = camPreview.getHolder();
openCamera();
capture = profilePhotoView.findViewById(R.id.capture);
capture.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
// Inflate the layout for this fragment
return profilePhotoView;
}
public void openCamera() {
chooseCamera();
String frontFacing = frontCamera;
try {
cameraManager.openCamera(frontFacing, stateCallback, null); //permissions taken care of
in ProfilePhotoActivity
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
public void chooseCamera() {
//find front facing camera through getCameraCharacteristics(cameraId)
for(int i = 0; i < cameraIDs.length; i++) {
try {
if(cameraManager.getCameraCharacteristics(cameraIDs[1]).get(CameraCharacteristics.LENS_FACING) ==
LENS_FACING_FRONT) {
frontCamera = cameraIDs[i];
Log.v("frontfacing", frontCamera);
cameraId = cameraIDs[i];
break;
}
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
}
#Override
public void surfaceRedrawNeeded(SurfaceHolder holder) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
#Override
public Thread newThread(Runnable r) {
return new Thread(r);
}
public void previewSetUp() {
CameraCharacteristics characteristics = null;
try {
characteristics = cameraManager.getCameraCharacteristics(cameraId);
} catch (CameraAccessException e) {
e.printStackTrace();
}
StreamConfigurationMap map =
characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
assert map != null;
surfaceSize = map.getOutputSizes(SurfaceHolder.class)[0];
camHolder.setFixedSize(surfaceSize.getWidth(), surfaceSize.getHeight());
Surface surface = camHolder.getSurface();
try {
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
} catch (CameraAccessException e) {
e.printStackTrace();
}
captureRequestBuilder.addTarget(surface);
OutputConfiguration outputConfig = new OutputConfiguration(surface);
Log.v("outputconfig", outputConfig.toString());
ExecutorService executor = Executors.newFixedThreadPool(2, new BackgroundThreadFactory());
Log.v("executor", executor.toString());
camConfig = new SessionConfiguration(SESSION_REGULAR, Arrays.asList(outputConfig), executor,
new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(#NonNull CameraCaptureSession session) {
cameraCaptureSessions = session;
Log.v("onConfigured", "onconfigured");
updatePreview();
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession session) {
Log.v("onConfiguredFailed", session.toString());
Toast.makeText(getContext(), "Changed", Toast.LENGTH_SHORT).show();
}
});
String supported = cameraDevice.getId();
try {
cameraDevice.createCaptureSession(camConfig);
Log.v("createCaptureSession", supported);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
public void updatePreview() {
Log.v("createCaptureSession2", String.valueOf(cameraCaptureSessions));
if(cameraDevice == null)
Toast.makeText(getContext(), "Error", Toast.LENGTH_SHORT).show();
Log.v("createCaptureSession1", String.valueOf(cameraCaptureSessions));
captureRequestBuilder.set(CaptureRequest.CONTROL_MODE,CaptureRequest.CONTROL_MODE_AUTO);
captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
try{
Log.v("createCaptureSession", String.valueOf(cameraCaptureSessions));
cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(), null, null);
}catch (CameraAccessException e) {
e.printStackTrace();
}
}
/**#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}**/
public void switchCameras() {
//start a new cameracapturesession; this will stop the pre-existing one
}
#Override
public void onDetach() {
super.onDetach();
}
#Override
public void onDestroy() {
super.onDestroy();
//executor.shutdown(); //executor in previewSetUp needs to be global
}
}
I am trying to update a progress bar while downloading a file, but in my Service task I do not have any access to the UI. This means I cannot find the ProgressBar element using findViewByID in order to update the ProgressBar. Here is the relevant code:
MainActivity:
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.content.Intent;
import android.view.View;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void startService(View view) {
startService(new Intent(getBaseContext(), MyService.class));
}
public void stopService(View view) {
stopService(new Intent(getBaseContext(), MyService.class));
}
}
MyService Class:
package com.example.services;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.ProgressBar;
import android.widget.Toast;
import java.net.MalformedURLException;
import java.net.URL;
import android.os.AsyncTask;
import android.util.Log;
import java.util.Timer;
import java.util.TimerTask;
public class MyService extends Service {
int counter = 0;
static final int UPDATE_INTERVAL = 1000;
private Timer timer = new Timer();
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
doSomethingRepeatedly();
try {
new DoBackgroundTask().execute(
new URL("http://www.amazon.com/somefiles.pdf"),
new URL("http://www.wrox.com/somefiles.pdf"),
new URL("http://www.google.com/somefiles.pdf"),
new URL("http://www.learn2develop.net/somefiles.pdf"));
} catch (MalformedURLException e) {
e.printStackTrace();
}
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
if (timer != null){
timer.cancel();
}
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
}
private void doSomethingRepeatedly() {
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
Log.d("MyService", String.valueOf(++counter));
}
}, 0, UPDATE_INTERVAL);
}
private class DoBackgroundTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalBytesDownloaded = 0;
for (int i = 0; i < count; i++) {
totalBytesDownloaded += DownloadFile(urls[i]);
publishProgress((int) (((i + 1) / (float) count) * 100));
}
return totalBytesDownloaded;
}
protected void onProgressUpdate(Integer... progress) {
Log.d("Downloading files", String.valueOf(progress[0]) + "% downloaded");
Toast.makeText(getBaseContext(),
String.valueOf(progress[0]) + "% downloaded-"+counter,
Toast.LENGTH_LONG).show();
}
protected void onPostExecute(Long result) {
Toast.makeText(getBaseContext(), "Downloaded " + result + " bytes",
Toast.LENGTH_LONG).show();
//stopSelf();
}
}
private int DownloadFile(URL url) {
try {
//---simulate taking some time to download a file---
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//---return an arbitrary number representing
// the size of the file downloaded---
return 100;
}
}
Basically, I want to update the ProgressBar in my MainActivity by using the bytesDownloaded variable in my MyService class, but I'm not sure how to handle the Async call in my MainActivity. If that is even possible.
Thanks!
I am working on Exoplayer Media Player in Android to Live Stream from an RTMP Media Source URL. I am new to this kind a development so I am following the official Tutorial. The live stream is working fine on all Android Devices! My Class for fetching the live stream is:
import android.annotation.SuppressLint;
import android.databinding.DataBindingUtil;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import com.example.juni1289.exoplayertest2.databinding.ActivityMainBinding;
import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.DefaultRenderersFactory;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.ext.rtmp.RtmpDataSourceFactory;
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.google.android.exoplayer2.extractor.ExtractorsFactory;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer2.util.Util;
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
private ExoPlayer player;
private boolean playWhenReady;
private static final DefaultBandwidthMeter BANDWIDTH_METER = new DefaultBandwidthMeter();
private ComponentListener componentListener;
private final String TAG = "MainActivity";
private MediaSource videoSource;
private AdaptiveTrackSelection.Factory adaptiveTrackSelectionFactory;
private TrackSelector trackSelector;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
componentListener = new ComponentListener();
initializePlayer();
}
private void initializePlayer() {
if (player == null) {
// a factory to create an AdaptiveVideoTrackSelection
adaptiveTrackSelectionFactory = new AdaptiveTrackSelection.Factory(BANDWIDTH_METER);
trackSelector = new DefaultTrackSelector(adaptiveTrackSelectionFactory);
player = ExoPlayerFactory.newSimpleInstance(
new DefaultRenderersFactory(this),
trackSelector,
new DefaultLoadControl());
binding.videoView.setPlayer(player);
RtmpDataSourceFactory rtmpDataSourceFactory = new RtmpDataSourceFactory();
// Produces Extractor instances for parsing the media data.
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
// This is the MediaSource representing the media to be played.
videoSource = new ExtractorMediaSource(Uri.parse(""),
rtmpDataSourceFactory, extractorsFactory, null, null);
playWhenReady = true;
player.prepare(videoSource);
player.setPlayWhenReady(playWhenReady);
player.addListener(componentListener);
}
}
private void releasePlayer() {
if (player != null) {
player.removeListener(componentListener);
playWhenReady = player.getPlayWhenReady();
player.release();
player = null;
}
}
#Override
public void onPause() {
super.onPause();
if (Util.SDK_INT <= 23) {
releasePlayer();
}
}
#Override
public void onStop() {
super.onStop();
if (Util.SDK_INT > 23) {
releasePlayer();
}
}
#Override
public void onResume() {
super.onResume();
hideSystemUi();
if ((Util.SDK_INT <= 23 || player == null)) {
initializePlayer();
}
}
#SuppressLint("InlinedApi")
private void hideSystemUi() {
binding.videoView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
}
private class ComponentListener extends Player.DefaultEventListener {
#Override
public void onTimelineChanged(Timeline timeline, Object manifest, int reason) {
super.onTimelineChanged(timeline, manifest, reason);
}
#Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
super.onTracksChanged(trackGroups, trackSelections);
}
#Override
public void onLoadingChanged(boolean isLoading) {
super.onLoadingChanged(isLoading);
}
#Override
public void onRepeatModeChanged(int repeatMode) {
super.onRepeatModeChanged(repeatMode);
}
#Override
public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
super.onShuffleModeEnabledChanged(shuffleModeEnabled);
}
#Override
public void onPlayerError(ExoPlaybackException error) {
super.onPlayerError(error);
}
#Override
public void onPositionDiscontinuity(int reason) {
super.onPositionDiscontinuity(reason);
}
#Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
super.onPlaybackParametersChanged(playbackParameters);
}
#Override
public void onSeekProcessed() {
super.onSeekProcessed();
}
#Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
super.onTimelineChanged(timeline, manifest);
}
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
String stateString;
switch (playbackState) {
case ExoPlayer.STATE_IDLE:
stateString = "ExoPlayer.STATE_IDLE -";
break;
case ExoPlayer.STATE_BUFFERING:
stateString = "ExoPlayer.STATE_BUFFERING -";
break;
case ExoPlayer.STATE_READY:
stateString = "ExoPlayer.STATE_READY -";
break;
case ExoPlayer.STATE_ENDED:
stateString = "ExoPlayer.STATE_ENDED -";
break;
default:
stateString = "UNKNOWN_STATE -";
break;
}
Log.e(TAG, "changed state to " + stateString
+ " playWhenReady: " + playWhenReady);
}
}
}
The Gradle Dependencies
implementation 'com.google.android.exoplayer:exoplayer-core:2.7.3'
implementation 'com.google.android.exoplayer:exoplayer-dash:2.7.3'
implementation 'com.google.android.exoplayer:exoplayer-ui:2.7.3'
implementation 'com.google.android.exoplayer:extension-rtmp:2.7.3'
The URL is from Nginx Server implemented in the background, the backend live streaming software used is Wirecast using MacBook.
The problem I am facing is that when I have lost the Wifi connection (working),the Live stream won't resume at all. Similarly is with the 3G/4G Mobile Network Connection that once it goes down the live stream won't resume back.
I have followed the given tutorial and searched many of the forums for the problem resolution! But I am unable to find any resource information in order to rectify the problem!
I purposed a solution for me that a Broadcast receiver is registered in the MainActivity that will check of Internet Connections, once it changes it state the Exoplayer will be re-initialized. But this has limitation, that it only works when the Wifi or the Mobile Data Connection will turn on or off!
I want Exoplayer to resume the live stream when Wifi or Mobile Data Connection goes down and then it got some life and the Exoplayer resume the live stream to be watch again!
Any help or guidance will be highly appreciated! As I am new to this development, any blunders can occur in my code.
I am also trying with the following code too:
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Surface;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.LoadControl;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.decoder.DecoderCounters;
import com.google.android.exoplayer2.ext.rtmp.RtmpDataSourceFactory;
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.google.android.exoplayer2.extractor.ExtractorsFactory;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.ui.SimpleExoPlayerView;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
import com.google.android.exoplayer2.upstream.DefaultAllocator;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer2.video.VideoRendererEventListener;
public class MainActivity extends AppCompatActivity implements VideoRendererEventListener {
private SimpleExoPlayerView exoPlayerView;
private final String logKEY = "MainActivity";
private SimpleExoPlayer player;
private MediaSource videoSource;
private final String url = "myurl";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initExoPlayer();
}
private void initExoPlayer() {
try {
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
AdaptiveTrackSelection.Factory videoSelectionFactory=new AdaptiveTrackSelection.Factory(bandwidthMeter);
//TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(videoSelectionFactory);
/////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//Create the player
DefaultAllocator defaultAllocator = new DefaultAllocator(true, C.DEFAULT_BUFFER_SEGMENT_SIZE);
DefaultLoadControl defaultLoadControl = new DefaultLoadControl(defaultAllocator, 30,
30, 10, DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS,
DefaultLoadControl.DEFAULT_TARGET_BUFFER_BYTES, DefaultLoadControl.DEFAULT_PRIORITIZE_TIME_OVER_SIZE_THRESHOLDS);
player = ExoPlayerFactory.newSimpleInstance(this, trackSelector, defaultLoadControl);
exoPlayerView.setPlayer(player);
exoPlayerView.setUseController(false);
RtmpDataSourceFactory rtmpDataSourceFactory = new RtmpDataSourceFactory();
// Produces Extractor instances for parsing the media data.
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
// This is the MediaSource representing the media to be played.
videoSource = new ExtractorMediaSource(Uri.parse(url),
rtmpDataSourceFactory, extractorsFactory, null, null);
// Prepare the player with the source.
player.prepare(videoSource);
//auto start playing
player.setPlayWhenReady(true);
//adding listeners
player.addListener(new ExoPlayer.EventListener() {
#Override
public void onTimelineChanged(Timeline timeline, Object manifest, int reason) {
}
#Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
}
#Override
public void onLoadingChanged(boolean isLoading) {
if (isLoading) {
Log.e(logKEY, "loadingChanged:::true");
} else {
Log.e(logKEY, "loadingChanged:::false");
}
}
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
}
#Override
public void onRepeatModeChanged(int repeatMode) {
}
#Override
public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
}
#Override
public void onPlayerError(ExoPlaybackException error) {
Log.e(logKEY, "Listener-onPlayerError...");
player.stop();
player.prepare(videoSource);
player.setPlayWhenReady(true);
}
#Override
public void onPositionDiscontinuity(int reason) {
}
#Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
}
#Override
public void onSeekProcessed() {
}
});
} catch (Exception e) {
Log.e(logKEY, "error:::" + e.toString());
e.printStackTrace();
}
}
private void initView() {
exoPlayerView = findViewById(R.id.exoPlayerView);
}
#Override
public void onVideoEnabled(DecoderCounters counters) {
}
#Override
public void onVideoDecoderInitialized(String decoderName, long initializedTimestampMs, long initializationDurationMs) {
}
#Override
public void onVideoInputFormatChanged(Format format) {
}
#Override
public void onDroppedFrames(int count, long elapsedMs) {
}
#Override
public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) {
Log.e(logKEY, "onVideoSizeChanged [" + " width: " + width + " height: " + height + "]");
Log.e(logKEY, "RES:(WxH):" + width + "X" + height + "\n " + height + "p");
}
#Override
public void onRenderedFirstFrame(Surface surface) {
}
#Override
public void onVideoDisabled(DecoderCounters counters) {
}
#Override
protected void onStop() {
super.onStop();
Log.e(logKEY, "onStop()...");
}
#Override
protected void onStart() {
super.onStart();
Log.e(logKEY, "onStart()...");
}
#Override
protected void onResume() {
super.onResume();
Log.e(logKEY, "onResume()...");
}
#Override
protected void onPause() {
super.onPause();
Log.e(logKEY, "onPause()...");
}
#Override
protected void onDestroy() {
super.onDestroy();
Log.e(logKEY, "onDestroy()...");
player.release();
}
}
The above is also having the said issues!
I am trying use ffmpeg in android. Here is the code so far. I took reference from this project. It just lets me convert video file. But I want to play a video file using ffmpeg. Is it possible? If yes then how we can do that?
package com.ffmpeg;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ImageView;
import com.github.hiteshsondhi88.libffmpeg.ExecuteBinaryResponseHandler;
import com.github.hiteshsondhi88.libffmpeg.FFmpeg;
import com.github.hiteshsondhi88.libffmpeg.LoadBinaryResponseHandler;
import com.github.hiteshsondhi88.libffmpeg.exceptions.FFmpegCommandAlreadyRunningException;
import com.github.hiteshsondhi88.libffmpeg.exceptions.FFmpegNotSupportedException;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
public class MainActivity extends AppCompatActivity {
Boolean loadedFlag = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (!loadedFlag) {
FFmpegInitLoader();
}
decodeVideo();
}
public void FFmpegInitLoader() {
FFmpeg ffmpeg = FFmpeg.getInstance(this);
try {
ffmpeg.loadBinary(new LoadBinaryResponseHandler() {
#Override
public void onStart() {
}
#Override
public void onFailure() {
}
#Override
public void onSuccess() {
System.out.println("Successfully loaded FFmpeg!!!");
loadedFlag = true;
}
#Override
public void onFinish() {
}
});
} catch (FFmpegNotSupportedException e) {
System.out.println("Whatever....this thing is not supported :::::::::::::::::::: ");
}
}
public void decodeVideo() {
FFmpeg ffmpeg = FFmpeg.getInstance(this);
try {
ffmpeg.execute(new String[]{"-y", "-i", "/storage/sdcard0/AVSEQ02.mp4", "-c:v", "libx264", "/storage/sdcard0/conv.mp4"}, new ExecuteBinaryResponseHandler() {
#Override
public void onStart() {
System.out.println("FFmpeg started for decoding");
}
#Override
public void onProgress(String message) {
System.out.println("progress message:::: " + message);
}
#Override
public void onFailure(String message) {
System.out.println("failure message:::: " + message);
}
#Override
public void onSuccess(String message) {
System.out.println("success message:::: " + message);
}
#Override
public void onFinish() {
}
});
} catch (FFmpegCommandAlreadyRunningException e) {
System.out.println("already running::::::");
}
}
}
Yes it is possible.See the below links.
AndroidFFmpeg
FFmpegMediaPlayer
I am trying to update a textview after 3 seconds, and i want to do that in a loop for which i am using thread .....what should i do in order to start background thread so that exactly after 3 seconds background1 thread starts ... and it should be done in a loop ?
package com.edu.math;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.TextView;
public class EduMath extends Activity {
TextView txt;
TextView tv;
TextView num;
String x;
int time = 3000;
float z ;
int random;
int random1;
int random_operator =1;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
txt=(TextView)findViewById(R.id.txt);
tv = (TextView)findViewById(R.id.randomNumber);
background.start();
}
// our handler
Handler handler = new Handler() {
public void handleMessage(Message msg) {//display each item in a single line
random = (int)Math.ceil(Math.random()*10);
random1 = (int)Math.ceil(Math.random()*10);
if(random1>random)
{
txt.setText(/*txt.getText()+*/""+random1+" "+>+" "+random+" "+
System.getProperty("line.separator"));
}
else
{
txt.setText(/*txt.getText()+*/""+random+" "+>+" "+random1+
System.getProperty("line.separator"));
}
}
};
Handler handler1 = new Handler() {
#Override
public void handleMessage(Message msg) {//display each item in a single line
txt.setText(/*txt.getText()+*/""+random1+" "+x+" "+random+System.getProperty("line.separator"));
}
};
Thread background1 =new Thread(new Runnable() {
#Override
public void run() {
for(int i=0;i<10;i++)
{
try {
Thread.sleep(time);
// send message to the handler with the current message handler
handler1.sendMessage(handler1.obtainMessage());
background.stop();
Log.d("EduMath-enclosing_method", "thread started");
} catch (Exception e) {
Log.v("Error", e.toString());
}
}
}
});
Thread background=new Thread(new Runnable() {
#Override
public void run() {
for(int i=0;i<10;i++)
{
try {
Thread.sleep(time);
// send message to the handler with the current message handler
handler.sendMessage(handler.obtainMessage());
background1.start();
} catch (Exception e) {
Log.v("Error", e.toString());
}
}
}
});
}
You must use AsyncTask for changing any views in layout, but at now I have very little experience with AsyncTask.
Try to use a java.util.Timer ( http://download.oracle.com/javase/1.4.2/docs/api/java/util/Timer.html )
public class HandlerDemo extends Activity {
ProgressBar bar;
Handler handler=new Handler() {
#Override
public void handleMessage(Message msg) {
//add your text
}
};
AtomicBoolean isRunning=new AtomicBoolean(false);
public void onStart() {
super.onStart();
Thread background=new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(3000);
handler.sendMessage(handler.obtainMessage());
}
catch (Throwable t) {
// just end the background thread
}
}
});
isRunning.set(true);
background.start();
}
public void onStop() {
super.onStop();
isRunning.set(false);
}
}
Try the solution on this post...seems to be what you looking for http://androidgenuine.com/?p=707