I'm building video chat application using webrtc. when i started video call some error is coming. how to resolve that issue.
E/RoomRTCClient: Room connection error: HTTP POST to https://appr.tc/join/E52U8KA error: Unacceptable certificate: CN=COMODO RSA Certification Authority, O=COMODO CA Limited, L=Salford, ST=Greater Manchester, C=GB.
E/WSRTCClient: HTTP POST to https://appr.tc/join/E52U8KA error: Unacceptable certificate: CN=COMODO RSA Certification Authority, O=COMODO CA Limited, L=Salford, ST=Greater Manchester, C=GB
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.UiThread;
import com.skillatwill.skillatwill.R;
import org.appspot.apprtc.AppRTCClient;
import org.appspot.apprtc.PeerConnectionClient;
import org.appspot.apprtc.WebSocketRTCClient;
import org.webrtc.Camera2Enumerator;
import org.webrtc.CameraEnumerator;
import org.webrtc.IceCandidate;
import org.webrtc.Logging;
import org.webrtc.RendererCommon.ScalingType;
import org.webrtc.SessionDescription;
import org.webrtc.StatsReport;
import org.webrtc.SurfaceViewRenderer;
import org.webrtc.VideoCapturer;
import org.webrtc.VideoFrame;
import org.webrtc.VideoRenderer;
import org.webrtc.VideoSink;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
/**
* Activity for peer connection call setup, call waiting
* and call view.
*/
public class CallActivity extends Activity implements AppRTCClient.SignalingEvents,
PeerConnectionClient.PeerConnectionEvents {
private static final String TAG = "CallActivity";
private static final String APPRTC_URL = "https://appr.tc";
private static final String UPPER_ALPHA_DIGITS = "ACEFGHJKLMNPQRUVWXY123456789";
// Peer connection statistics callback period in ms.
private static final int STAT_CALLBACK_PERIOD = 1000;
private final ProxyRenderer remoteProxyRenderer = new ProxyRenderer();
private final ProxyVideoSink localProxyVideoSink = new ProxyVideoSink();
private final List<VideoRenderer.Callbacks> remoteRenderers = new ArrayList<>();
private PeerConnectionClient peerConnectionClient = null;
private AppRTCClient appRtcClient;
private AppRTCClient.SignalingParameters signalingParameters;
private SurfaceViewRenderer pipRenderer;
private SurfaceViewRenderer fullscreenRenderer;
private Toast logToast;
private boolean activityRunning;
private AppRTCClient.RoomConnectionParameters roomConnectionParameters;
private PeerConnectionClient.PeerConnectionParameters peerConnectionParameters;
private boolean iceConnected;
private boolean isError;
private long callStartedTimeMs = 0;
private boolean micEnabled = true;
private boolean isSwappedFeeds;
// Control buttons for limited UI
private ImageButton disconnectButton;
private ImageButton cameraSwitchButton;
private ImageButton toggleMuteButton;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_call);
iceConnected = false;
signalingParameters = null;
// Create UI controls.
pipRenderer = findViewById(R.id.pip_video_view);
fullscreenRenderer = findViewById(R.id.fullscreen_video_view);
disconnectButton = findViewById(R.id.button_call_disconnect);
cameraSwitchButton = findViewById(R.id.button_call_switch_camera);
toggleMuteButton = findViewById(R.id.button_call_toggle_mic);
// Add buttons click events.
disconnectButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
onCallHangUp();
}
});
cameraSwitchButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
onCameraSwitch();
}
});
toggleMuteButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
boolean enabled = onToggleMic();
toggleMuteButton.setAlpha(enabled ? 1.0f : 0.3f);
}
});
// Swap feeds on pip view click.
pipRenderer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
setSwappedFeeds(!isSwappedFeeds);
}
});
remoteRenderers.add(remoteProxyRenderer);
// Create peer connection client.
peerConnectionClient = new PeerConnectionClient();
// Create video renderers.
pipRenderer.init(peerConnectionClient.getRenderContext(), null);
pipRenderer.setScalingType(ScalingType.SCALE_ASPECT_FIT);
fullscreenRenderer.init(peerConnectionClient.getRenderContext(), null);
fullscreenRenderer.setScalingType(ScalingType.SCALE_ASPECT_FILL);
pipRenderer.setZOrderMediaOverlay(true);
pipRenderer.setEnableHardwareScaler(true /* enabled */);
fullscreenRenderer.setEnableHardwareScaler(true /* enabled */);
// Start with local feed in fullscreen and swap it to the pip when the call is connected.
setSwappedFeeds(true /* isSwappedFeeds */);
// Generate a random room ID with 7 uppercase letters and digits
String randomRoomID = randomString(7, UPPER_ALPHA_DIGITS);
// Show the random room ID so that another client can join from https://appr.tc
TextView roomIdTextView = findViewById(R.id.roomID);
roomIdTextView.setText(getString(R.string.room_id_caption) + randomRoomID);
Log.d(TAG, getString(R.string.room_id_caption) + randomRoomID);
// Connect video call to the random room
connectVideoCall(randomRoomID);
}
// Create a random string
private String randomString(int length, String characterSet) {
StringBuilder sb = new StringBuilder(); //consider using StringBuffer if needed
for (int i = 0; i < length; i++) {
int randomInt = new SecureRandom().nextInt(characterSet.length());
sb.append(characterSet.substring(randomInt, randomInt + 1));
}
return sb.toString();
}
// Join video call with randomly generated roomId
private void connectVideoCall(String roomId) {
Uri roomUri = Uri.parse(APPRTC_URL);
int videoWidth = 0;
int videoHeight = 0;
peerConnectionParameters =
new PeerConnectionClient.PeerConnectionParameters(true,
false,
false,
videoWidth,
videoHeight,
0,
Integer.parseInt(getString(R.string.pref_maxvideobitratevalue_default)),
getString(R.string.pref_videocodec_default),
true,
false,
Integer.parseInt(getString(R.string.pref_startaudiobitratevalue_default)),
getString(R.string.pref_audiocodec_default),
false,
false,
false,
false,
false,
false,
false,
false,
null);
// Create connection client. Use the standard WebSocketRTCClient.
// DirectRTCClient could be used for point-to-point connection
appRtcClient = new WebSocketRTCClient(this);
// Create connection parameters.
roomConnectionParameters =
new AppRTCClient.RoomConnectionParameters(
roomUri.toString(),
roomId,
false,
null);
peerConnectionClient.createPeerConnectionFactory(
getApplicationContext(), peerConnectionParameters, CallActivity.this);
startCall();
}
public void onCallHangUp() {
disconnect();
}
public void onCameraSwitch() {
if (peerConnectionClient != null) {
peerConnectionClient.switchCamera();
}
}
public boolean onToggleMic() {
if (peerConnectionClient != null) {
micEnabled = !micEnabled;
peerConnectionClient.setAudioEnabled(micEnabled);
}
return micEnabled;
}
private void startCall() {
if (appRtcClient == null) {
Log.e(TAG, "AppRTC client is not allocated for a call.");
return;
}
callStartedTimeMs = System.currentTimeMillis();
// Start room connection.
logAndToast(getString(R.string.connecting_to, roomConnectionParameters.roomUrl));
appRtcClient.connectToRoom(roomConnectionParameters);
}
#UiThread
private void callConnected() {
final long delta = System.currentTimeMillis() - callStartedTimeMs;
Log.i(TAG, "Call connected: delay=" + delta + "ms");
if (peerConnectionClient == null || isError) {
Log.w(TAG, "Call is connected in closed or error state");
return;
}
// Enable statistics callback.
peerConnectionClient.enableStatsEvents(true, STAT_CALLBACK_PERIOD);
setSwappedFeeds(false /* isSwappedFeeds */);
}
// Disconnect from remote resources, dispose of local resources, and exit.
private void disconnect() {
activityRunning = false;
remoteProxyRenderer.setTarget(null);
localProxyVideoSink.setTarget(null);
if (appRtcClient != null) {
appRtcClient.disconnectFromRoom();
appRtcClient = null;
}
if (pipRenderer != null) {
pipRenderer.release();
pipRenderer = null;
}
if (fullscreenRenderer != null) {
fullscreenRenderer.release();
fullscreenRenderer = null;
}
if (peerConnectionClient != null) {
peerConnectionClient.close();
peerConnectionClient = null;
}
if (iceConnected && !isError) {
setResult(RESULT_OK);
} else {
setResult(RESULT_CANCELED);
}
finish();
}
private void disconnectWithErrorMessage(final String errorMessage) {
if (!activityRunning) {
Log.e(TAG, "Critical error: " + errorMessage);
disconnect();
} else {
new AlertDialog.Builder(this)
.setTitle(getText(R.string.channel_error_title))
.setMessage(errorMessage)
.setCancelable(false)
.setNeutralButton(R.string.ok,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
disconnect();
}
})
.create()
.show();
}
}
// Log |msg| and Toast about it.
private void logAndToast(String msg) {
Log.d(TAG, msg);
if (logToast != null) {
logToast.cancel();
}
logToast = Toast.makeText(this, msg, Toast.LENGTH_SHORT);
logToast.show();
}
private void reportError(final String description) {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (!isError) {
isError = true;
disconnectWithErrorMessage(description);
}
}
});
}
// Create VideoCapturer
private VideoCapturer createVideoCapturer() {
final VideoCapturer videoCapturer;
Logging.d(TAG, "Creating capturer using camera2 API.");
videoCapturer = createCameraCapturer(new Camera2Enumerator(this));
if (videoCapturer == null) {
reportError("Failed to open camera");
return null;
}
return videoCapturer;
}
// Create VideoCapturer from camera
private VideoCapturer createCameraCapturer(CameraEnumerator enumerator) {
final String[] deviceNames = enumerator.getDeviceNames();
// First, try to find front facing camera
Logging.d(TAG, "Looking for front facing cameras.");
for (String deviceName : deviceNames) {
if (enumerator.isFrontFacing(deviceName)) {
Logging.d(TAG, "Creating front facing camera capturer.");
VideoCapturer videoCapturer = enumerator.createCapturer(deviceName, null);
if (videoCapturer != null) {
return videoCapturer;
}
}
}
// Front facing camera not found, try something else
Logging.d(TAG, "Looking for other cameras.");
for (String deviceName : deviceNames) {
if (!enumerator.isFrontFacing(deviceName)) {
Logging.d(TAG, "Creating other camera capturer.");
VideoCapturer videoCapturer = enumerator.createCapturer(deviceName, null);
if (videoCapturer != null) {
return videoCapturer;
}
}
}
return null;
}
private void setSwappedFeeds(boolean isSwappedFeeds) {
Logging.d(TAG, "setSwappedFeeds: " + isSwappedFeeds);
this.isSwappedFeeds = isSwappedFeeds;
localProxyVideoSink.setTarget(isSwappedFeeds ? fullscreenRenderer : pipRenderer);
remoteProxyRenderer.setTarget(isSwappedFeeds ? pipRenderer : fullscreenRenderer);
fullscreenRenderer.setMirror(isSwappedFeeds);
pipRenderer.setMirror(!isSwappedFeeds);
}
// -----Implementation of AppRTCClient.AppRTCSignalingEvents ---------------
// All callbacks are invoked from websocket signaling looper thread and
// are routed to UI thread.
private void onConnectedToRoomInternal(final AppRTCClient.SignalingParameters params) {
final long delta = System.currentTimeMillis() - callStartedTimeMs;
signalingParameters = params;
logAndToast("Creating peer connection, delay=" + delta + "ms");
VideoCapturer videoCapturer = null;
if (peerConnectionParameters.videoCallEnabled) {
videoCapturer = createVideoCapturer();
}
peerConnectionClient.createPeerConnection(
localProxyVideoSink, remoteRenderers, videoCapturer, signalingParameters);
if (signalingParameters.initiator) {
logAndToast("Creating OFFER...");
// Create offer. Offer SDP will be sent to answering client in
// PeerConnectionEvents.onLocalDescription event.
peerConnectionClient.createOffer();
} else {
if (params.offerSdp != null) {
peerConnectionClient.setRemoteDescription(params.offerSdp);
logAndToast("Creating ANSWER...");
// Create answer. Answer SDP will be sent to offering client in
// PeerConnectionEvents.onLocalDescription event.
peerConnectionClient.createAnswer();
}
if (params.iceCandidates != null) {
// Add remote ICE candidates from room.
for (IceCandidate iceCandidate : params.iceCandidates) {
peerConnectionClient.addRemoteIceCandidate(iceCandidate);
}
}
}
}
#Override
public void onConnectedToRoom(final AppRTCClient.SignalingParameters params) {
runOnUiThread(new Runnable() {
#Override
public void run() {
onConnectedToRoomInternal(params);
}
});
}
#Override
public void onRemoteDescription(final SessionDescription sdp) {
final long delta = System.currentTimeMillis() - callStartedTimeMs;
runOnUiThread(new Runnable() {
#Override
public void run() {
if (peerConnectionClient == null) {
Log.e(TAG, "Received remote SDP for non-initilized peer connection.");
return;
}
logAndToast("Received remote " + sdp.type + ", delay=" + delta + "ms");
peerConnectionClient.setRemoteDescription(sdp);
if (!signalingParameters.initiator) {
logAndToast("Creating ANSWER...");
// Create answer. Answer SDP will be sent to offering client in
// PeerConnectionEvents.onLocalDescription event.
peerConnectionClient.createAnswer();
}
}
});
}
#Override
public void onRemoteIceCandidate(final IceCandidate candidate) {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (peerConnectionClient == null) {
Log.e(TAG, "Received ICE candidate for a non-initialized peer connection.");
return;
}
peerConnectionClient.addRemoteIceCandidate(candidate);
}
});
}
#Override
public void onRemoteIceCandidatesRemoved(final IceCandidate[] candidates) {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (peerConnectionClient == null) {
Log.e(TAG, "Received ICE candidate removals for a non-initialized peer connection.");
return;
}
peerConnectionClient.removeRemoteIceCandidates(candidates);
}
});
}
#Override
public void onChannelClose() {
runOnUiThread(new Runnable() {
#Override
public void run() {
logAndToast("Remote end hung up; dropping PeerConnection");
disconnect();
}
});
}
#Override
public void onChannelError(final String description) {
reportError(description);
}
// -----Implementation of PeerConnectionClient.PeerConnectionEvents.---------
// Send local peer connection SDP and ICE candidates to remote party.
// All callbacks are invoked from peer connection client looper thread and
// are routed to UI thread.
#Override
public void onLocalDescription(final SessionDescription sdp) {
final long delta = System.currentTimeMillis() - callStartedTimeMs;
runOnUiThread(new Runnable() {
#Override
public void run() {
if (appRtcClient != null) {
logAndToast("Sending " + sdp.type + ", delay=" + delta + "ms");
if (signalingParameters.initiator) {
appRtcClient.sendOfferSdp(sdp);
} else {
appRtcClient.sendAnswerSdp(sdp);
}
}
if (peerConnectionParameters.videoMaxBitrate > 0) {
Log.d(TAG, "Set video maximum bitrate: " + peerConnectionParameters.videoMaxBitrate);
peerConnectionClient.setVideoMaxBitrate(peerConnectionParameters.videoMaxBitrate);
}
}
});
}
#Override
public void onIceCandidate(final IceCandidate candidate) {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (appRtcClient != null) {
appRtcClient.sendLocalIceCandidate(candidate);
}
}
});
}
#Override
public void onIceCandidatesRemoved(final IceCandidate[] candidates) {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (appRtcClient != null) {
appRtcClient.sendLocalIceCandidateRemovals(candidates);
}
}
});
}
#Override
public void onIceConnected() {
final long delta = System.currentTimeMillis() - callStartedTimeMs;
runOnUiThread(new Runnable() {
#Override
public void run() {
logAndToast("ICE connected, delay=" + delta + "ms");
iceConnected = true;
callConnected();
}
});
}
#Override
public void onIceDisconnected() {
runOnUiThread(new Runnable() {
#Override
public void run() {
logAndToast("ICE disconnected");
iceConnected = false;
disconnect();
}
});
}
#Override
public void onPeerConnectionClosed() {
}
#Override
public void onPeerConnectionStatsReady(final StatsReport[] reports) {
}
#Override
public void onPeerConnectionError(final String description) {
reportError(description);
}
// Activity interfaces
#Override
public void onStop() {
super.onStop();
activityRunning = false;
if (peerConnectionClient != null) {
peerConnectionClient.stopVideoSource();
}
}
#Override
public void onStart() {
super.onStart();
activityRunning = true;
// Video is not paused for screencapture. See onPause.
if (peerConnectionClient != null) {
peerConnectionClient.startVideoSource();
}
}
#Override
protected void onDestroy() {
Thread.setDefaultUncaughtExceptionHandler(null);
disconnect();
if (logToast != null) {
logToast.cancel();
}
activityRunning = false;
super.onDestroy();
}
private static class ProxyRenderer implements VideoRenderer.Callbacks {
private VideoRenderer.Callbacks target;
#Override
synchronized public void renderFrame(VideoRenderer.I420Frame frame) {
if (target == null) {
Logging.d(TAG, "Dropping frame in proxy because target is null.");
VideoRenderer.renderFrameDone(frame);
return;
}
target.renderFrame(frame);
}
synchronized public void setTarget(VideoRenderer.Callbacks target) {
this.target = target;
}
}
private static class ProxyVideoSink implements VideoSink {
private VideoSink target;
#Override
synchronized public void onFrame(VideoFrame frame) {
if (target == null) {
Logging.d(TAG, "Dropping frame in proxy because target is null.");
return;
}
target.onFrame(frame);
}
synchronized public void setTarget(VideoSink target) {
this.target = target;
}
}
}
You are using a demo signaling server operated by an entity (Google) that does not consider this demo signaling server a production system. The certificate expired a week ago.
Run your own server, instructions can be found here: https://github.com/webrtc/apprtc
Related
I want to play this link but i m unable to play this link in my exoplayer
I will be able to play this link only when this referer will be added in the exoplayer but i m unable to add this referer. I dont know how can i add this referer to my exoplayer
Referer: http://nbajunkie.xyz/jp1/
https://reels2watch.com/hls/s1.m3u8
dataSourceFactory.getDefaultRequestProperties().set("Referer", "https://yourdomain.com");
I dont know how to add this referer in the header can someone help me about it or Anyone can do it for me ? Because i don’t know much about java kindly let me know how to solve this issue.
import static com.google.android.exoplayer2.util.Util.getUserAgent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.media.session.PlaybackStateCompat;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.ProgressBar;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.mediarouter.app.MediaRouteButton;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.DefaultRenderersFactory;
import com.google.android.exoplayer2.LoadControl;
import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.RenderersFactory;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.source.dash.DashMediaSource;
import com.google.android.exoplayer2.source.dash.DefaultDashChunkSource;
import com.google.android.exoplayer2.source.hls.HlsMediaSource;
import com.google.android.exoplayer2.source.smoothstreaming.DefaultSsChunkSource;
import com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.ui.PlayerView;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.upstream.DefaultHttpDataSource;
import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory;
import com.google.android.exoplayer2.upstream.HttpDataSource;
import com.google.android.exoplayer2.util.Util;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.LoadAdError;
import com.google.android.gms.ads.interstitial.InterstitialAd;
import com.google.android.gms.ads.interstitial.InterstitialAdLoadCallback;
import com.google.android.gms.cast.MediaInfo;
import com.google.android.gms.cast.MediaLoadOptions;
import com.google.android.gms.cast.MediaMetadata;
import com.google.android.gms.cast.framework.CastButtonFactory;
import com.google.android.gms.cast.framework.CastContext;
import com.google.android.gms.cast.framework.CastSession;
import com.google.android.gms.cast.framework.CastState;
import com.google.android.gms.cast.framework.CastStateListener;
import com.google.android.gms.cast.framework.SessionManagerListener;
import com.google.android.gms.cast.framework.media.RemoteMediaClient;
import com.google.firebase.FirebaseApp;
import com.google.firebase.firestore.FirebaseFirestore;
import com.Myapp.hd.Steaming.R;
import com.Myapp.hd.Steaming.HelperClass;
import com.Myapp.hd.Steaming.BaseActivity;
import com.Myapp.hd.Steaming.Location;
import com.Myapp.hd.Steaming.sessionManager.SessionManager;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
public class Exo_Player extends BaseActivity {
private static final String TAG = "Exo_Player";
String url, userAgent;
boolean tokenEnable = false;
private InterstitialAd interstitial;
private PlayerView playerView;
private SimpleExoPlayer player;
private static final DefaultBandwidthMeter BANDWIDTH_METER = new DefaultBandwidthMeter();
private DataSource.Factory mediaDataSourceFactory;
private Handler mainHandler;
private ProgressBar progressBar;
FirebaseFirestore db;
SessionManager sessionManager;
FirebaseFirestore firebaseFirestore;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
//////////////////////////////////////////////////////
setContentView(R.layout.exo_player_ui);
castContext = CastContext.getSharedInstance(this);
initCast();
db = FirebaseFirestore.getInstance();
sessionManager = new SessionManager(this);
FirebaseApp.initializeApp(this);
AdRequest adRequest = new AdRequest.Builder().build();
InterstitialAd.load(Exo_Player.this, sessionManager.getBackads(), adRequest,
new InterstitialAdLoadCallback() {
#Override
public void onAdLoaded(#NonNull InterstitialAd interstitialAd) {
// The mInterstitialAd reference will be null until
// an ad is loaded.
interstitial = interstitialAd;
Log.i(TAG, "onAdLoaded");
}
#Override
public void onAdFailedToLoad(#NonNull LoadAdError loadAdError) {
// Handle the error
Log.i(TAG, loadAdError.getMessage());
interstitial = null;
}
});
progressBar = findViewById(R.id.progressBar);
processToken();
listenCast();
}
MediaRouteButton mediaRouteButton;
CastContext castContext;
RemoteMediaClient remoteMediaClient;
public boolean initCast() {
url = getIntent().getStringExtra(getString(R.string.url));
userAgent = getIntent().getStringExtra(getString(R.string.user_agent));
tokenEnable = getIntent().getBooleanExtra(getString(R.string.t_enable), false);
mediaRouteButton = (MediaRouteButton) findViewById(R.id.media_route_button);
CastButtonFactory.setUpMediaRouteButton(getApplicationContext(), mediaRouteButton);
if (castContext == null)
castContext = CastContext.getSharedInstance(this);
castContext.addCastStateListener(new CastStateListener() {
#Override
public void onCastStateChanged(int state) {
/*if (state == CastState.NO_DEVICES_AVAILABLE) {
// mediaRouteButton.setVisibility(View.GONE);
}
else if(state==CastState.CONNECTING) {
showToast("Connecting");
} else*/ if (state == CastState.CONNECTED) {
// showToast("Connected");
// castMetadata();
openCastPlayer();
}/* else if (mediaRouteButton.getVisibility() == View.GONE) {
mediaRouteButton.setVisibility(View.VISIBLE);
}*/
}
});
if (castContext.getCastState() == CastState.CONNECTED) {
openCastPlayer();
return true;
} else {
// showToast("not connected");
}
if (castContext.getCastState() != CastState.NO_DEVICES_AVAILABLE)
mediaRouteButton.setVisibility(View.VISIBLE);
return false;
}
private void registerListener() {
if (mCastContext != null) {
mCastContext.getSessionManager().addSessionManagerListener(
mSessionManagerListener, CastSession.class);
}
}
private void unRegisterListener() {
if (mCastContext != null) {
mCastContext.getSessionManager().removeSessionManagerListener(
mSessionManagerListener, CastSession.class);
}
}
private void showToast(String connecting) {
Toast.makeText(this, connecting, Toast.LENGTH_SHORT).show();
}
private void processToken() {
if (!HelperClass.isValid(url) || !tokenEnable) {
init("");
return;
}
HashMap<String, Object> hashMap = new HashMap<>();
enqueue(getLocInterface().getLoc(sessionManager.getToken(), hashMap), new CallBack<Location>() {
#Override
public void onComplete() {
super.onComplete();
}
#Override
public void onError(Throwable e) {
super.onError(e);
Toast.makeText(Exo_Player.this,
"Failed to process url", Toast.LENGTH_SHORT).show();
}
#Override
public void onNext(#NotNull Location location) {
super.onNext(location);
if (location.appendResult != null)
init(location.appendResult);
}
});
}
private void init(String s) {
url += s;
Log.e(TAG, "init: new url is " + url);
mediaDataSourceFactory = buildDataSourceFactory(true);
mainHandler = new Handler();
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
RenderersFactory renderersFactory = new DefaultRenderersFactory(this);
// TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
// TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
// TrackSelector trackSelector = new DefaultTrackSelector();
LoadControl loadControl = new DefaultLoadControl();
player = new SimpleExoPlayer.Builder(this, renderersFactory).setLoadControl(loadControl).build();
playerView = findViewById(R.id.exoPlayerView);
playerView.setPlayer(player);
playerView.setUseController(true);
playerView.requestFocus();
Uri uri = Uri.parse(url);
final MediaSource mediaSource = buildMediaSource(uri, null);
player.prepare(mediaSource);
player.setPlayWhenReady(true);
player.addListener(new Player.Listener() {
#Override
public void onTracksChanged(#NotNull TrackGroupArray trackGroups, #NotNull TrackSelectionArray trackSelections) {
Log.d(TAG, "onTracksChanged: " + trackGroups.length);
}
#Override
public void onIsLoadingChanged(boolean isLoading) {
Log.d(TAG, "onLoadingChanged: " + isLoading);
}
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
Log.d(TAG, "onPlayerStateChanged: " + playWhenReady);
if (playbackState == PlaybackStateCompat.STATE_PLAYING) {
progressBar.setVisibility(View.GONE);
}
}
#Override
public void onRepeatModeChanged(int repeatMode) {
}
#Override
public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
}
#Override
public void onPlayerError(#NotNull PlaybackException error) {
Log.e(TAG, "onPlayerError: ", error);
player.stop();
// errorDialog();
player.prepare(mediaSource);
player.setPlayWhenReady(true);
}
#Override
public void onPositionDiscontinuity(int reason) {
Log.d(TAG, "onPositionDiscontinuity: true");
}
#Override
public void onPlaybackParametersChanged(#NotNull PlaybackParameters playbackParameters) {
}
#Override
public void onSeekProcessed() {
}
});
Log.d("INFO", "ActivityVideoPlayer");
}
private void pausePlayer() {
player.setPlayWhenReady(false);
player.getPlaybackState();
}
private void startPlayer() {
player.setPlayWhenReady(true);
player.getPlaybackState();
}
#Override
protected void onPause() {
super.onPause();
try {
unRegisterListener();
pausePlayer();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
protected void onResume() {
super.onResume();
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
/////////////////////////////////////////////
try {
registerListener();
if (HelperClass.vpn(this)) {
finish();
}
startPlayer();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onDestroy() {
super.onDestroy();
Log.v(TAG, "onDestroy()...");
if (player != null)
player.release();
}
private MediaSource buildMediaSource(Uri uri, String overrideExtension) {
int type = TextUtils.isEmpty(overrideExtension) ? Util.inferContentType(uri)
: Util.inferContentType("." + overrideExtension);
switch (type) {
case C.TYPE_SS:
return new SsMediaSource.Factory(new DefaultSsChunkSource.Factory(mediaDataSourceFactory), buildDataSourceFactory(false)).createMediaSource(uri);
case C.TYPE_DASH:
return new DashMediaSource.Factory(new DefaultDashChunkSource.Factory(mediaDataSourceFactory), buildDataSourceFactory(false)).createMediaSource(uri);
case C.TYPE_HLS:
return new HlsMediaSource.Factory(mediaDataSourceFactory).createMediaSource(uri);
case C.TYPE_OTHER:
return new ProgressiveMediaSource.Factory(mediaDataSourceFactory).createMediaSource(uri);
default: {
throw new IllegalStateException("Unsupported type: " + type);
}
}
}
private DataSource.Factory buildDataSourceFactory(boolean useBandwidthMeter) {
return buildDataSourceFactory(useBandwidthMeter ? BANDWIDTH_METER : null);
}
public DataSource.Factory buildDataSourceFactory(DefaultBandwidthMeter bandwidthMeter) {
return new DefaultDataSourceFactory(this, bandwidthMeter,
buildHttpDataSourceFactory(bandwidthMeter));
}
public HttpDataSource.Factory buildHttpDataSourceFactory(DefaultBandwidthMeter bandwidthMeter) {
String s = "xxxxx";
if (userAgent != null && !userAgent.isEmpty()) {
s = userAgent;
}
return new DefaultHttpDataSourceFactory(getUserAgent2(this, s), bandwidthMeter);
}
public static String getUserAgent2(Context context, String applicationName) {
return applicationName
+ "";
}
#Override
public void onBackPressed() {
super.onBackPressed();
if (interstitial != null) {
interstitial.show(Exo_Player.this);
}
if (player != null)
player.stop();
}
// public void errorDialog() {
// new AlertDialog.Builder(this)
// .setIcon(android.R.drawable.ic_dialog_alert)
// .setTitle(getResources().getString(R.string.msg_oops))
// .setCancelable(false)
// .setMessage(getResources().getString(R.string.msg_failed))
// .setPositiveButton(getResources().getString(R.string.option_retry), new DialogInterface.OnClickListener() {
// #Override
// public void onClick(DialogInterface dialog, int which) {
// retryLoad();
// z }
//
// })
// .setNegativeButton(getResources().getString(R.string.option_no), new DialogInterface.OnClickListener() {
// #Override
// public void onClick(DialogInterface dialogInterface, int i) {
// finish();
// }
// })
// .show();
// }
// public void retryLoad() {
// Uri uri = Uri.parse(url);
// MediaSource mediaSource = buildMediaSource(uri, null);
// player.prepare(mediaSource);
// player.setPlayWhenReady(true);
// }
public void castplayer(String name, String link, String unique, String img) {
if (!isCastApiAvailable()) {
return;
}
Context context = this;
CastSession castSession = CastContext.getSharedInstance(context).getSessionManager()
.getCurrentCastSession();
if (castSession.isConnected()) {
MediaMetadata movieMetadata = new MediaMetadata(MediaMetadata.MEDIA_TYPE_GENERIC);
movieMetadata.putString(MediaMetadata.KEY_TITLE, name);
MediaInfo mediaInfo = new MediaInfo.Builder(link)
.setMetadata(movieMetadata)
.setEntity(unique)
.build();
final RemoteMediaClient remoteMediaClient = castSession.getRemoteMediaClient();
if (remoteMediaClient == null) {
// Timber.tag(TAG).w("showQueuePopup(): null RemoteMediaClient");
return;
}
if (remoteMediaClient.isPlaying()) {
MediaInfo curMedia = remoteMediaClient.getMediaInfo();
if (curMedia != null && curMedia.getEntity().equals(unique)) {
return;
}
}
if (remoteMediaClient.isLoadingNextItem() || remoteMediaClient.isBuffering()) {
return;
}
// final QueueDataProvider provider = QueueDataProvider.getInstance(context);
// PopupMenu popup = new PopupMenu(context, binding.epLayout);
// popup.getMenuInflater().inflate(
// provider.isQueueDetached() || provider.getCount() == 0
// ? R.menu.detached_popup_add_to_queue
// : R.menu.popup_add_to_queue, popup.getMenu());
// PopupMenu.OnMenuItemClickListener clickListener = menuItem -> {
// QueueDataProvider provider1 = QueueDataProvider.getInstance(context);
// MediaQueueItem queueItem = new MediaQueueItem.Builder(mediaInfo).setAutoplay(
// false).setPreloadTime(2).build();
// MediaQueueItem[] newItemArray = new MediaQueueItem[]{queueItem};
// String toastMessage = null;
// if (provider1.isQueueDetached() && provider1.getCount() > 0) {
// if ((menuItem.getItemId() == R.id.action_play_now)
// || (menuItem.getItemId() == R.id.action_add_to_queue)) {
// MediaQueueItem[] items = Utils
// .rebuildQueueAndAppend(provider1.getItems(), queueItem);
// remoteMediaClient.queueLoad(items, provider1.getCount(),
// MediaStatus.REPEAT_MODE_REPEAT_OFF, null);
// } else {
// return false;
// }
// } else {
// if (provider1.getCount() == 0) {
// remoteMediaClient.queueLoad(newItemArray, 0,
// MediaStatus.REPEAT_MODE_REPEAT_OFF, null);
// } else {
// int currentId = provider1.getCurrentItemId();
//// if (menuItem.getItemId() == R.id.action_play_now) {
// remoteMediaClient.queueInsertAndPlayItem(queueItem, currentId, null);
remoteMediaClient.load(mediaInfo, new MediaLoadOptions.Builder().build());
// } else if (menuItem.getItemId() == R.id.action_play_next) {
// int currentPosition = provider1.getPositionByItemId(currentId);
// if (currentPosition == provider1.getCount() - 1) {
// //we are adding to the end of queue
// remoteMediaClient.queueAppendItem(queueItem, null);
// } else {
// int nextItemId = provider1.getItem(currentPosition + 1).getItemId();
// remoteMediaClient.queueInsertItems(newItemArray, nextItemId, null);
// }
// toastMessage = context.getString(
// R.string.queue_item_added_to_play_next);
// } else if (menuItem.getItemId() == R.id.action_add_to_queue) {
// remoteMediaClient.queueAppendItem(queueItem, null);
// toastMessage = context.getString(R.string.queue_item_added_to_queue);
// } else {
// return false;
// }
// }
// }
// if (menuItem.getItemId() == R.id.action_play_now) {
Intent intent = new Intent(context, ExpandedControlsActivity.class);
context.startActivity(intent);
// }
// if (!TextUtils.isEmpty(toastMessage)) {
// Toast.makeText(context, toastMessage, Toast.LENGTH_SHORT).show();
// }
// return true;
// };
// popup.setOnMenuItemClickListener(clickListener);
// popup.show();
// }
} else {
Toast.makeText(context,
"Not Connected", Toast.LENGTH_SHORT).show();
}
}
private CastContext mCastContext;
private CastSession mCastSession;
private SessionManagerListener<CastSession> mSessionManagerListener;
private void listenCast() {
if (!isCastApiAvailable()) {
return;
}
setupCastListener();
mCastContext = CastContext.getSharedInstance(this);
mCastSession = mCastContext.getSessionManager().getCurrentCastSession();
}
private void setupCastListener() {
mSessionManagerListener = new SessionManagerListener<CastSession>() {
#Override
public void onSessionEnded(CastSession session, int error) {
onApplicationDisconnected();
mCastContext = null;
mCastSession = null;
}
#Override
public void onSessionResumed(CastSession session, boolean wasSuspended) {
onApplicationConnected(session);
}
#Override
public void onSessionResumeFailed(CastSession session, int error) {
onApplicationDisconnected();
}
#Override
public void onSessionStarted(CastSession session, String sessionId) {
onApplicationConnected(session);
}
#Override
public void onSessionStartFailed(CastSession session, int error) {
onApplicationDisconnected();
}
#Override
public void onSessionStarting(CastSession session) {
}
#Override
public void onSessionEnding(CastSession session) {
}
#Override
public void onSessionResuming(CastSession session, String sessionId) {
}
#Override
public void onSessionSuspended(CastSession session, int reason) {
}
private void onApplicationConnected(CastSession castSession) {
mCastSession = castSession;
openCastPlayer();
invalidateOptionsMenu();
}
private void onApplicationDisconnected() {
invalidateOptionsMenu();
}
};
}
private void openCastPlayer() {
castplayer(getString(R.string.app_name), url, url, url);
finish();
}
}
I remember that was changed with the newer updates at some point last year. Now you need to pass a map to setDefaultRequestProperties after building a HttpDataSource. Using a DefaultHttpDataSource.Factory should be enough if you are not considering using a custom one.
Trying to run MIDI on my Android app. I'm following the midisuite example to configure my app and it works fine with the exception of aftertouch. Whenever I try to trigger aftertouch, I run into a threading exception type
InteruptedException. How should I prevent this threading issue? My knowledge on multithreading isn't the best or else I would've figured this out already. All I can really tell right now is that the message is sending too fast and the thread hasn't woken up yet from its sleep call.
I followed the github repo with my code as follows:
MidiReceiver subclass:
#TargetApi(Build.VERSION_CODES.M)
public class MidiEngine extends MidiReceiver {
public AudioActivity activity;
private MidiEventScheduler eventScheduler;
private MidiFramer midiFramer;
private MidiReceiver midiReceiver = new MyReceiver();
private Thread mThread;
private boolean go;
private int mProgram;
public MidiEngine() {
this(new AudioActivity());
}
public MidiEngine(AudioActivity activity) {
this.activity = activity;
midiReceiver = new MyReceiver();
midiFramer = new MidiFramer(midiReceiver);
}
public AudioActivity getActivity() {
return this.activity;
}
/* This will be called when MIDI data arrives. */
#Override
public void onSend(byte[] data, int offset, int count, long timestamp)
throws IOException {
if (eventScheduler != null) {
if (!MidiConstants.isAllActiveSensing(data, offset, count)) {
eventScheduler.getReceiver().send(data, offset, count,
timestamp);
}
}
}
// Custom Listener to send to correct methods
private class MyReceiver extends MidiReceiver {
#Override
public void onSend(byte[] msg, int offset, int count, long timestamp) throws IOException {
byte command = (byte)(msg[0] & MidiConstants.STATUS_COMMAND_MASK);
int channel = (byte)(msg[0] & MidiConstants.STATUS_CHANNEL_MASK);
switch (command) {
case MidiConstants.STATUS_NOTE_ON:
activity.keyDown(i, msg[1], msg[2]);
break;
case MidiConstants.STATUS_NOTE_OFF:
activity.keyUp(channel, msg[1]);
break;
case MidiConstants.STATUS_POLYPHONIC_AFTERTOUCH:
activity.keyDown(channel, msg[1], msg[2]);
break;
case MidiConstants.STATUS_PITCH_BEND:
activity.pitchBendAction(channel, (msg[2] << 7) + msg[1]);
break;
case MidiConstants.STATUS_CONTROL_CHANGE:
activity.ccAction(channel, msg[1], msg[2]);
break;
case MidiConstants.STATUS_PROGRAM_CHANGE:
mProgram = msg[1];
break;
default:
break;
}
}
}
class MyRunnable implements Runnable {
#Override
public void run() {
do {
try {
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
try {
processMidiEvents();
}
catch (Exception e) {
Log.e("Java", "SynthEngine background thread exception.", e);
}
}
});
Thread.sleep(100);
}
catch (InterruptedException e) {
Log.e("Java", "Threading exception", e);
}
}
while (go);
}
}
/**
* #throws IOException
*
*/
private void processMidiEvents() throws IOException {
long now = System.nanoTime();
MidiEventScheduler.MidiEvent event = (MidiEventScheduler.MidiEvent) eventScheduler.getNextEvent(now);
while (event != null) {
midiFramer.send(event.data, 0, event.count, event.getTimestamp());
eventScheduler.addEventToPool(event);
event = (MidiEventScheduler.MidiEvent) eventScheduler.getNextEvent(now);
}
}
public void start() {
stop();
go = true;
mThread = new Thread(new MyRunnable());
mThread.setPriority(6);
eventScheduler = new MidiEventScheduler();
mThread.start();
}
public void stop() {
go = false;
if (mThread != null) {
try {
mThread.interrupt();
mThread.join(500);
}
catch (Exception e) {
}
mThread = null;
eventScheduler = null;
}
}
}
Stack Trace Error (line 154 refers to the Thread.sleep part in my custom Runnable class):
Java: Threading exception
java.lang.InterruptedException
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:1031)
at java.lang.Thread.sleep(Thread.java:985)
at com.rfoo.midiapp.communication.MidiEngineInput$MyRunnable.run(MidiEngineInput.java:154)
at java.lang.Thread.run(Thread.java:818)
Thanks!
EDIT: Thread start
Midi Device Service subclass (thread will start whenever a device has connected or disconnected).
#TargetApi(Build.VERSION_CODES.M)
public class MidiSynthDeviceService extends MidiDeviceService {
private static final String TAG = "MidiSynthDeviceService";
private boolean midiStarted = false;
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy() {
AudioActivity.midiEngine.stop();
super.onDestroy();
}
#Override
// Declare the receivers associated with your input ports.
public MidiReceiver[] onGetInputPortReceivers() {
return new MidiReceiver[] { AudioActivity.midiEngine };
}
/**
* This will get called when clients connect or disconnect.
* You can use it to turn on your synth only when needed.
*/
#Override
public void onDeviceStatusChanged(MidiDeviceStatus status) {
if (status.isInputPortOpen(0) && !midiStarted) {
AudioActivity.midiEngine.start();
midiStarted = true;
} else if (!status.isInputPortOpen(0) && midiStarted){
AudioActivity.midiEngine.stop();
midiStarted = false;
}
}
}
Activity class:
public class AudioActivity extends AppCompatActivity {
private Thread thread;
public static MidiEngine midiEngine;
#Override
protected void onCreate(Bundle savedInstanceState) {
// Layout inits
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
// Setup MIDI:
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_MIDI)) {
Toast.makeText(this, "MIDI not supported!", Toast.LENGTH_LONG).show();
}
else {
midiEngine = new MidiEngine(this);
setupMidi();
}
// Setup audio thread:
if (thread == null) {
thread = new Thread() {
public void run() {
setPriority(Thread.MAX_PRIORITY);
// Runs an Open SL audio thread (C++)
// This generates a waveform.
// AudioEngine is a wrapper class connecting C++ to Java
AudioEngine.runProcess();
}
}
}
}
public void setupMidi() {
if (activity == null) activity = (AudioActivity) getContext();
mMidiManager = (MidiManager) activity.getSystemService(AudioActivity.MIDI_SERVICE);
if (mMidiManager == null) {
Toast.makeText(activity, "MidiManager is null!", Toast.LENGTH_LONG).show();
return;
}
// Get Device Info
MidiDeviceInfo deviceInfo = MidiTools.findDevice(mMidiManager, "RFOO", "AudioApp");
// MIDI Input
portIndex = 0;
inputPortSelector = new MidiOutputPortConnectionSelector(mMidiManager, activity, R.id
.inputListView, deviceInfo, portIndex);
inputPortSelector.setConnectedListener(new MyPortsConnectedListener());
midi_ch_input = 0;
midi_ch_output = 0;
}
// Bunch of UI code here....
}
I'm new to Android app developing, and I've tried to program a very simple app: each time the headphone cable is inserted it will play a random song from the collection, and stop whenever the headphone cable is disconnected.
However, I now face a very strange problem: no matter what I do, the app plays always two songs at the same time.
It's very strange because I tried to synchronize everything but it didn't solve the issue...
Here follows my code. Thanks in advance for any help!
public class MainActivity extends AppCompatActivity {
private int countMusic;
private boolean headphones= false;
private HeadphonePlugReceiver receiver;
private HashMap<Integer, String> playing_title;
private RandomPlayer player;
Object lock = new Object();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
playing_title = new HashMap<>();
scanAgain();
Button scanButton = (Button)findViewById(R.id.scan_again);
scanButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
scanAgain();
}
});
updateStatus();
receiver = new HeadphonePlugReceiver();
registerReceiver(receiver, new IntentFilter(Intent.ACTION_HEADSET_PLUG));
}
private void updateStatus() {
runOnUiThread(new Runnable() {
#Override
public void run() {
TextView statusTextView = (TextView)findViewById(R.id.status);
TextView titleTextView = (TextView)findViewById(R.id.title);
if (headphones) {
statusTextView.setText("Headphones connected!");
String txt = "";
for (Integer cd: playing_title.keySet()) {
txt += String.format("%d: %s ### ", cd, playing_title.get(cd).replace("_", " "));
}
titleTextView.setText(txt);
} else {
statusTextView.setText("Headphones not connected.");
titleTextView.setText("Music not playing");
}
}
});
}
private void addDebug(final String code) {
runOnUiThread(new Runnable() {
#Override
public void run() {
TextView debugTextView = (TextView)findViewById(R.id.debug);
String dbg = String.format("%s \n %s", debugTextView.getText(), code);
debugTextView.setText(dbg);
}
});
}
private void addError(final String msg) {
runOnUiThread(new Runnable() {
#Override
public void run() {
TextView errorTextView = (TextView)findViewById(R.id.error);
errorTextView.setText(msg);
}
});
}
private void startPlayer() {
if (player == null) {
player = new RandomPlayer(this);
player.start();
}
}
private void stopPlayer() {
if (player != null) {
player.interr();
player = null;
}
}
private void scanAgain() {
try {
TextView countTextView = (TextView)findViewById(R.id.count);
countTextView.setText("Scanning... ");
countMusic = scanMusic().getCount();
countTextView.setText(String.format("Music file found: %d", countMusic));
}
catch(Exception e) {
Log.e("problem", e.getMessage());
}
}
public Cursor scanMusic() {
ContentResolver cr = this.getContentResolver();
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String selection = MediaStore.Audio.Media.IS_MUSIC + "!= 0";
String sortOrder = MediaStore.Audio.Media.TITLE + " ASC";
String[] projection = {
MediaStore.Audio.Media._ID,
MediaStore.Audio.Media.TITLE,
MediaStore.Audio.Media.DATA,
MediaStore.Audio.Media.DISPLAY_NAME,
MediaStore.Audio.Media.DURATION,
MediaStore.Audio.Media.TITLE_KEY
};
Cursor cur = cr.query(uri, projection, selection, null, sortOrder);
return cur;
}
private class HeadphonePlugReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
synchronized (lock) {
int state = intent.getIntExtra("state", 0);
managePlayer(state);
// Log.e("state", String.format("state: %d", state));
}
}
private void managePlayer(int state) {
boolean n_headphones = (state != 0);
if (n_headphones == headphones)
return;
headphones = n_headphones;
if (headphones)
startPlayer();
else
stopPlayer();
}
}
private class RandomPlayer extends Thread implements MediaPlayer.OnCompletionListener {
private final MainActivity act;
private final Random r;
private final int code;
private MediaPlayer mp;
private boolean keep_going = true;
Object lock2 = new Object();
public RandomPlayer(MainActivity mainActivity) {
r = new Random(System.currentTimeMillis());
act = mainActivity;
code = r.nextInt(10000);
}
public void onCompletion(MediaPlayer arg0) {
playNext();
}
#Override
public void run() {
playNext();
while (keep_going) {
try {
sleep(100);
} catch (InterruptedException e) {
keep_going = false;
}
}
if (mp != null) {
mp.stop();
mp.release();
mp = null;
}
playing_title.remove(code);
updateStatus();
}
public void interr() {
keep_going = false;
}
private void playNext() {
synchronized (lock2) {
if (mp != null) {
mp.stop();
mp.release();
mp = null;
}
mp = new MediaPlayer();
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
//mp.setVolume(0.9f , 0.9f);
mp.setOnCompletionListener(this);
int chosen = r.nextInt(countMusic);
Cursor cur = scanMusic();
for (int i = 0; i < chosen; i++)
cur.moveToNext();
playing_title.put(code, cur.getString(cur.getColumnIndex(MediaStore.Audio.Media.TITLE)));
try {
int a1 = cur.getColumnIndex(MediaStore.Audio.Media.DATA);
String a2 = cur.getString(a1);
mp.setDataSource(a2);
mp.prepare();
mp.start();
addDebug(a2);
} catch (Exception e) {
Log.e("Randomplayer", "exception", e);
addError(e.getMessage());
}
updateStatus();
}
}
}
}
I am following the this ExampleMediaController tutorial.
This is VideoControlView.java,
package com.otwar.deepak.video_styling;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ProgressBar;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import java.lang.ref.WeakReference;
import java.util.Formatter;
import java.util.Locale;
public class VideoControllerView extends FrameLayout {
private static final String TAG = "VideoControllerView";
private MediaPlayerControl mPlayer;
private Context mContext;
private ViewGroup mAnchor;
private View mRoot;
private ProgressBar mProgress;
private TextView mEndTime, mCurrentTime;
private boolean mShowing;
private boolean mDragging;
private static final int sDefaultTimeout = 3000;
private static final int FADE_OUT = 1;
private static final int SHOW_PROGRESS = 2;
private boolean mUseFastForward;
private boolean mFromXml;
private boolean mListenersSet;
private OnClickListener mNextListener, mPrevListener;
StringBuilder mFormatBuilder;
Formatter mFormatter;
private ImageButton mPauseButton;
private ImageButton mFfwdButton;
private ImageButton mRewButton;
private ImageButton mNextButton;
private ImageButton mPrevButton;
private ImageButton mFullscreenButton;
private Handler mHandler = new MessageHandler(this);
public VideoControllerView(Context context, AttributeSet attrs) {
super(context, attrs);
mRoot = null;
mContext = context;
mUseFastForward = true;
mFromXml = true;
Log.i(TAG, TAG);
}
public VideoControllerView(Context context, boolean useFastForward) {
super(context);
mContext = context;
mUseFastForward = useFastForward;
Log.i(TAG, TAG);
}
public VideoControllerView(Context context) {
this(context, true);
Log.i(TAG, TAG);
}
#Override
public void onFinishInflate() {
if (mRoot != null)
initControllerView(mRoot);
}
public void setMediaPlayer(MediaPlayerControl player) {
mPlayer = player;
updatePausePlay();
updateFullScreen();
}
/**
* Set the view that acts as the anchor for the control view.
* This can for example be a VideoView, or your Activity's main view.
* #param view The view to which to anchor the controller when it is visible.
*/
public void setAnchorView(ViewGroup view) {
mAnchor = view;
LayoutParams frameParams = new LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
);
removeAllViews();
View v = makeControllerView();
addView(v, frameParams);
}
/**
* Create the view that holds the widgets that control playback.
* Derived classes can override this to create their own.
* #return The controller view.
* #hide This doesn't work as advertised
*/
protected View makeControllerView() {
LayoutInflater inflate = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mRoot = inflate.inflate(R.layout.media_controller, null);
initControllerView(mRoot);
return mRoot;
}
private void initControllerView(View v) {
mPauseButton = (ImageButton) v.findViewById(R.id.pause);
if (mPauseButton != null) {
mPauseButton.requestFocus();
mPauseButton.setOnClickListener(mPauseListener);
}
mFullscreenButton = (ImageButton) v.findViewById(R.id.fullscreen);
if (mFullscreenButton != null) {
mFullscreenButton.requestFocus();
mFullscreenButton.setOnClickListener(mFullscreenListener);
}
mFfwdButton = (ImageButton) v.findViewById(R.id.ffwd);
if (mFfwdButton != null) {
mFfwdButton.setOnClickListener(mFfwdListener);
if (!mFromXml) {
mFfwdButton.setVisibility(mUseFastForward ? View.VISIBLE : View.GONE);
}
}
mRewButton = (ImageButton) v.findViewById(R.id.rew);
if (mRewButton != null) {
mRewButton.setOnClickListener(mRewListener);
if (!mFromXml) {
mRewButton.setVisibility(mUseFastForward ? View.VISIBLE : View.GONE);
}
}
// By default these are hidden. They will be enabled when setPrevNextListeners() is called
mNextButton = (ImageButton) v.findViewById(R.id.next);
if (mNextButton != null && !mFromXml && !mListenersSet) {
mNextButton.setVisibility(View.GONE);
}
mPrevButton = (ImageButton) v.findViewById(R.id.prev);
if (mPrevButton != null && !mFromXml && !mListenersSet) {
mPrevButton.setVisibility(View.GONE);
}
mProgress = (ProgressBar) v.findViewById(R.id.mediacontroller_progress);
if (mProgress != null) {
if (mProgress instanceof SeekBar) {
SeekBar seeker = (SeekBar) mProgress;
seeker.setOnSeekBarChangeListener(mSeekListener);
}
mProgress.setMax(1000);
}
mEndTime = (TextView) v.findViewById(R.id.time);
mCurrentTime = (TextView) v.findViewById(R.id.time_current);
mFormatBuilder = new StringBuilder();
mFormatter = new Formatter(mFormatBuilder, Locale.getDefault());
installPrevNextListeners();
}
/**
* Show the controller on screen. It will go away
* automatically after 3 seconds of inactivity.
*/
public void show() {
show(sDefaultTimeout);
}
/**
* Disable pause or seek buttons if the stream cannot be paused or seeked.
* This requires the control interface to be a MediaPlayerControlExt
*/
private void disableUnsupportedButtons() {
if (mPlayer == null) {
return;
}
try {
if (mPauseButton != null && !mPlayer.canPause()) {
mPauseButton.setEnabled(false);
}
if (mRewButton != null && !mPlayer.canSeekBackward()) {
mRewButton.setEnabled(false);
}
if (mFfwdButton != null && !mPlayer.canSeekForward()) {
mFfwdButton.setEnabled(false);
}
} catch (IncompatibleClassChangeError ex) {
// We were given an old version of the interface, that doesn't have
// the canPause/canSeekXYZ methods. This is OK, it just means we
// assume the media can be paused and seeked, and so we don't disable
// the buttons.
}
}
/**
* Show the controller on screen. It will go away
* automatically after 'timeout' milliseconds of inactivity.
* #param timeout The timeout in milliseconds. Use 0 to show
* the controller until hide() is called.
*/
public void show(int timeout) {
if (!mShowing && mAnchor != null) {
setProgress();
if (mPauseButton != null) {
mPauseButton.requestFocus();
}
disableUnsupportedButtons();
LayoutParams tlp = new LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
Gravity.BOTTOM
);
mAnchor.addView(this, tlp);
mShowing = true;
}
updatePausePlay();
updateFullScreen();
// cause the progress bar to be updated even if mShowing
// was already true. This happens, for example, if we're
// paused with the progress bar showing the user hits play.
mHandler.sendEmptyMessage(SHOW_PROGRESS);
Message msg = mHandler.obtainMessage(FADE_OUT);
if (timeout != 0) {
mHandler.removeMessages(FADE_OUT);
mHandler.sendMessageDelayed(msg, timeout);
}
}
public boolean isShowing() {
return mShowing;
}
/**
* Remove the controller from the screen.
*/
public void hide() {
if (mAnchor == null) {
return;
}
try {
mAnchor.removeView(this);
mHandler.removeMessages(SHOW_PROGRESS);
} catch (IllegalArgumentException ex) {
Log.w("MediaController", "already removed");
}
mShowing = false;
}
private String stringForTime(int timeMs) {
int totalSeconds = timeMs / 1000;
int seconds = totalSeconds % 60;
int minutes = (totalSeconds / 60) % 60;
int hours = totalSeconds / 3600;
mFormatBuilder.setLength(0);
if (hours > 0) {
return mFormatter.format("%d:%02d:%02d", hours, minutes, seconds).toString();
} else {
return mFormatter.format("%02d:%02d", minutes, seconds).toString();
}
}
private int setProgress() {
if (mPlayer == null || mDragging) {
return 0;
}
int position = mPlayer.getCurrentPosition();
int duration = mPlayer.getDuration();
if (mProgress != null) {
if (duration > 0) {
// use long to avoid overflow
long pos = 1000L * position / duration;
mProgress.setProgress( (int) pos);
}
int percent = mPlayer.getBufferPercentage();
mProgress.setSecondaryProgress(percent * 10);
}
if (mEndTime != null)
mEndTime.setText(stringForTime(duration));
if (mCurrentTime != null)
mCurrentTime.setText(stringForTime(position));
return position;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
show(sDefaultTimeout);
return true;
}
#Override
public boolean onTrackballEvent(MotionEvent ev) {
show(sDefaultTimeout);
return false;
}
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (mPlayer == null) {
return true;
}
int keyCode = event.getKeyCode();
final boolean uniqueDown = event.getRepeatCount() == 0
&& event.getAction() == KeyEvent.ACTION_DOWN;
if (keyCode == KeyEvent.KEYCODE_HEADSETHOOK
|| keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE
|| keyCode == KeyEvent.KEYCODE_SPACE) {
if (uniqueDown) {
doPauseResume();
show(sDefaultTimeout);
if (mPauseButton != null) {
mPauseButton.requestFocus();
}
}
return true;
} else if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY) {
if (uniqueDown && !mPlayer.isPlaying()) {
mPlayer.start();
updatePausePlay();
show(sDefaultTimeout);
}
return true;
} else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP
|| keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE) {
if (uniqueDown && mPlayer.isPlaying()) {
mPlayer.pause();
updatePausePlay();
show(sDefaultTimeout);
}
return true;
} else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
|| keyCode == KeyEvent.KEYCODE_VOLUME_UP
|| keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {
// don't show the controls for volume adjustment
return super.dispatchKeyEvent(event);
} else if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_MENU) {
if (uniqueDown) {
hide();
}
return true;
}
show(sDefaultTimeout);
return super.dispatchKeyEvent(event);
}
private OnClickListener mPauseListener = new OnClickListener() {
public void onClick(View v) {
doPauseResume();
show(sDefaultTimeout);
}
};
private OnClickListener mFullscreenListener = new OnClickListener() {
public void onClick(View v) {
doToggleFullscreen();
show(sDefaultTimeout);
}
};
public void updatePausePlay() {
if (mRoot == null || mPauseButton == null || mPlayer == null) {
return;
}
if (mPlayer.isPlaying()) {
mPauseButton.setImageResource(R.drawable.ic_media_pause);
} else {
mPauseButton.setImageResource(R.drawable.ic_media_play);
}
}
public void updateFullScreen() {
if (mRoot == null || mFullscreenButton == null || mPlayer == null) {
return;
}
if (mPlayer.isFullScreen()) {
mFullscreenButton.setImageResource(R.drawable.ic_media_fullscreen_shrink);
}
else {
mFullscreenButton.setImageResource(R.drawable.ic_media_fullscreen_stretch);
}
}
private void doPauseResume() {
if (mPlayer == null) {
return;
}
if (mPlayer.isPlaying()) {
mPlayer.pause();
} else {
mPlayer.start();
}
updatePausePlay();
}
private void doToggleFullscreen() {
if (mPlayer == null) {
return;
}
mPlayer.toggleFullScreen();
}
// There are two scenarios that can trigger the seekbar listener to trigger:
//
// The first is the user using the touchpad to adjust the posititon of the
// seekbar's thumb. In this case onStartTrackingTouch is called followed by
// a number of onProgressChanged notifications, concluded by onStopTrackingTouch.
// We're setting the field "mDragging" to true for the duration of the dragging
// session to avoid jumps in the position in case of ongoing playback.
//
// The second scenario involves the user operating the scroll ball, in this
// case there WON'T BE onStartTrackingTouch/onStopTrackingTouch notifications,
// we will simply apply the updated position without suspending regular updates.
private OnSeekBarChangeListener mSeekListener = new OnSeekBarChangeListener() {
public void onStartTrackingTouch(SeekBar bar) {
show(3600000);
mDragging = true;
// By removing these pending progress messages we make sure
// that a) we won't update the progress while the user adjusts
// the seekbar and b) once the user is done dragging the thumb
// we will post one of these messages to the queue again and
// this ensures that there will be exactly one message queued up.
mHandler.removeMessages(SHOW_PROGRESS);
}
public void onProgressChanged(SeekBar bar, int progress, boolean fromuser) {
if (mPlayer == null) {
return;
}
if (!fromuser) {
// We're not interested in programmatically generated changes to
// the progress bar's position.
return;
}
long duration = mPlayer.getDuration();
long newposition = (duration * progress) / 1000L;
mPlayer.seekTo( (int) newposition);
if (mCurrentTime != null)
mCurrentTime.setText(stringForTime( (int) newposition));
}
public void onStopTrackingTouch(SeekBar bar) {
mDragging = false;
setProgress();
updatePausePlay();
show(sDefaultTimeout);
// Ensure that progress is properly updated in the future,
// the call to show() does not guarantee this because it is a
// no-op if we are already showing.
mHandler.sendEmptyMessage(SHOW_PROGRESS);
}
};
#Override
public void setEnabled(boolean enabled) {
if (mPauseButton != null) {
mPauseButton.setEnabled(enabled);
}
if (mFfwdButton != null) {
mFfwdButton.setEnabled(enabled);
}
if (mRewButton != null) {
mRewButton.setEnabled(enabled);
}
if (mNextButton != null) {
mNextButton.setEnabled(enabled && mNextListener != null);
}
if (mPrevButton != null) {
mPrevButton.setEnabled(enabled && mPrevListener != null);
}
if (mProgress != null) {
mProgress.setEnabled(enabled);
}
disableUnsupportedButtons();
super.setEnabled(enabled);
}
private OnClickListener mRewListener = new OnClickListener() {
public void onClick(View v) {
if (mPlayer == null) {
return;
}
int pos = mPlayer.getCurrentPosition();
pos -= 5000; // milliseconds
mPlayer.seekTo(pos);
setProgress();
show(sDefaultTimeout);
}
};
private OnClickListener mFfwdListener = new OnClickListener() {
public void onClick(View v) {
if (mPlayer == null) {
return;
}
int pos = mPlayer.getCurrentPosition();
pos += 15000; // milliseconds
mPlayer.seekTo(pos);
setProgress();
show(sDefaultTimeout);
}
};
private void installPrevNextListeners() {
if (mNextButton != null) {
mNextButton.setOnClickListener(mNextListener);
mNextButton.setEnabled(mNextListener != null);
}
if (mPrevButton != null) {
mPrevButton.setOnClickListener(mPrevListener);
mPrevButton.setEnabled(mPrevListener != null);
}
}
public void setPrevNextListeners(OnClickListener next, OnClickListener prev) {
mNextListener = next;
mPrevListener = prev;
mListenersSet = true;
if (mRoot != null) {
installPrevNextListeners();
if (mNextButton != null && !mFromXml) {
mNextButton.setVisibility(View.VISIBLE);
}
if (mPrevButton != null && !mFromXml) {
mPrevButton.setVisibility(View.VISIBLE);
}
}
}
public interface MediaPlayerControl {
void start();
void pause();
int getDuration();
int getCurrentPosition();
void seekTo(int pos);
boolean isPlaying();
int getBufferPercentage();
boolean canPause();
boolean canSeekBackward();
boolean canSeekForward();
boolean isFullScreen();
void toggleFullScreen();
}
private static class MessageHandler extends Handler {
private final WeakReference<VideoControllerView> mView;
MessageHandler(VideoControllerView view) {
mView = new WeakReference<VideoControllerView>(view);
}
#Override
public void handleMessage(Message msg) {
VideoControllerView view = mView.get();
if (view == null || view.mPlayer == null) {
return;
}
int pos;
switch (msg.what) {
case FADE_OUT:
view.hide();
break;
case SHOW_PROGRESS:
pos = view.setProgress();
if (!view.mDragging && view.mShowing && view.mPlayer.isPlaying()) {
msg = obtainMessage(SHOW_PROGRESS);
sendMessageDelayed(msg, 1000 - (pos % 1000));
}
break;
}
}
}
}
My videoPlayerActivity.java
package com.otwar.deepak.video_styling;
import android.app.Activity;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.FrameLayout;
import java.io.IOException;
public class VideoPlayerActivity extends Activity implements SurfaceHolder.Callback, MediaPlayer.OnPreparedListener, VideoControllerView.MediaPlayerControl {
SurfaceView videoSurface;
MediaPlayer player;
VideoControllerView controller;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_player);
videoSurface = (SurfaceView) findViewById(R.id.videoSurface);
SurfaceHolder videoHolder = videoSurface.getHolder();
videoHolder.addCallback(this);
player = new MediaPlayer();
controller = new VideoControllerView(this);
try {
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setDataSource(this, Uri.parse("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"));
player.setOnPreparedListener(this);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
controller.show();
return false;
}
// Implement SurfaceHolder.Callback
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
player.setDisplay(holder);
player.prepareAsync();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
// End SurfaceHolder.Callback
// Implement MediaPlayer.OnPreparedListener
#Override
public void onPrepared(MediaPlayer mp) {
controller.setMediaPlayer(this);
controller.setAnchorView((FrameLayout) findViewById(R.id.videoSurfaceContainer));
player.start();
}
// End MediaPlayer.OnPreparedListener
// Implement VideoMediaController.MediaPlayerControl
#Override
public boolean canPause() {
return true;
}
#Override
public boolean canSeekBackward() {
return true;
}
#Override
public boolean canSeekForward() {
return true;
}
#Override
public int getBufferPercentage() {
return 0;
}
#Override
public int getCurrentPosition() {
return player.getCurrentPosition();
}
#Override
public int getDuration() {
return player.getDuration();
}
#Override
public boolean isPlaying() {
return player.isPlaying();
}
#Override
public void pause() {
player.pause();
}
#Override
public void seekTo(int i) {
player.seekTo(i);
}
#Override
public void start() {
player.start();
}
#Override
public boolean isFullScreen() {
return false;
}
#Override
public void toggleFullScreen() {
}
// End VideoMediaController.MediaPlayerControl
}
the problem is simple, the media player is blocking the UI when implementing the source from remote server. i used a sync prepare for the initialize the media-player, but its block the UI when reset the media player.
here i written a code using thread, it helps a lot but need a clean solution.
public class QuranPlayerAct extends Activity implements DownloadMusicLstn,SeekBar.OnSeekBarChangeListener, OnClickListener,
MediaPlayer.OnPreparedListener, OnCompletionListener,
PlayerBtnClickedLstn, Runnable {
private static final int PLAY_FROM_LOCAL = 234;
private static final int PLAY_FROM_SERVER = 321;
private static final String TAG = "SongsListAct";
private static final int PAUSED = 756;
private static final int STARTED = 554;
private static final int STOPED = 386;
private static final int CLOSED = 453;
private TextView downloadEsplasedTV;
private RelativeLayout playerRetLay;
private ListView musicLst;
private ProgressBar dwnPrgV;
private ImageView playImgV;
private SeekBar songProgressBar;
private TextView songTitleLabel;
private TextView songCurrentDurationLabel;
private TextView songTotalDurationLabel;
private MediaPlayer mp;
private Utilities utils;
private Handler handler;
private boolean stopDownload;
private RelativeLayout downloadRetLay;
private ArrayList<String> musicFiles;
private ImageButton closeImgV;
private TextView downloadTitle;
private long currentDuration;
private Runnable mUpdateTimeTask = new Runnable() {
public void run() {
if (mPrepared) {
long totalDuration = mp.getDuration();
currentDuration = mp.getCurrentPosition();
songTotalDurationLabel.setText(""
+ utils.milliSecondsToTimer(totalDuration));
songCurrentDurationLabel.setText(""
+ utils.milliSecondsToTimer(currentDuration));
int progress = (int) (utils.getProgressPercentage(
currentDuration, totalDuration));
songProgressBar.setProgress(progress);
}
handler.postDelayed(this, 100);
}
};
private TextView downloadTotalTV;
private TextView downloadPercentageTV;
private ImageView stopImgV;
private ImageButton closeDownloadImgV;
private int fileSize;
private boolean mPrepared;
private ProgressBar songsLoadingPB;
private String url;
private String fName;
private boolean stopped;
private int plLoc;
private int track_no;
private int state;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_quran_player);
// setActionBar();
setActionBar2();
getRefs();
handler = new Handler();
initMediaPlayer();
playerRetLay.setVisibility(View.GONE);
// updateList();
createAppDirectory();
Thread t = new Thread(this);
t.start();
}
private void setActionBar2() {
final ActionBar bar = getActionBar();
bar.setDisplayShowHomeEnabled(false);
bar.setDisplayShowCustomEnabled(true);
bar.setDisplayShowTitleEnabled(false);
bar.setCustomView(R.layout.player_actionbar_lay);
}
/*
* private void setActionBar() { final ActionBar bar = getActionBar();
*
* bar.setDisplayShowHomeEnabled(false);
* bar.setDisplayShowCustomEnabled(true);
* bar.setDisplayShowTitleEnabled(false);
* bar.setCustomView(R.layout.player_actionbar_lay);
*
* TextView tv = (TextView) bar.getCustomView().findViewById(
* R.id.action_bar_title);
*
* try { tv.setTypeface(Typeface .createFromAsset(getAssets(),
* "DANUBE__.TTF")); } catch (Exception e) { e.printStackTrace(); } }
*/
#Override
public void onResume() {
super.onResume();
setVisiblilityToPlayerAndUI(false);
updateProgressBar();
if(state==CLOSED)playerRetLay.setVisibility(View.GONE);
}
#Override
public void onPause() {
super.onPause();
l("Activity paused");
stopDownload = true;
setVisiblilityToPlayerAndUI(false);
handler.removeCallbacks(mUpdateTimeTask);
if (mp != null)
switch (state) {
case STARTED:
mp.pause();
playImgV.setImageResource(R.drawable.play_img);
break;
}
}
private void getRefs() {
musicLst = (ListView) findViewById(R.id.musLst_lstV);
playerRetLay = (RelativeLayout) findViewById(R.id.musLst_player_retLay);
dwnPrgV = (ProgressBar) findViewById(R.id.musLst_down_progbarV);
downloadRetLay = (RelativeLayout) findViewById(R.id.musLst_dwn_retLay);
playImgV = (ImageView) findViewById(R.id.musLst_ply_btn);
songProgressBar = (SeekBar) findViewById(R.id.musLst_seek_bar);
songTitleLabel = (TextView) findViewById(R.id.musLst_mus_det_txt);
songCurrentDurationLabel = (TextView) findViewById(R.id.time_esplased_TV);
songTotalDurationLabel = (TextView) findViewById(R.id.total_time_TV);
closeImgV = (ImageButton) findViewById(R.id.musLst_close_btn);
downloadTitle = (TextView) findViewById(R.id.musLst_down_title_TV);
downloadEsplasedTV = (TextView) findViewById(R.id.time_esplased_TV22);
downloadTotalTV = (TextView) findViewById(R.id.total_time_TV2);
downloadPercentageTV = (TextView) findViewById(R.id.total_percentage);
stopImgV = (ImageView) findViewById(R.id.musLst_stop_btn);
closeDownloadImgV = (ImageButton) findViewById(R.id.close_down_btn);
songsLoadingPB = (ProgressBar) findViewById(R.id.songs_load_progressbar);
}
#Override
public void run() {
if (!isNetworkAvailable()) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(QuranPlayerAct.this,
"No Internet Connection Available",
Toast.LENGTH_LONG).show();
}
});
return;
}
MusicAppUtils appUtils = new MusicAppUtils();
String jsn = appUtils
.getDataFromUrl(MusicAppCommons.HTTP_AIMANSANGAM_COM_LISTFILES_PHP);
if (jsn == null)
return;
jsn = jsn.replace(",]", "]");
musicFiles = appUtils.parseMusicFilesJson(jsn);
updateList();
}
private boolean isNetworkAvailable() {
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager
.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
private void createAppDirectory() {
if (MusicAppCommons
.checkFileExist(MusicAppCommons.AIMANSANGAM_MUSIC_DIR)) {
Log.i(TAG, "app directory already exist");
return;
}
File dir = new File(MusicAppCommons.AIMANSANGAM_MUSIC_DIR);
if (dir.mkdirs())
Log.i(TAG, "app directory created");
}
private void setVisiblilityToPlayerAndUI(boolean b) {
if (b) {
songsLoadingPB.setVisibility(View.VISIBLE);
downloadRetLay.setVisibility(View.VISIBLE);
// playerRetLay.setVisibility(View.VISIBLE);
} else {
songsLoadingPB.setVisibility(View.GONE);
downloadRetLay.setVisibility(View.GONE);
// playerRetLay.setVisibility(View.GONE);
}
}
private void initMediaPlayer() {
utils = new Utilities();
mp = new MediaPlayer();
mp.setOnCompletionListener(this);
songProgressBar.setOnSeekBarChangeListener(this);
playImgV.setOnClickListener(this);
closeDownloadImgV.setOnClickListener(this);
closeImgV.setOnClickListener(this);
stopImgV.setOnClickListener(this);
}
private void resetTimeLabel() {
runOnUiThread(new Runnable() {
#Override
public void run() {
songTotalDurationLabel.setText("..");
songCurrentDurationLabel.setText("..");
}
});
}
public void updateProgressBar() {
handler.removeCallbacks(mUpdateTimeTask);
handler.postDelayed(mUpdateTimeTask, 100);
}
#Override
public void onDestroy() {
super.onDestroy();
handler.removeCallbacks(mUpdateTimeTask);
if (mp != null)
mp.release();
}
public void updateList() {
l("called update list");
if (musicFiles == null)
return;
updateMusicListView(MusicLstAdapter.MUSIC_NOT_DOWNLOADING);
}
private void updateMusicListView(int state) {
final MusicLstAdapter lstAdapter = new MusicLstAdapter(this,
musicFiles, this, state, this);
runOnUiThread(new Runnable() {
#Override
public void run() {
musicLst.setAdapter(lstAdapter);
lstAdapter.notifyDataSetChanged();
}
});
}
#Override
public void onClick(View v) {
if (v == closeDownloadImgV) {
downloadRetLay.setVisibility(View.GONE);
stopDownload = true;
Toast.makeText(this, "Download canceled", Toast.LENGTH_SHORT)
.show();
} else if (v == playImgV) {
if (stopped)
new PlayerThread();
if (mp.isPlaying()) {
if (mp != null) {
state = PAUSED;
mp.pause();
l("pause");
playImgV.setImageResource(R.drawable.play_img);
}
} else {
if (mp != null) {
state = STARTED;
mp.start();
l("start");
playImgV.setImageResource(R.drawable.pause_img);
}
}
} else if (v == closeImgV) {
l("close clicked");
state = CLOSED;
playerRetLay.setVisibility(View.GONE);
handler.removeCallbacks(mUpdateTimeTask);
mp.stop();
mPrepared = false;
new Thread(new Runnable() {
#Override
public void run() {
mp.reset();
}
}).start();
} else if (v == stopImgV) {
l("stop clicked");
state = STOPED;
handler.removeCallbacks(mUpdateTimeTask);
mp.stop();
resetTimeLabel();
playImgV.setImageResource(R.drawable.play_img);
stopped = true;
mPrepared = false;
}
}
// --------************************************************************************
#Override
public void setSize(final int fileSize) {
handler.post(new Runnable() {
#Override
public void run() {
dwnPrgV.setMax(fileSize);
QuranPlayerAct.this.fileSize = fileSize;
float size = (float) fileSize / 1048576;
DecimalFormat format = new DecimalFormat("#.##");
downloadTotalTV.setText(format.format(size) + " MB");
downloadPercentageTV.setText("0 %");
}
});
}
#Override
public void onProgressUpdate(final long total) {
handler.post(new Runnable() {
#Override
public void run() {
dwnPrgV.setProgress((int) total);
float size = (float) total / 1048576;
DecimalFormat format = new DecimalFormat("#.##");
downloadEsplasedTV.setText(format.format(size) + " MB");
float l = total / (float) fileSize * 100;
int round = Math.round(l);
downloadPercentageTV.setText(round + " %");
}
});
}
#Override
public void finished() {
handler.post(new Runnable() {
#Override
public void run() {
downloadRetLay.setVisibility(View.GONE);
}
});
updateMusicListView(MusicLstAdapter.MUSIC_NOT_DOWNLOADING);
}
#Override
public void onDownloadSuccess(boolean success) {
if (success) {
} else {
}
}
#Override
public boolean isStopDownload() {
return stopDownload;
}
#Override
public void downloadStarted(final String fName) {
stopDownload = false;
handler.post(new Runnable() {
#Override
public void run() {
downloadTitle.setText(fName);
downloadRetLay.setVisibility(View.VISIBLE);
}
});
updateMusicListView(MusicLstAdapter.MUSIC_DOWNLOADING);
}
// ----------------*****************************************************************************
#Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromTouch) {
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
handler.removeCallbacks(mUpdateTimeTask);
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
handler.removeCallbacks(mUpdateTimeTask);
int totalDuration = mp.getDuration();
int currentPosition = utils.progressToTimer(seekBar.getProgress(),
totalDuration);
mp.seekTo(currentPosition);
updateProgressBar();
}
#Override
public void onPrepared(MediaPlayer mp) {
l("onprepared");
mPrepared = true;
mp.start();
state = STARTED;
playImgV.setImageResource(R.drawable.pause_img);
}
private void l(String str) {
Log.i(TAG, str);
}
// ---------------------***************************************************************************
private class PlayerThread extends Thread {
public PlayerThread() {
start();
}
#Override
public void run() {
try {
stopped = false;
mPrepared = false;
resetTimeLabel();
mp.reset();
mp.setDataSource(url);
if (plLoc == PLAY_FROM_SERVER) {
mp.prepareAsync();
mp.setOnPreparedListener(QuranPlayerAct.this);
updatePlayerImg(R.drawable.play_img);
} else {
mp.prepare();
mp.start();
mPrepared = true;
state = STARTED;
updatePlayerImg(R.drawable.pause_img);
}
updatePlayerUI();
updateProgressBar();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void updatePlayerUI() {
runOnUiThread(new Runnable() {
#Override
public void run() {
songTitleLabel.setText(fName);
songProgressBar.setProgress(0);
songProgressBar.setMax(100);
}
});
}
}
private void updatePlayerImg(final int playImg) {
runOnUiThread(new Runnable() {
#Override
public void run() {
playImgV.setImageResource(playImg);
}
});
}
// ------------------------------
#Override
public void onCompletion(MediaPlayer mp) {
track_no++;
if (track_no > musicFiles.size() - 1) {
track_no = 0;
}
playerRetLay.setVisibility(View.VISIBLE);
fName = musicFiles.get(track_no);
String filePath = MusicAppCommons.AIMANSANGAM_MUSIC_DIR + "/" + fName;
if (MusicAppCommons.checkFileExist(filePath)) {
url = filePath;
plLoc = PLAY_FROM_LOCAL;
} else {
url = MusicAppCommons.HTTP_AIMANSANGAM_COM_QURAN_FILES + fName;
url = url.replace(" ", "%20");
plLoc = PLAY_FROM_SERVER;
}
new PlayerThread();
}
#Override
public void clickedOnPlayBtn(int val) {
this.track_no = val;
l("song clicked");
playerRetLay.setVisibility(View.VISIBLE);
fName = musicFiles.get(val);
String filePath = MusicAppCommons.AIMANSANGAM_MUSIC_DIR + "/" + fName;
if (MusicAppCommons.checkFileExist(filePath)) {
url = filePath;
plLoc = PLAY_FROM_LOCAL;
} else {
url = MusicAppCommons.HTTP_AIMANSANGAM_COM_QURAN_FILES + fName;
url = url.replace(" ", "%20");
plLoc = PLAY_FROM_SERVER;
}
new PlayerThread();
}
}