I'm currently developing an android application which detect objects using camera using tensorflow detection API. I want to take screenshot of the camera activity where the detection is happening.
How can I take screenshot of the camera activity including the camera preview itself?
This code came from tensorflow demo application. I just want to add a screenshot functionality using a button. That's why I added a button and an Image View. The Image View is where the screenshot preview will show but I dont have any idea on how to implement this :(
This is the code for the camera activity:
CameraActivity.java
public abstract class CameraActivity extends Activity
implements OnImageAvailableListener, Camera.PreviewCallback {
private static final Logger LOGGER = new Logger();
private static final int PERMISSIONS_REQUEST = 1;
private static final String PERMISSION_CAMERA = Manifest.permission.CAMERA;
private static final String PERMISSION_STORAGE = Manifest.permission.WRITE_EXTERNAL_STORAGE;
private boolean debug = false;
private Handler handler;
private HandlerThread handlerThread;
private boolean useCamera2API;
private boolean isProcessingFrame = false;
private byte[][] yuvBytes = new byte[3][];
private int[] rgbBytes = null;
private int yRowStride;
protected int previewWidth = 0;
protected int previewHeight = 0;
private Runnable postInferenceCallback;
private Runnable imageConverter;
#Override
protected void onCreate(final Bundle savedInstanceState) {
LOGGER.d("onCreate " + this);
super.onCreate(null);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_camera);
if (hasPermission()) {
setFragment();
} else {
requestPermission();
}
}
private byte[] lastPreviewFrame;
protected int[] getRgbBytes() {
imageConverter.run();
return rgbBytes;
}
protected int getLuminanceStride() {
return yRowStride;
}
protected byte[] getLuminance() {
return yuvBytes[0];
}
/**
* Callback for android.hardware.Camera API
*/
#Override
public void onPreviewFrame(final byte[] bytes, final Camera camera) {
if (isProcessingFrame) {
LOGGER.w("Dropping frame!");
return;
}
try {
// Initialize the storage bitmaps once when the resolution is known.
if (rgbBytes == null) {
Camera.Size previewSize = camera.getParameters().getPreviewSize();
previewHeight = previewSize.height;
previewWidth = previewSize.width;
rgbBytes = new int[previewWidth * previewHeight];
onPreviewSizeChosen(new Size(previewSize.width, previewSize.height), 90);
}
} catch (final Exception e) {
LOGGER.e(e, "Exception!");
return;
}
isProcessingFrame = true;
lastPreviewFrame = bytes;
yuvBytes[0] = bytes;
yRowStride = previewWidth;
imageConverter =
new Runnable() {
#Override
public void run() {
ImageUtils.convertYUV420SPToARGB8888(bytes, previewWidth, previewHeight, rgbBytes);
}
};
postInferenceCallback =
new Runnable() {
#Override
public void run() {
camera.addCallbackBuffer(bytes);
isProcessingFrame = false;
}
};
processImage();
}
/**
* Callback for Camera2 API
*/
#Override
public void onImageAvailable(final ImageReader reader) {
//We need wait until we have some size from onPreviewSizeChosen
if (previewWidth == 0 || previewHeight == 0) {
return;
}
if (rgbBytes == null) {
rgbBytes = new int[previewWidth * previewHeight];
}
try {
final Image image = reader.acquireLatestImage();
if (image == null) {
return;
}
if (isProcessingFrame) {
image.close();
return;
}
isProcessingFrame = true;
Trace.beginSection("imageAvailable");
final Plane[] planes = image.getPlanes();
fillBytes(planes, yuvBytes);
yRowStride = planes[0].getRowStride();
final int uvRowStride = planes[1].getRowStride();
final int uvPixelStride = planes[1].getPixelStride();
imageConverter =
new Runnable() {
#Override
public void run() {
ImageUtils.convertYUV420ToARGB8888(
yuvBytes[0],
yuvBytes[1],
yuvBytes[2],
previewWidth,
previewHeight,
yRowStride,
uvRowStride,
uvPixelStride,
rgbBytes);
}
};
postInferenceCallback =
new Runnable() {
#Override
public void run() {
image.close();
isProcessingFrame = false;
}
};
processImage();
} catch (final Exception e) {
LOGGER.e(e, "Exception!");
Trace.endSection();
return;
}
Trace.endSection();
}
#Override
public synchronized void onStart() {
LOGGER.d("onStart " + this);
super.onStart();
}
#Override
public synchronized void onResume() {
LOGGER.d("onResume " + this);
super.onResume();
handlerThread = new HandlerThread("inference");
handlerThread.start();
handler = new Handler(handlerThread.getLooper());
}
#Override
public synchronized void onPause() {
LOGGER.d("onPause " + this);
if (!isFinishing()) {
LOGGER.d("Requesting finish");
finish();
}
handlerThread.quitSafely();
try {
handlerThread.join();
handlerThread = null;
handler = null;
} catch (final InterruptedException e) {
LOGGER.e(e, "Exception!");
}
super.onPause();
}
#Override
public synchronized void onStop() {
LOGGER.d("onStop " + this);
super.onStop();
}
#Override
public synchronized void onDestroy() {
LOGGER.d("onDestroy " + this);
super.onDestroy();
}
protected synchronized void runInBackground(final Runnable r) {
if (handler != null) {
handler.post(r);
}
}
#Override
public void onRequestPermissionsResult(
final int requestCode, final String[] permissions, final int[] grantResults) {
if (requestCode == PERMISSIONS_REQUEST) {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED
&& grantResults[1] == PackageManager.PERMISSION_GRANTED) {
setFragment();
} else {
requestPermission();
}
}
}
private boolean hasPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return checkSelfPermission(PERMISSION_CAMERA) == PackageManager.PERMISSION_GRANTED &&
checkSelfPermission(PERMISSION_STORAGE) == PackageManager.PERMISSION_GRANTED;
} else {
return true;
}
}
private void requestPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (shouldShowRequestPermissionRationale(PERMISSION_CAMERA) ||
shouldShowRequestPermissionRationale(PERMISSION_STORAGE)) {
Toast.makeText(CameraActivity.this,
"Camera AND storage permission are required for this demo", Toast.LENGTH_LONG).show();
}
requestPermissions(new String[] {PERMISSION_CAMERA, PERMISSION_STORAGE}, PERMISSIONS_REQUEST);
}
}
// Returns true if the device supports the required hardware level, or better.
private boolean isHardwareLevelSupported(
CameraCharacteristics characteristics, int requiredLevel) {
int deviceLevel = characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
if (deviceLevel == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) {
return requiredLevel == deviceLevel;
}
// deviceLevel is not LEGACY, can use numerical sort
return requiredLevel <= deviceLevel;
}
private String chooseCamera() {
final CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
for (final String cameraId : manager.getCameraIdList()) {
final CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
// We don't use a front facing camera in this sample.
final Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
if (facing != null && facing == CameraCharacteristics.LENS_FACING_FRONT) {
continue;
}
final StreamConfigurationMap map =
characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
if (map == null) {
continue;
}
// Fallback to camera1 API for internal cameras that don't have full support.
// This should help with legacy situations where using the camera2 API causes
// distorted or otherwise broken previews.
useCamera2API = (facing == CameraCharacteristics.LENS_FACING_EXTERNAL)
|| isHardwareLevelSupported(characteristics,
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL);
LOGGER.i("Camera API lv2?: %s", useCamera2API);
return cameraId;
}
} catch (CameraAccessException e) {
LOGGER.e(e, "Not allowed to access camera");
}
return null;
}
protected void setFragment() {
String cameraId = chooseCamera();
Fragment fragment;
if (useCamera2API) {
CameraConnectionFragment camera2Fragment =
CameraConnectionFragment.newInstance(
new CameraConnectionFragment.ConnectionCallback() {
#Override
public void onPreviewSizeChosen(final Size size, final int rotation) {
previewHeight = size.getHeight();
previewWidth = size.getWidth();
CameraActivity.this.onPreviewSizeChosen(size, rotation);
}
},
this,
getLayoutId(),
getDesiredPreviewFrameSize());
camera2Fragment.setCamera(cameraId);
fragment = camera2Fragment;
} else {
fragment =
new LegacyCameraConnectionFragment(this, getLayoutId(), getDesiredPreviewFrameSize());
}
getFragmentManager()
.beginTransaction()
.replace(R.id.container, fragment)
.commit();
}
protected void fillBytes(final Plane[] planes, final byte[][] yuvBytes) {
// Because of the variable row stride it's not possible to know in
// advance the actual necessary dimensions of the yuv planes.
for (int i = 0; i < planes.length; ++i) {
final ByteBuffer buffer = planes[i].getBuffer();
if (yuvBytes[i] == null) {
LOGGER.d("Initializing buffer %d at size %d", i, buffer.capacity());
yuvBytes[i] = new byte[buffer.capacity()];
}
buffer.get(yuvBytes[i]);
}
}
public boolean isDebug() {
return debug;
}
public void requestRender() {
final OverlayView overlay = (OverlayView) findViewById(R.id.debug_overlay);
if (overlay != null) {
overlay.postInvalidate();
}
}
public void addCallback(final OverlayView.DrawCallback callback) {
final OverlayView overlay = (OverlayView) findViewById(R.id.debug_overlay);
if (overlay != null) {
overlay.addCallback(callback);
}
}
public void onSetDebug(final boolean debug) {}
#Override
public boolean onKeyDown(final int keyCode, final KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
debug = !debug;
requestRender();
onSetDebug(debug);
return true;
}
return super.onKeyDown(keyCode, event);
}
protected void readyForNextImage() {
if (postInferenceCallback != null) {
postInferenceCallback.run();
}
}
protected int getScreenOrientation() {
switch (getWindowManager().getDefaultDisplay().getRotation()) {
case Surface.ROTATION_270:
return 270;
case Surface.ROTATION_180:
return 180;
case Surface.ROTATION_90:
return 90;
default:
return 0;
}
}
protected abstract void processImage();
protected abstract void onPreviewSizeChosen(final Size size, final int rotation);
protected abstract int getLayoutId();
protected abstract Size getDesiredPreviewFrameSize();
}
And this is the layout file
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="500dp"
tools:context="org.tensorflow.demo.CameraActivity">
<Button
android:id="#+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Screenshot" />
</FrameLayout>
<ImageView
android:id="#+id/imageView"
android:layout_width="140dp"
android:layout_height="160dp"
android:layout_marginStart="205dp"
android:layout_marginTop="0dp" />
I just want to take screenshot of the activity including the camera where the detection is happening. I tried some tutorials on how to take screenshot. It captures all the parts of the screen but doesnt capture the camera part. It only shows black screen. HELP!
Related
I have a problem in my code. I want to autoplay first video from recyclerview in ExoPlayer, The player is working good on scroll but the first video does not play automatically
public class VideoPlayerRecyclerView extends RecyclerView {
private static final String TAG = "VideoPlayerRecyclerView";
private enum VolumeState {ON, OFF};
// ui
private ImageView thumbnail, volumeControl;
private ProgressBar progressBar;
private View viewHolderParent;
private FrameLayout frameLayout;
private PlayerView videoSurfaceView;
private SimpleExoPlayer videoPlayer;
// vars
private ArrayList<Status_Bakend> mediaObjects = new ArrayList<>();
private int videoSurfaceDefaultHeight = 0;
private int screenDefaultHeight = 0;
private Context context;
private int playPosition = -1;
private boolean isVideoViewAdded;
private RequestManager requestManager;
// controlling playback state
private VolumeState volumeState;
public VideoPlayerRecyclerView(#NonNull Context context) {
super(context);
init(context);
}
public VideoPlayerRecyclerView(#NonNull Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
init(context);
}
private void init(final Context context){
this.context = context.getApplicationContext();
Display display = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
Point point = new Point();
display.getSize(point);
videoSurfaceDefaultHeight = point.x;
screenDefaultHeight = point.y;
videoSurfaceView = new PlayerView(this.context);
videoSurfaceView.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_ZOOM);
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory =
new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector =
new DefaultTrackSelector(videoTrackSelectionFactory);
// 2. Create the player
videoPlayer = ExoPlayerFactory.newSimpleInstance(context, trackSelector);
// Bind the player to the view.
videoSurfaceView.setUseController(false);
videoSurfaceView.setPlayer(videoPlayer);
setVolumeControl(VolumeState.ON);
playVideo(true);
videoPlayer.setPlayWhenReady(true);
addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
Log.d(TAG, "onScrollStateChanged: called.");
if(thumbnail != null){ // show the old thumbnail
thumbnail.setVisibility(VISIBLE);
}
// There's a special case when the end of the list has been reached.
// Need to handle that with this bit of logic
if(!recyclerView.canScrollVertically(1)){
playVideo(true);
}
else{
playVideo(false);
}
}
}
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
}
});
addOnChildAttachStateChangeListener(new OnChildAttachStateChangeListener() {
#Override
public void onChildViewAttachedToWindow(View view) {
}
#Override
public void onChildViewDetachedFromWindow(View view) {
if (viewHolderParent != null && viewHolderParent.equals(view)) {
resetVideoView();
}
}
});
videoPlayer.addListener(new Player.EventListener() {
#Override
public void onTimelineChanged(Timeline timeline, #Nullable Object manifest, int reason) {
}
#Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
}
#Override
public void onLoadingChanged(boolean isLoading) {
}
#Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
switch (playbackState) {
case Player.STATE_BUFFERING:
Log.e(TAG, "onPlayerStateChanged: Buffering video.");
if (progressBar != null) {
progressBar.setVisibility(VISIBLE);
}
break;
case Player.STATE_ENDED:
Log.d(TAG, "onPlayerStateChanged: Video ended.");
videoPlayer.seekTo(0);
break;
case Player.STATE_IDLE:
break;
case Player.STATE_READY:
Log.e(TAG, "onPlayerStateChanged: Ready to play.");
if (progressBar != null) {
progressBar.setVisibility(GONE);
}
if(!isVideoViewAdded){
addVideoView();
}
break;
default:
break;
}
}
#Override
public void onRepeatModeChanged(int repeatMode) {
}
#Override
public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
}
#Override
public void onPlayerError(ExoPlaybackException error) {
}
#Override
public void onPositionDiscontinuity(int reason) {
}
#Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
}
#Override
public void onSeekProcessed() {
}
});
}
public void playVideo(boolean isEndOfList) {
int targetPosition;
if(!isEndOfList){
int startPosition = ((LinearLayoutManager) getLayoutManager()).findFirstVisibleItemPosition();
int endPosition = ((LinearLayoutManager) getLayoutManager()).findLastVisibleItemPosition();
// if there is more than 2 list-items on the screen, set the difference to be 1
if (endPosition - startPosition > 1) {
endPosition = startPosition + 1;
}
// something is wrong. return.
if (startPosition < 0 || endPosition < 0) {
return;
}
// if there is more than 1 list-item on the screen
if (startPosition != endPosition) {
int startPositionVideoHeight = getVisibleVideoSurfaceHeight(startPosition);
int endPositionVideoHeight = getVisibleVideoSurfaceHeight(endPosition);
targetPosition = startPositionVideoHeight > endPositionVideoHeight ? startPosition : endPosition;
}
else {
targetPosition = startPosition;
}
}
else{
targetPosition = mediaObjects.size() - 1;
}
Toast.makeText(context, "playVideo: target position: " + targetPosition, Toast.LENGTH_SHORT).show();
// video is already playing so return
if (targetPosition == playPosition) {
return;
}
// set the position of the list-item that is to be played
playPosition = targetPosition;
if (videoSurfaceView == null) {
return;
}
// remove any old surface views from previously playing videos
videoSurfaceView.setVisibility(INVISIBLE);
removeVideoView(videoSurfaceView);
int currentPosition = targetPosition - ((LinearLayoutManager) getLayoutManager()).findFirstVisibleItemPosition();
View child = getChildAt(currentPosition);
if (child == null) {
return;
}
VideoPlayerViewHolder holder = (VideoPlayerViewHolder) child.getTag();
if (holder == null) {
playPosition = -1;
return;
}
thumbnail = holder.thumbnail;
progressBar = holder.progressBar;
volumeControl = holder.volumeControl;
viewHolderParent = holder.itemView;
requestManager = holder.requestManager;
frameLayout = holder.itemView.findViewById(R.id.media_container);
videoSurfaceView.setPlayer(videoPlayer);
videoPlayer.addVideoListener(new VideoListener() {
#Override
public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) {
frameLayout.getLayoutParams().height = (height * 2);
}
#Override
public void onRenderedFirstFrame() {
}
});
viewHolderParent.setOnClickListener(videoViewClickListener);
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(
context, Util.getUserAgent(context, "RecyclerView VideoPlayer"));
String mediaUrl = mediaObjects.get(targetPosition).getStatus_link();
if (mediaUrl != null) {
MediaSource videoSource = new ExtractorMediaSource.Factory(dataSourceFactory)
.createMediaSource(Uri.parse(mediaUrl));
videoPlayer.prepare(videoSource);
videoPlayer.setPlayWhenReady(true);
}
}
private OnClickListener videoViewClickListener = new OnClickListener() {
#Override
public void onClick(View v) {
toggleVolume();
}
};
/**
* Returns the visible region of the video surface on the screen.
* if some are cut off, it will return less than the #videoSurfaceDefaultHeight
* #param playPosition
* #return
*/
private int getVisibleVideoSurfaceHeight(int playPosition) {
int at = playPosition - ((LinearLayoutManager) getLayoutManager()).findFirstVisibleItemPosition();
Log.d(TAG, "getVisibleVideoSurfaceHeight: at: " + at);
View child = getChildAt(at);
if (child == null) {
return 0;
}
int[] location = new int[2];
child.getLocationInWindow(location);
if (location[1] < 0) {
return location[1] + videoSurfaceDefaultHeight;
} else {
return screenDefaultHeight - location[1];
}
}
// Remove the old player
private void removeVideoView(PlayerView videoView) {
ViewGroup parent = (ViewGroup) videoView.getParent();
if (parent == null) {
return;
}
int index = parent.indexOfChild(videoView);
if (index >= 0) {
parent.removeViewAt(index);
isVideoViewAdded = false;
viewHolderParent.setOnClickListener(null);
}
}
private void addVideoView(){
frameLayout.addView(videoSurfaceView);
isVideoViewAdded = true;
videoSurfaceView.requestFocus();
videoSurfaceView.setVisibility(VISIBLE);
videoSurfaceView.setAlpha(1);
}
private void resetVideoView(){
if(isVideoViewAdded){
removeVideoView(videoSurfaceView);
playPosition = -1;
videoSurfaceView.setVisibility(INVISIBLE);
}
}
public void releasePlayer() {
if (videoPlayer != null) {
videoPlayer.release();
videoPlayer = null;
}
viewHolderParent = null;
}
private void toggleVolume() {
if (videoPlayer != null) {
if (volumeState == VolumeState.OFF) {
Log.d(TAG, "togglePlaybackState: enabling volume.");
setVolumeControl(VolumeState.ON);
} else if(volumeState == VolumeState.ON) {
Log.d(TAG, "togglePlaybackState: disabling volume.");
setVolumeControl(VolumeState.OFF);
}
}
}
private void setVolumeControl(VolumeState state){
volumeState = state;
if(state == VolumeState.OFF){
videoPlayer.setVolume(0f);
animateVolumeControl();
}
else if(state == VolumeState.ON){
videoPlayer.setVolume(1f);
animateVolumeControl();
}
}
private void animateVolumeControl(){
if(volumeControl != null){
volumeControl.bringToFront();
if(volumeState == VolumeState.OFF){
requestManager.load(R.drawable.ic_favorite_border_black_24dp)
.into(volumeControl);
}
else if(volumeState == VolumeState.ON){
requestManager.load(R.drawable.ic_favorite_border_black_24dp)
.into(volumeControl);
}
volumeControl.animate().cancel();
volumeControl.setAlpha(1f);
volumeControl.animate()
.alpha(0f)
.setDuration(600).setStartDelay(1000);
}
}
public void setMediaObjects(ArrayList<Status_Bakend> mediaObjects){
this.mediaObjects = mediaObjects;
}
}
This is my code on recyclerview scroll working fine on scroll but I want to autoplay my first video in recyclerview without scrolling.
Just add this line after setAdapter to the recycler view.
recyclerView.smoothScrollBy(0, -1);
OR
recyclerView.smoothScrollBy(0, 1);
This will solve your problem.
You only need to make the first video play using postDelayed().
I think the reason is that the views of the RecyclerView items are all drawn on the layout and the video play process are duplicated.
I make whole video player app but stuck at mediacontroller. I want to show my own mediacontroller with different button, not the default one. It's 4rth day, i'm just trying to make my own mediacontroller but didn't succeed.
I succeed by doing it with surfaceview but i want to use it with videoview.
I try the following code.
public class MyMediaController extends MediaController {
private static final String TAG = "VideoControllerView";
MediaController.MediaPlayerControl mPlayer;
private Context mContext;
private View 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;
StringBuilder mFormatBuilder;
Formatter mFormatter;
private ImageButton mPauseButton;
private ImageButton mSubtitleButton;
private ImageButton mResizeButton;
private ImageButton mNextButton;
private ImageButton mPrevButton;
private final AccessibilityManager mAccessibilityManager;
public MyMediaController(Context context, AttributeSet attrs) {
super(context, attrs);
mRoot = null;
mContext = context;
mUseFastForward = true;
mFromXml = true;
mAccessibilityManager = (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
}
public MyMediaController(Context context, boolean useFastForward) {
super(context, useFastForward);
mUseFastForward = useFastForward;
mAccessibilityManager = (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
}
public MyMediaController(Context context) {
this(context, true);
mContext = context;
}
#Override
public void setMediaPlayer(MediaController.MediaPlayerControl player) {
mPlayer = player;
updatePausePlay();
}
#Override
public void setAnchorView(View view) {
mAnchor = view;
FrameLayout.LayoutParams frameParams = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
);
removeAllViews();
View v = makeControllerView();
addView(v, frameParams);
}
protected View makeControllerView() {
LayoutInflater inflate = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mRoot = inflate.inflate(R.layout.media_controller_layout, null);
initControllerView(mRoot);
return mRoot;
}
private void initControllerView(View mRoot) {
mPauseButton = mRoot.findViewById(R.id.pause);
if (mPauseButton != null) {
mPauseButton.requestFocus();
mPauseButton.setOnClickListener(mPauseListener);
}
mResizeButton = mRoot.findViewById(R.id.resize);
if (mResizeButton != null) {
mResizeButton.requestFocus();
mResizeButton.setOnClickListener(mResizeListener);
}
mSubtitleButton = mRoot.findViewById(R.id.subtitle);
if (mSubtitleButton != null)
{
mSubtitleButton.requestFocus();
mSubtitleButton.setOnClickListener(mSubtitleListener);
}
mNextButton = mRoot.findViewById(R.id.next);
if (mNextButton != null ) {
mNextButton.requestFocus();
mNextButton.setOnClickListener(mNextListener);
}
mPrevButton = mRoot.findViewById(R.id.prev);
if (mPrevButton != null ) {
mPrevButton.requestFocus();
mPrevButton.setOnClickListener(mPrevListener);
}
mProgress = mRoot.findViewById(R.id.mediacontroller_progress);
if (mProgress != null) {
if (mProgress instanceof SeekBar) {
SeekBar seeker = (SeekBar) mProgress;
seeker.setOnSeekBarChangeListener(mSeekListener);
}
mProgress.setMax(1000);
}
mEndTime = mRoot.findViewById(R.id.time);
mCurrentTime = mRoot.findViewById(R.id.time_current);
mFormatBuilder = new StringBuilder();
mFormatter = new Formatter(mFormatBuilder, Locale.getDefault());
}
public final View.OnClickListener mPauseListener = new OnClickListener() {
#Override
public void onClick(View v) {
doPauseResume();
show(sDefaultTimeout);
}
};
private void doPauseResume() {
if (mPlayer == null) {
return;
}
if (mPlayer.isPlaying()) {
mPlayer.pause();
} else {
mPlayer.start();
}
updatePausePlay();
}
private void updatePausePlay() {
if (mRoot == null || mPauseButton == null)
return;
if (mPlayer.isPlaying())
mPauseButton.setImageResource(R.drawable.ic_pause);
else
mPauseButton.setImageResource(R.drawable.ic_play);
}
public final View.OnClickListener mResizeListener = new OnClickListener() {
#Override
public void onClick(View v) {
//Todo
Toast.makeText(mContext,"Resize is clicked",Toast.LENGTH_SHORT).show();
}
};
public final View.OnClickListener mNextListener = new OnClickListener() {
#Override
public void onClick(View v) {
//Todo
Toast.makeText(mContext,"NextBtn is clicked",Toast.LENGTH_SHORT).show();
}
};
public final View.OnClickListener mPrevListener = new OnClickListener() {
#Override
public void onClick(View v) {
//Todo
Toast.makeText(mContext,"PreviousBtn is clicked",Toast.LENGTH_SHORT).show();
}
};
public final View.OnClickListener mSubtitleListener = new OnClickListener() {
#Override
public void onClick(View v) {
//Todo
Toast.makeText(mContext,"subtitleBtn is clicked",Toast.LENGTH_SHORT).show();
}
};
private final SeekBar.OnSeekBarChangeListener mSeekListener = new SeekBar.OnSeekBarChangeListener() {
#Override
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.
removeCallbacks(mShowProgress);
}
#Override
public void onProgressChanged(SeekBar bar, int progress, boolean fromuser) {
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));
}
#Override
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.
post(mShowProgress);
}
};
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;
}
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 final Runnable mShowProgress = new Runnable() {
#Override
public void run() {
int pos = setProgress();
if (!mDragging && mShowing && mPlayer.isPlaying()) {
postDelayed(mShowProgress, 1000 - (pos % 1000));
}
}
};
#Override
public void show(int timeout) {
if (!mShowing && mAnchor != null) {
setProgress();
if (mPauseButton != null) {
mPauseButton.requestFocus();
}
FrameLayout.LayoutParams tlp = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
Gravity.BOTTOM
);
addView(this, tlp);
mShowing = true;
}
updatePausePlay();
// 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.
post(mShowProgress);
if (timeout != 0 && !mAccessibilityManager.isTouchExplorationEnabled()) {
removeCallbacks(mFadeOut);
postDelayed(mFadeOut, timeout);
}
}
#Override
public boolean isShowing() {
return mShowing;
}
/**
* Remove the controller from the screen.
*/
#Override
public void hide() {
if (mAnchor == null)
return;
if (mShowing) {
try {
removeCallbacks(mShowProgress);
removeView(this);
} catch (IllegalArgumentException ex) {
Log.w("MediaController", "already removed");
}
mShowing = false;
}
}
private final Runnable mFadeOut = new Runnable() {
#Override
public void run() {
hide();
}
};
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
show(0);
break;
case MotionEvent.ACTION_UP:
show(sDefaultTimeout);
break;
case MotionEvent.ACTION_CANCEL:
hide();
break;
default:
break;
}
return true;
}
}
Plz someone suggest my the right way to do it. I realy need help.
So I am new to coding and working with the camera. I don't understand why the cameraId was null. Would really appreciate if someone could help me out. Thanks
Code:
public class CameraFragment extends Fragment {
private TextureView textureView;
private HandlerThread mBackgroundHandlerThread;
private Handler mBackgroundHandler;
private String mCameraId;
private Size mPreviewSize;
public static CameraFragment newInstance() {
return new CameraFragment();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout. fragment_camera, container, false);
textureView = (TextureView) rootView.findViewById(R.id.textureView);
return rootView;
}
private static final int REQUEST_CAMERA_PERMISSION_RESULT = 0;
private TextureView.SurfaceTextureListener surfaceTextureListener = new TextureView.SurfaceTextureListener() {
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
setupCamera(width, height);
connectCamera();
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
};
private CameraDevice mCameraDevice;
private CameraDevice.StateCallback mCameraDeviceStateCallback = new CameraDevice.StateCallback() {
#Override
public void onOpened(#NonNull CameraDevice camera) {
mCameraDevice = camera;
startPreview();
//Toast.makeText(getApplicationContext(), "Camera connected!", Toast.LENGTH_LONG).show();
}
#Override
public void onDisconnected(#NonNull CameraDevice camera) {
camera.close();
mCameraDevice = null;
}
#Override
public void onError(#NonNull CameraDevice camera, int error) {
camera.close();
mCameraDevice = null;
}
};
#Override
public void onResume() {
super.onResume();
startBackgroundThread();
if (textureView.isAvailable()) {
//setupCamera(textureView.getWidth(), textureView.getHeight());
connectCamera();
} else {
textureView.setSurfaceTextureListener(surfaceTextureListener);
}
}
#Override
public void onPause() {
closeCamera();
stopBackgroundThread();
super.onPause();
}
private void closeCamera() {
if(mCameraDevice != null) {
mCameraDevice.close();
mCameraDevice = null;
}
}
private void stopBackgroundThread() {
mBackgroundHandlerThread.quitSafely();
try {
mBackgroundHandlerThread.join();
mBackgroundHandlerThread = null;
mBackgroundHandler = null;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void setupCamera(int width, int height) {
if(mCameraDevice == null)
return;
CameraManager cameraManager = (CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE);
try {
if (cameraManager != null) {
mCameraId = cameraManager.getCameraIdList()[0];
}
assert cameraManager != null;
for (String cameraId : cameraManager.getCameraIdList()) {
CameraCharacteristics cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId);
if(cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) ==
CameraCharacteristics.LENS_FACING_FRONT){
continue;
}
StreamConfigurationMap map = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
int deviceOrientation = getActivity().getWindowManager().getDefaultDisplay().getRotation();
int totalRotation = sensorToDeviceRotation(cameraCharacteristics, deviceOrientation);
boolean swapRotation = totalRotation == 90 || totalRotation == 270;
int rotatedWidth = width;
int rotatedHeight = height;
if (swapRotation){
rotatedWidth = height;
rotatedHeight = width;
}
if (map != null) {
mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class), rotatedWidth, rotatedHeight);
}
mCameraId = cameraId;
return;
}
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void connectCamera() {
CameraManager cameraManager = (CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE);
try {
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA) ==
PackageManager.PERMISSION_GRANTED) {
assert cameraManager != null;
cameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, mBackgroundHandler);
} else {
if (shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) {
Toast.makeText(getActivity(), "This app requires access to camera", Toast.LENGTH_LONG).show();
}
requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION_RESULT);
}
} else {
assert cameraManager != null;
cameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, mBackgroundHandler);
}
}catch(CameraAccessException e){
e.printStackTrace();
}
}
private CaptureRequest.Builder mCaptureRequestBuilder;
private static SparseIntArray ORIENTATIONS = new SparseIntArray();
static {
ORIENTATIONS.append(Surface.ROTATION_0, 0);
ORIENTATIONS.append(Surface.ROTATION_90, 90);
ORIENTATIONS.append(Surface.ROTATION_180, 180);
ORIENTATIONS.append(Surface.ROTATION_270, 270);
}
private static class CompareSizeByArea implements Comparator<Size> {
#Override
public int compare(Size lhs, Size rhs){
return Long.signum((long) lhs.getWidth() * lhs.getHeight() /
(long) rhs.getWidth() * rhs.getHeight());
}
}
private static int sensorToDeviceRotation(CameraCharacteristics cameraCharacteristics, int deviceOrientation){
int sensorOrientation = cameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
deviceOrientation = ORIENTATIONS.get(deviceOrientation);
return(sensorOrientation + deviceOrientation + 360) % 360;
}
public void onWindowFocusChanged (boolean hasFocus) {
super.getActivity().onWindowFocusChanged(hasFocus);
View decorView = getActivity().getWindow().getDecorView();
if(hasFocus){
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
}
}
private void startBackgroundThread() {
mBackgroundHandlerThread = new HandlerThread("Camera Background");
mBackgroundHandlerThread.start();
mBackgroundHandler = new Handler(mBackgroundHandlerThread.getLooper());
}
private void startPreview() {
SurfaceTexture surfaceTexture = textureView.getSurfaceTexture();
assert surfaceTexture != null;
surfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
Surface previewSurface = new Surface(surfaceTexture);
try {
mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
mCaptureRequestBuilder.addTarget(previewSurface);
mCameraDevice.createCaptureSession(Collections.singletonList(previewSurface),
new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(#NonNull CameraCaptureSession session) {
try {
session.setRepeatingRequest(mCaptureRequestBuilder.build(),
null, mBackgroundHandler);
} catch (CameraAccessException e){
e.printStackTrace();
}
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession session) {
Toast.makeText(getActivity(), "Unable to connect to camera", Toast.LENGTH_LONG).show();
}
}, null);
} catch (CameraAccessException e){
e.printStackTrace();
}
}
private static Size chooseOptimalSize(Size[] choices, int width, int height) {
List<Size> bigEnough = new ArrayList<Size>();
for(Size option : choices){
if(option.getHeight() == option.getWidth() * height/width &&
option.getWidth() >= width && option.getHeight() >= height) {
bigEnough.add(option);
}
}
if(bigEnough.size() > 0){
return Collections.min(bigEnough, (Comparator<? super Size>) new CompareSizeByArea());
} else {
return choices[0];
}
}
}
Log:
> FATAL EXCEPTION: main
Process: com.example.patrick.wz, PID: 5246
java.lang.IllegalArgumentException: cameraId was null
at android.hardware.camera2.CameraManager.openCameraForUid(CameraManager.java:454)
at android.hardware.camera2.CameraManager.openCamera(CameraManager.java:430)
at com.example.patrick.wz.Fragments.CameraFragment.connectCamera(CameraFragment.java:214)
at com.example.patrick.wz.Fragments.CameraFragment.access$100(CameraFragment.java:40)
at com.example.patrick.wz.Fragments.CameraFragment$1.onSurfaceTextureAvailable(CameraFragment.java:74)
at android.view.TextureView.getHardwareLayer(TextureView.java:390)
at android.view.TextureView.draw(TextureView.java:339)
at android.view.View.updateDisplayListIfDirty(View.java:18069)
at android.view.View.draw(View.java:18847)
at android.view.ViewGroup.drawChild(ViewGroup.java:4214)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4000)
at android.view.View.updateDisplayListIfDirty(View.java:18060)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4198)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4178)
at android.view.View.updateDisplayListIfDirty(View.java:18028)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4198)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4178)
at android.view.View.updateDisplayListIfDirty(View.java:18028)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4198)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4178)
at android.view.View.updateDisplayListIfDirty(View.java:18028)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4198)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4178)
at android.view.View.updateDisplayListIfDirty(View.java:18028)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4198)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4178)
at android.view.View.updateDisplayListIfDirty(View.java:18028)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4198)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4178)
at android.view.View.updateDisplayListIfDirty(View.java:18028)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4198)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4178)
at android.view.View.updateDisplayListIfDirty(View.java:18028)
at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:659)
at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:757)
at android.view.ViewRootImpl.draw(ViewRootImpl.java:2980)
at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2794)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2347)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1386)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6733)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:911)
at android.view.Choreographer.doCallbacks(Choreographer.java:723)
at android.view.Choreographer.doFrame(Choreographer.java:658)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
In onResume, you've commented out the call to setupCamera, which is what sets mCameraId. So it's still null when you get to connectCamera.
I would appreciate some help with this current problem. I think I understand the cause of the issue, however I have no idea how to fix it. I have two custom views, one implements a ViewGroup and the other just a View.
CameraSourcePreview and GraphicOverlay
However they are both generic to T where T : GraphicOverlay<\T>.Graphic
In BarcodeFragmentActivity. Line 64.
SetContentView(Resource.Layout.Barcode_Capture)
Throws the following error.
System.NotSupportedException: Constructing instances of generic types from Java is not supported, as the type parameters cannot be determined. occurred
Im not sure how to create a full stack trace, as I am using my phone as the test device. Program wont run on an emulator.
Code on Github: https://github.com/StormMaster12/StockApp.
Thought it would be easier to see it on there, than copy all of my code in.
Edit Code Throwing Error.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Content.PM;
using Android.Gms.Vision.Barcodes;
using Android.Gms.Common.Apis;
using Android.Gms.Common;
using Android.Gms.Vision;
using Android.Hardware;
using Android.Support.V4.View;
using Android.Support.V4.App;
using Android.Support.V7.App;
using Android.Support.Design.Widget;
using StockApp.UI;
using Android.Util;
namespace StockApp.BarcodeReader
{
[Activity(Label = "Barcode Fragment Activity")]
class BarcodeFragmentActivity : AppCompatActivity
{
private static string tag = "Barcode-Reader";
private static int RC_HANDLE_GMS = 9001;
private static int RC_HANDLE_CAMERA_PERM = 2;
public static string AutoFocus = "AutoFocus";
public static string UseFlash = "UseFlash";
public static string BarcodeObject = "Barcode";
private CameraSourcePreview<BarcodeGraphic> mPreview;
private Android.Gms.Vision.CameraSource mCameraSource;
private GraphicOverlay<BarcodeGraphic> mGraphicOverlay;
private ScaleGestureDetector scaleGestureDetector;
private GestureDetector getsureDetector;
private View layout;
private static BarcodeFragmentActivity thisInstance;
public override View OnCreateView(View parent, string name, Context context, IAttributeSet attrs)
{
return base.OnCreateView(parent, name, context, attrs);
}
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
thisInstance = this;
SetContentView(Resource.Layout.Barcode_Capture);
//LayoutInflater inflater = LayoutInflater.From(this);
//ViewGroup viewGroup = (ViewGroup)FindViewById(Resource.Id.preview);
//View child = inflater.Inflate(Resource.Layout.layout1, viewGroup, true);
mPreview = (CameraSourcePreview<BarcodeGraphic>)FindViewById(Resource.Id.preview);
mGraphicOverlay = (GraphicOverlay<BarcodeGraphic>)FindViewById(Resource.Id.graphicOverlay);
bool autoFocus = Intent.GetBooleanExtra(AutoFocus, false);
bool useFlash = Intent.GetBooleanExtra(UseFlash, false);
int rc = (int) ActivityCompat.CheckSelfPermission(this, Manifest.Permission.Camera);
if (rc == (int) Permission.Granted)
{
createCameraSource(autoFocus, useFlash);
}
else
{
requestCameraPermission();
}
getsureDetector = new GestureDetector(this, new CaptureGestureListener());
}
private void requestCameraPermission()
{
string[] permissions = new string[] { Manifest.Permission.CallPhone };
if (ActivityCompat.ShouldShowRequestPermissionRationale(this, Manifest.Permission.Camera))
{
Snackbar.Make(layout, "Require Camera Permions To Read Barcodes", Snackbar.LengthIndefinite)
.SetAction("Ok", new Action<View> (delegate(View obj)
{
ActivityCompat.RequestPermissions(this, permissions, RC_HANDLE_CAMERA_PERM);
}
)).Show();
}
else
{
ActivityCompat.RequestPermissions(this, permissions, RC_HANDLE_CAMERA_PERM);
}
//Activity thisActivity = this;
//View.IOnClickListener listener = new View.IOnClickListener;
}
public override bool OnTouchEvent(MotionEvent e)
{
bool b = scaleGestureDetector.OnTouchEvent(e);
bool c = getsureDetector.OnTouchEvent(e);
return b || c || base.OnTouchEvent(e);
}
private void createCameraSource(bool autoFocus, bool useFlash)
{
Context context = ApplicationContext;
BarcodeDetector barcodeDetector = new BarcodeDetector.Builder(context).Build();
BarcodeTrackerFactory barcodeFactory = new BarcodeTrackerFactory(mGraphicOverlay);
barcodeDetector.SetProcessor(
new MultiProcessor.Builder(barcodeFactory).Build());
if (!barcodeDetector.IsOperational)
{
IntentFilter lowstorageFilter = new IntentFilter(Intent.ActionDeviceStorageLow);
bool hasLowStorage = RegisterReceiver(null, lowstorageFilter) != null;
if (hasLowStorage)
{
Toast.MakeText(this, "Low Storage Error", ToastLength.Long);
}
}
Android.Gms.Vision.CameraSource.Builder builder = new Android.Gms.Vision.CameraSource.Builder(base.ApplicationContext, barcodeDetector)
.SetFacing(Android.Gms.Vision.CameraFacing.Back)
.SetRequestedPreviewSize(1600, 1024)
.SetRequestedFps(15.0f)
.SetAutoFocusEnabled(true);
mCameraSource = builder.Build();
}
private void startCameraSource()
{
int code = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(ApplicationContext);
if(code != ConnectionResult.Success)
{
Dialog dig = GoogleApiAvailability.Instance.GetErrorDialog(this, code, RC_HANDLE_GMS);
dig.Show();
}
if (mCameraSource != null)
{
try
{
mPreview.start(mCameraSource, mGraphicOverlay);
}
catch (InvalidOperationException)
{
mCameraSource.Release();
mCameraSource = null;
}
}
}
private bool OnTap(float rawX, float rawY)
{
int[] location = new int[2];
mGraphicOverlay.GetLocationOnScreen(location);
float x = (rawX - location[0]);
float y = (rawY - location[1]);
Barcode best = null;
float bestDistance = float.MaxValue;
foreach (BarcodeGraphic graphic in mGraphicOverlay.getGraphics())
{
Barcode barcode = graphic.GetBarcode();
if(barcode.BoundingBox.Contains((int)x,(int)y))
{
best = barcode;
break;
}
float dx = x - barcode.BoundingBox.CenterX();
float dy = y - barcode.BoundingBox.CenterY();
float distance = (dx * dx) + (dy * dy);
if ( distance > bestDistance)
{
best = barcode;
bestDistance = distance;
}
if (best != null)
{
Intent data = new Intent();
data.PutExtra(BarcodeObject, best);
SetResult(CommonStatusCodes.Success, data);
Finish();
return true;
}
}
return false;
}
protected override void OnResume()
{
base.OnResume();
startCameraSource();
}
protected override void OnPause()
{
base.OnPause();
if (mPreview != null)
{
mPreview.stop();
}
}
protected override void OnDestroy()
{
base.OnDestroy();
if(mPreview != null)
{
mPreview.release();
}
}
private class CaptureGestureListener : GestureDetector.SimpleOnGestureListener
{
public override bool OnSingleTapConfirmed(MotionEvent e)
{
return thisInstance.OnTap(e.RawX, e.RawY) || base.OnSingleTapConfirmed(e);
}
}
private class ScaleListener : ScaleGestureDetector.IOnScaleGestureListener
{
public IntPtr Handle => throw new NotImplementedException();
public void Dispose()
{
throw new NotImplementedException();
}
public bool OnScale(ScaleGestureDetector detector)
{
return false;
}
public bool OnScaleBegin(ScaleGestureDetector detector)
{
return true;
}
public void OnScaleEnd(ScaleGestureDetector detector)
{
}
}
}
}
Code that is being called.
CameraSourcePreview
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Gms.Vision;
using Android.Util;
using Android.Support.Annotation;
using Android.Gms.Common.Images;
using Android.Content.Res;
using Android.Graphics;
namespace StockApp.UI
{
[Register("stockapp.stockapp.ui.CameraSourcePreview")]
class CameraSourcePreview<T> : ViewGroup where T : GraphicOverlay<T>.Graphic
{
private static string TAG = "CameraSourcePreview";
private Context mContext;
private SurfaceView mSurfaceView;
public bool mStartRequested;
private bool mSurfaceAvaialbe;
private Android.Gms.Vision.CameraSource mCameraSource;
private GraphicOverlay<T> mOverlay;
private static CameraSourcePreview<T> Instance { get; set; }
public CameraSourcePreview(Context context, IAttributeSet attrs) : base(context,attrs)
{
mContext = context;
mStartRequested = false;
mSurfaceAvaialbe = false;
SurfaceCallback instance = new SurfaceCallback();
mSurfaceView = new SurfaceView(context);
mSurfaceView.Holder.AddCallback(instance);
AddView(mSurfaceView);
}
public void start(Android.Gms.Vision.CameraSource cameraSource)
{
if (cameraSource == null)
{
stop();
}
mCameraSource = cameraSource;
if(mCameraSource != null)
{
mStartRequested = true;
startIfReady();
}
}
public void start(Android.Gms.Vision.CameraSource cameraSource, GraphicOverlay<T> graphicOverlay)
{
mOverlay = graphicOverlay;
start(cameraSource);
}
public void stop()
{
if(mCameraSource != null)
{
mCameraSource.Stop();
}
}
public void release()
{
if(mCameraSource != null)
{
mCameraSource.Release();
mCameraSource = null;
}
}
private bool isPortaitMode()
{
int orientation = (int)mContext.Resources.Configuration.Orientation;
if (orientation == (int)Android.Content.Res.Orientation.Landscape)
{
return false;
}
else if (orientation == (int)Android.Content.Res.Orientation.Portrait)
{
return true;
}
return false;
}
private void startIfReady()
{
if (mStartRequested && mSurfaceAvaialbe)
{
mCameraSource.Start(mSurfaceView.Holder);
if (mOverlay != null)
{
Android.Gms.Common.Images.Size size = mCameraSource.PreviewSize;
int min = Math.Min(size.Width, size.Height);
int max = Math.Max(size.Width, size.Width);
if(isPortaitMode())
{
mOverlay.setCameraInfo(min, max, (int)mCameraSource.CameraFacing);
}
else
{
mOverlay.setCameraInfo(max, min, (int)mCameraSource.CameraFacing);
}
mOverlay.Clear();
}
mStartRequested = false;
}
}
protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
int intWidth = 320;
int intHeight = 240;
if(mCameraSource != null)
{
Android.Gms.Common.Images.Size size = mCameraSource.PreviewSize;
if(size != null)
{
intWidth = size.Width;
intHeight = size.Height;
}
}
if(isPortaitMode())
{
int tmp = intWidth;
intHeight = intWidth;
intWidth = tmp;
}
int layoutWidth = l - r;
int layoutHeight = t - b;
int childWidth = layoutWidth;
int childHeight = (int)(((float)layoutWidth / (float) intHeight)*intWidth);
if (childHeight > layoutWidth)
{
childHeight = layoutHeight;
childWidth = (int)(((float)layoutHeight / (float)intHeight) * intWidth);
}
for (int i =0 ; i < ChildCount; i++ )
{
GetChildAt(i).Layout(0, 0, childWidth, childHeight);
}
try
{
startIfReady();
}
catch (Exception e)
{
Log.Debug("Something went wrong", e.ToString());
}
}
private class SurfaceCallback : ISurfaceHolderCallback
{
public IntPtr Handle => throw new NotImplementedException();
public void Dispose()
{
}
public void SurfaceChanged(ISurfaceHolder holder, [GeneratedEnum] Format format, int width, int height)
{
}
public void SurfaceCreated(ISurfaceHolder holder)
{
Instance.mSurfaceAvaialbe = true;
try
{
Instance.startIfReady();
}
catch (Exception e)
{
Log.Debug("Something went wrong",e.ToString());
}
}
public void SurfaceDestroyed(ISurfaceHolder holder)
{
Instance.mSurfaceAvaialbe = false;
}
}
}
}
GraphicOverlay
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Gms.Vision;
using Android.Util;
using Android.Graphics;
using Java.Util;
namespace StockApp.UI
{
[Register("stockapp.stockapp.ui.GraphicOverlay")]
class GraphicOverlay<T> : View where T: GraphicOverlay<T>.Graphic
{
public T tT ;
private Object mLock = new object();
private int mPreviewWidth { get; set; }
private float mWidthScaleFactor { get; set; } = 1.0f;
private int mPreviewHeight;
private float mHeightScaleFactor { get; set; } = 1.0f;
private int mFacing { get; set; } = (int)CameraFacing.Back;
private HashSet<T> mGraphics = new HashSet<T>();
public GraphicOverlay(Context context, IAttributeSet attrs)
: base(context, attrs)
{
}
public void Clear()
{
lock(mLock)
{
mGraphics.Clear();
}
}
public void Add(T graphic)
{
lock(mLock)
{
mGraphics.Add(graphic);
}
PostInvalidate();
}
public void Remove(T graphic)
{
lock(mLock)
{
mGraphics.Remove(graphic);
}
PostInvalidate();
}
public List<T> getGraphics()
{
lock(mLock)
{
return mGraphics.ToList();
}
}
public void setCameraInfo(int previewWidth, int previewHeight, int facing)
{
lock(mLock)
{
mPreviewHeight = previewHeight;
mPreviewWidth = previewWidth;
mFacing = facing;
}
PostInvalidate();
}
protected void onDraw(Canvas canvas)
{
base.OnDraw(canvas);
lock(mLock)
{
if(mPreviewWidth !=0 && mPreviewHeight !=0)
{
mWidthScaleFactor = (float)canvas.Width / (float)mPreviewWidth;
mHeightScaleFactor = (float)canvas.Height / (float)mPreviewHeight;
}
foreach (Graphic graphic in mGraphics)
{
graphic.Draw(canvas);
}
}
}
public abstract class Graphic
{
private GraphicOverlay<T> mOverlay;
public Graphic(GraphicOverlay<T> overlay)
{
mOverlay = overlay;
}
public abstract void Draw(Canvas canvas);
public float scaleX(float horizontal) { return horizontal * mOverlay.mWidthScaleFactor; }
public float scaleY(float vertical) { return vertical * mOverlay.mHeightScaleFactor; }
public float translateX(float x)
{
float scale = scaleX(x);
if(mOverlay.mFacing == (int)CameraFacing.Front)
{
return mOverlay.Width - scale;
}
else
{
return scale;
}
}
public float translateY(float y) { return scaleY(y); }
public void postInvalidate() { mOverlay.PostInvalidate(); }
}
}
}
Are there any additional libraries that contain button graphics for the Android ExoPlayer found here. There are the options for fast forward, rewind, play, pause and a few others but there are no options for a mute/unmute or fast forward 2x/4x/etc. I want those options as I build an alternative UI.
Change the Media Controller to provide the options that going to mute/unmute or fast forward. For adding these view(Buttons) in to the view of controller then for that customize the media controller. Check this also Custom Media Controller
VideoControllerView
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;
StringBuilder mFormatBuilder;
Formatter mFormatter;
private ImageButton mPauseButton;
private ImageButton mVolumeButton;
private ImageButton mRewButton;
private ImageButton mSettingButton;
private Button mQualityButton;
private ImageButton mFullscreenButton;
private Handler mHandler = new MessageHandler(this);
private SeekBar seekbar;
private AudioManager audioManager;
private TextView txtVolume;
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);
}
#SuppressLint("MissingSuperCall")
#Override
public void onFinishInflate() {
if (mRoot != null)
initControllerView(mRoot);
}
public void setMediaPlayer(MediaPlayerControl player) {
mPlayer = player;
updatePausePlay();
updateFullScreen(false);
}
/**
* 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.custom_media_controller, null);
initControllerView(mRoot);
return mRoot;
}
#SuppressLint("WrongViewCast")
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);
}
mVolumeButton = (ImageButton) v.findViewById(R.id.volume);
if (mVolumeButton != null) {
mVolumeButton.setOnClickListener(mVolumeListener);
if (!mFromXml) {
//mVolumeButton.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
mSettingButton = (ImageButton) v.findViewById(R.id.settings);
if (mSettingButton != null && !mFromXml && !mListenersSet) {
// mSettingButton.setVisibility(View.GONE);
}
mQualityButton = (Button) v.findViewById(R.id.quality);
if (mQualityButton != null && !mFromXml && !mListenersSet) {
//mQualityButton.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 (mVolumeButton != null && !mPlayer.canSeekForward()) {
mVolumeButton.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();
// 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();
//Log.d(TAG, "Duration->" + duration);
//Log.d(TAG, "Duration Current->" + position);
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 mQualityChangeListener = new OnClickListener() {
public void onClick(View v) {
mPlayer.updateVideoQuality();
}
};
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_pause);
} else {
mPauseButton.setImageResource(R.drawable.ic_play);
}
}
public void updateFullScreen(boolean isFullScreen) {
if (mRoot == null || mFullscreenButton == null || mPlayer == null) {
return;
}
if (isFullScreen) {
mFullscreenButton.setImageDrawable(mContext.getResources().getDrawable(R.drawable.ic_unstretch));
} else {
mFullscreenButton.setImageDrawable(mContext.getResources().getDrawable(R.drawable.ic_stretch));
}
}
private void doPauseResume() {
if (mPlayer == null) {
return;
}
if (mPlayer.isPlaying()) {
mPlayer.pause();
} else {
mPlayer.start();
}
updatePausePlay();
}
private void doToggleFullscreen() {
if (mPlayer == null) {
return;
}
if (mPlayer.isFullScreen()) {
mFullscreenButton.setImageDrawable(mContext.getResources().getDrawable(R.drawable.ic_unstretch));
} else {
mFullscreenButton.setImageDrawable(mContext.getResources().getDrawable(R.drawable.ic_stretch));
}
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 (mVolumeButton != null) {
mVolumeButton.setEnabled(enabled);
}
if (mRewButton != null) {
mRewButton.setEnabled(enabled);
}
if (mSettingButton != null) {
mSettingButton.setEnabled(enabled && mNextListener != null);
}
if (mQualityButton != null) {
mQualityButton.setEnabled(enabled && mQualityChangeListener != 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 -= 15000; // milliseconds
mPlayer.seekTo(pos);
setProgress();
show(sDefaultTimeout);
}
};
private OnClickListener mVolumeListener = new OnClickListener() {
public void onClick(View v) {
if (mPlayer == null) {
return;
}
showPopup(mContext);
}
};
private void installPrevNextListeners() {
if (mSettingButton != null) {
mSettingButton.setOnClickListener(mNextListener);
mSettingButton.setEnabled(mNextListener != null);
}
if (mQualityButton != null) {
mQualityButton.setOnClickListener(mQualityChangeListener);
mQualityButton.setEnabled(mQualityChangeListener != null);
}
}
public void setPrevNextListeners(OnClickListener next, OnClickListener prev) {
mNextListener = next;
mQualityChangeListener = prev;
mListenersSet = true;
if (mRoot != null) {
installPrevNextListeners();
if (mSettingButton != null && !mFromXml) {
mSettingButton.setVisibility(View.VISIBLE);
}
if (mQualityButton != null && !mFromXml) {
mQualityButton.setVisibility(View.VISIBLE);
}
}
}
public interface MediaPlayerControl {
void start();
void pause();
int getDuration();
int getCurrentPosition();
void seekTo(int pos);
boolean isPlaying();
int getAudioSessionId();
int getBufferPercentage();
boolean canPause();
boolean canSeekBackward();
boolean canSeekForward();
boolean isFullScreen();
void toggleFullScreen();
void updateVideoQuality();
}
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;
}
}
}
// The method that displays the popup.
private void showPopup(final Context context) {
final Dialog dialog = new Dialog(context,
android.R.style.Theme_Translucent_NoTitleBar);
// Inflate the popup_layout.xml
LinearLayout viewGroup = (LinearLayout) findViewById(R.id.popup);
LayoutInflater layoutInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = layoutInflater.inflate(R.layout.popup_volumebar, viewGroup);
seekbar = (SeekBar) layout.findViewById(R.id.seekBar1);
txtVolume = (TextView) layout.findViewById(R.id.txtPopupVolume);
// Setting dialogview
Window window = dialog.getWindow();
window.setGravity(Gravity.CENTER | Gravity.END);
window.setLayout(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
dialog.setTitle(null);
dialog.setCanceledOnTouchOutside(true);
dialog.setContentView(layout);
dialog.setCancelable(true);
dialog.show();
initControls();
}
private void initControls() {
try {
audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
seekbar.setMax(audioManager
.getStreamMaxVolume(AudioManager.STREAM_MUSIC));
seekbar.setProgress(audioManager
.getStreamVolume(AudioManager.STREAM_MUSIC));
txtVolume.setText("" + audioManager.getStreamVolume(AudioManager.STREAM_MUSIC));
seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar arg0) {
}
#Override
public void onStartTrackingTouch(SeekBar arg0) {
}
#Override
public void onProgressChanged(SeekBar arg0, int progress, boolean arg2) {
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC,
progress, 0);
txtVolume.setText("" + progress);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
and custom_media_controller.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:background="#color/TvControllerBackground"
android:gravity="center_horizontal"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal"
android:paddingTop="4dip">
<Button
android:id="#+id/quality"
style="#style/MediaButton.Previous"
android:background="#null"
android:contentDescription="#string/description"
android:paddingLeft="#dimen/size_5"
android:paddingRight="#dimen/size_5"
android:text="#string/hd"
android:textColor="#color/white"
android:textStyle="bold"
android:visibility="gone" />
<ImageButton
android:id="#+id/rew"
style="#style/MediaButton.Rew"
android:contentDescription="#string/description"
android:visibility="gone" />
<ImageButton
android:id="#+id/pause"
style="#style/MediaButton.Play"
android:contentDescription="#string/description" />
<ImageButton
android:id="#+id/volume"
style="#style/MediaButton.Ffwd"
android:contentDescription="#string/description" />
<ImageButton
android:id="#+id/settings"
style="#style/MediaButton.Setting"
android:contentDescription="#string/description"
android:visibility="gone" />
<ImageButton
android:id="#+id/fullscreen"
style="#style/MediaButton.FullScreen"
android:contentDescription="#string/description"
android:visibility="visible" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center_horizontal"
android:orientation="horizontal"
android:paddingBottom="#dimen/size_5">
<TextView
android:id="#+id/time_current"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:paddingLeft="4dip"
android:paddingRight="4dip"
android:paddingTop="4dip"
android:textSize="14sp"
android:textStyle="bold" />
<SeekBar
android:id="#+id/mediacontroller_progress"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="0dip"
android:layout_height="32dip"
android:layout_gravity="center_horizontal"
android:layout_weight="1"
android:progressDrawable="#drawable/apptheme_scrubber_progress_horizontal_holo_light"
android:thumb="#drawable/apptheme_scrubber_control_selector_holo_light" />
<TextView
android:id="#+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:paddingLeft="4dip"
android:paddingRight="4dip"
android:paddingTop="4dip"
android:textSize="14sp"
android:textStyle="bold" />
</LinearLayout>