Here is my MainActivity Where I want to send the chosen GIF To the Wallpaper Service class using Uri :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.setType("*/*");
startActivityForResult(i, 0);
}
});
Button btn1;
btn1 = findViewById(R.id.btn1);
btn1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 0){
Uri uri = data.getData();
Intent i = new Intent(MainActivity.this,one.class);
i.putExtra("ayush",uri.toString());
startActivity(i);
////////////////
}
}
}
And here is my Second Activity where I want to Receive the Gif data and put it on the movie decode stream. Please Suggest me some ways. Please suggest me some ways to do it.
public void onDestroy() {
super.onDestroy();
}
#Override
public Engine onCreateEngine() {
// TODO Auto-generated method stub
try {
//Movie movie=Movie.decodeStream(getResources().getMovie(R.drawable.endless_staircase));
Movie movie = getResources().getMovie(Intent.getIntent(Uri.parse(//I want to use the get intent extra here )));
return new GIFWallpaperEngine(movie);
} catch (Exception e) {
// TODO: handle exception
Log.d("GIF", "Could Not load Asset");
return null;
}
}
private class GIFWallpaperEngine extends Engine {
private final int frameDuration = 20;
private SurfaceHolder holder;
private Movie movie;
private boolean visible;
private Handler handler;
int mWhen;
long mStart;
float mScaleX, mScaleY;
public GIFWallpaperEngine(Movie movie) {
this.movie = movie;
handler = new Handler();
mWhen = -1;
}
#Override
public void onCreate(SurfaceHolder surfaceHolder) {
// TODO Auto-generated method stub
super.onCreate(surfaceHolder);//tick();
this.holder = surfaceHolder;
}
private void draw() {
tick();
Canvas canvas = null;
try {
canvas = holder.lockCanvas();
canvas.save();
canvas.scale(mScaleX, mScaleY);
if (canvas != null) {
movie.draw(canvas, 0, 0);
}
canvas.restore();
// holder.unlockCanvasAndPost(canvas);
//movie.setTime(((int)(SystemClock.uptimeMillis()-SystemClock.uptimeMillis())%(movie.duration())));
//movie.setTime((int)((System.currentTimeMillis()%movie.duration())));
movie.setTime(mWhen);
} finally {
if (canvas != null)
holder.unlockCanvasAndPost(canvas);
}
handler.removeCallbacks(drawGIF);
if (visible) handler.postDelayed(drawGIF, 1000L / 25L);
}
void tick() {
int dur = movie.duration();
if (mWhen == -1L) {
mWhen = 0;
mStart = SystemClock.uptimeMillis();
} else {
long mDiff = SystemClock.uptimeMillis() - mStart;
mWhen = (int) (mDiff % dur);
}
}
#Override
public void onSurfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
// TODO Auto-generated method stub
super.onSurfaceChanged(holder, format, width, height);
mScaleX = width / (1f * movie.width());
mScaleY = height / (1f * movie.height());
draw();
}
private Runnable drawGIF = new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
draw();
}
};
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
handler.removeCallbacks(drawGIF);
}
public void onVisibilityChanged(boolean visible) {
// TODO Auto-generated method stub
//super.onVisibilityChanged(visible);
this.visible = visible;
if (visible) {
handler.post(drawGIF);
} else {
handler.removeCallbacks(drawGIF);
}
}
}
}
Please Suggest me Some Ways to do it.
Related
Im creating an app in android studio where I want 10 clips to be played at the same time side by side. Im having some problems with some lags already at three clips and I wounder if Im better off using threads? In that case how?
Any hint would be very much apreciated
Here is my code so far. I know it is not very efficient and I am better off using an array of a player object for example but Im just testing so far:
public class MainActivity extends AppCompatActivity implements TextureView.SurfaceTextureListener {
private MediaPlayer mp1, mp2, mp3;
private TextureView tv1, tv2, tv3;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv1 = findViewById(R.id.textureView1);
tv2 = findViewById(R.id.textureView2);
tv3 = findViewById(R.id.textureView3);
tv1.setSurfaceTextureListener(this);
tv2.setSurfaceTextureListener(this);
tv3.setSurfaceTextureListener(this);
}
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
Surface surface = new Surface(surfaceTexture);
mp1 = MediaPlayer.create(this, R.raw.a7);
mp1.setSurface(surface);
// mp1.prepareAsync(); //
mp1.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp1) {
mp1.start();
}
});
Surface surface2 = new Surface(surfaceTexture);
mp2 = MediaPlayer.create(this, R.raw.a9);
mp2.setSurface(surface2);
// mp1.prepareAsync(); //
mp2.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp2) {
mp2.start();
}
});
Surface surface3 = new Surface(surfaceTexture);
mp3 = MediaPlayer.create(this, R.raw.a10);
mp3.setSurface(surface3);
// mp1.prepareAsync(); //
mp3.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp3) {
mp3.start();
}
});
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
return false;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
#Override
protected void onPause() {
if (mp1 != null && mp1.isPlaying()) {
mp1.pause();
}
super.onPause();
}
#Override
protected void onResume() {
if (mp1 != null) {
mp1.start();
}
super.onResume();
}
#Override
protected void onDestroy() {
if (mp1 != null) {
mp1.stop();
mp1.release();
mp1 = null;
}
super.onDestroy();
}
}
You should play media in a different non-ui thread. like this:-
public class MediaService extends Service {
private MediaPlayer mp1, mp2, mp3;
private static final String ACTION_START = TAG + ".ACTION_START";
private IBinder mBinder = new MyBinder();
private MediaPlayer.OnPreparedListener mMediaPrepared = new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
Log.d(TAG, "MediaPlayer.onPrepared");
onCommandPlay(mp);
}
};
#Override
public IBinder onBind(Intent intent) {
Log.v(TAG, "onBind");
return mBinder;
}
#Override
public void onCreate() {
super.onCreate();
m1 = MediaPlayer.create(this, R.raw.a1);
m2 = MediaPlayer.create(this, R.raw.a2);
m3 = MediaPlayer.create(this, R.raw.a9);
}
#Override
public void onDestroy() {
super.onDestroy();
if (m1 != null) m1 .release();
if (m2 != null) m2 .release();
if (m3 != null) m3 .release();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
final String action = intent.getAction();
Log.d(TAG, "onStartCommand: " + intent.getAction());
if (ACTION_START.equals(action)) {
onCommandStart();
return START_STICKY;
}
stopSelf();
return Service.START_STICKY_COMPATIBILITY;
}
/**
* Performs actions related to media player when Service onStartCommand method is called
*
*/
private void onCommandStart() {
// Create Notifications with remote views
mNotification = new NotificationCompat.Builder(this).setTicker("Media Service started...")
.setSmallIcon(R.mipmap.ic_launcher)
.setContent(collapsed)
.setAutoCancel(false)
.setOngoing(true)
.build();
startForeground(NOTIFICATION_ID, mNotification);
startPlaying();
}
private void onCommandPlay(MediaPlayer mp) {
try {
mp.start();
} catch (IllegalStateException e) {
Log.e(TAG, "onCommandPlay", e);
}
}
/**
* Start playing the provided media item
*
*/
private void startPlaying() {
mCurrent = item;
try {
mp1.reset();
mp1.setOnPreparedListener(mMediaPrepared);
mp2.reset();
mp2.setOnPreparedListener(mMediaPrepared);
mp3.reset();
mp3.setOnPreparedListener(mMediaPrepared);
AssetFileDescriptor afd1 = getResources().openRawResourceFd(getResources().openRawResourceFd(R.raw.a9););
AssetFileDescriptor afd2 = getResources().openRawResourceFd(getResources().openRawResourceFd(R.raw.a10););
AssetFileDescriptor afd3 = getResources().openRawResourceFd(getResources().openRawResourceFd(R.raw.a8););
mp1.setDataSource(afd1 .getFileDescriptor(), afd1 .getStartOffset(), afd1.getLength());
mp2.setDataSource(afd2 .getFileDescriptor(), afd2 .getStartOffset(), afd2 .getLength());
mp3.setDataSource(afd3 .getFileDescriptor(), afd3 .getStartOffset(), afd3 .getLength());
mp1.prepareAsync();
mp2.prepareAsync();
mp3.prepareAsync();
} catch (IOException e) {
Log.e(TAG, "startPlaying", e);
}
}
public class MyBinder extends Binder {
public MediaService getService() {
return MediaService.this;
}
}
}
then start the service from Activity like this:
Intent intent = new Intent(context, MediaService.class);
intent.setAction(ACTION_START);
startServie(intent);
You should also handle different media playing use-cases. You can refer this link for more.
I'm trying to cancle my AsyncTask when I click Back Button by using this code :
#Override
public void onBackPressed() {
super.onBackPressed();
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
if(playerTask!=null && !playerTask.isCancelled()) playerTask.cancel(true);
this.finish();
}
But doesn't work playerTask still works :
PlayerTask playerTask = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pop_for_ringtone);
mediaPlayer = new MediaPlayer();
playerTask = new PlayerTask();
playerTask.execute(url);
/***/
#SuppressLint("StaticFieldLeak")
public class PlayerTask extends AsyncTask<String, Void, Boolean> {
ProgressBar pb = findViewById(R.id.progress);
#Override
protected void onPreExecute() {
super.onPreExecute();
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
AudioAttributes attribs = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build();
mediaPlayer.setAudioAttributes(attribs);
} else {
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
}
}
#Override
protected Boolean doInBackground(String... strings) {
if(!isCancelled()) {
try {
mediaPlayer.setDataSource(strings[0]);
mediaPlayer.prepare();
prepared = true;
} catch (IOException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
}
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.start();
}
});
}
else
{
playerTask.cancel(true);
}
return prepared;
}
#Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
music.setEnabled(true);
music.setVisibility(View.VISIBLE);
music.setChecked(true);
}
}
Try this
#Override
public void onBackPressed() {
// if playerTask == null mediaPlayer is never start, no need to handle
if(playerTask != null && playerTask.getStatus() == AsyncTask.Status.FINISHED) {
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
} else if (playerTask != null && playerTask.getStatus() != AsyncTask.Status.FINISHED) {
// It mean your task is running, should stop your mediaPlayer inside your task
playerTask.cancel(true);
}
super.onBackPressed();
}
And in your PlayerTask override onCancelled method
#Override
protected void onCancelled(Boolean aBoolean) {
if(isCancelled() && mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
}
Hope it help
You have 2 problem to change .
1.When you call super.onBackPressed(); before you canceled the playerTask ,your activity will destroy firstly .So you should call after playerTask canceled .
2.When you judged that the playTask is running , you also need to use playerTask.getStatus() == AsyncTask.Status.RUNNING .
Change
#Override
public void onBackPressed() {
super.onBackPressed();
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
if(playerTask!=null && !playerTask.isCancelled()) playerTask.cancel(true);
this.finish();
}
to
#Override
public void onBackPressed() {
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
if(playerTask!=null && !playerTask.isCancelled() && playerTask.getStatus() == AsyncTask.Status.RUNNING){
playerTask.cancel(true);
playerTask = null;
}
super.onBackPressed();
this.finish();
}
Referring to the docs for AsyncTask.cancel(boolean), AsyncTask cancel(boolean), we see that this method only sets the isCancelled() to give true and results in onCancelled() function to execute instead of onPostExecute(). So if you need to cancel the AsyncTask properly you need to add a flag to periodically check if(!isCancelled()) in doInBackground() and stop execution. Your code would look something like this
#Override
protected Boolean doInBackground(String... strings) {
if(!isCancelled()){
//ToDo:whatever you need to do in the asynctask
}
else{
//ToDo: cancel the execution
}
}
}
MediaPlayer mediaPlayer = new MediaPlayer();
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
AudioAttributes attribs = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build();
mediaPlayer.setAudioAttributes(attribs);
} else {
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
}
mediaPlayer.setDataSource(url);
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.start();
music.setEnabled(true);
music.setVisibility(View.VISIBLE);
music.setChecked(true);
}
});
And then onBackPressed() you can do mediaPlayer.release()
I have created the wave while media play with following code,
and stop the player while clicking on the back button or stop button.
Copy in xml file.
<VisualizerView
android:id="#+id/waveform_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"/>
MainActivity.java
private MediaPlayer myMediaPlayer;
private VisualizerView mWaveformView;
Visualizer audioOutput = null;
onCreate()
{
mWaveformView = (VisualizerView) findViewById(R.id.waveform_view);
myButtonPlayLastRecordAudio.setOnClickListener(this);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.buttonPlay:
myAudioSavePathInDevice = Environment.getExternalStorageDirectory().toString() + "/" +
"AudioRecording.3gp";
myMediaPlayer = new MediaPlayer();
myMediaPlayer.setVolume(1.5f, 1.5f);
if (myAudioSavePathInDevice == null || myAudioSavePathInDevice.isEmpty()) {
Toast.makeText(MainActivity.this, "No Audio Found", Toast.LENGTH_LONG).show();
} else {
try {
FileInputStream is = new FileInputStream(myAudioSavePathInDevice);
myMediaPlayer.setDataSource(is.getFD());
myMediaPlayer.prepare();
myMediaPlayer.start();
Toast.makeText(AudioRecordingActivity.this, "Recording Playing", Toast.LENGTH_LONG).show();
mWaveformView.clear();
createVisualizer();
} catch (IOException e) {
e.printStackTrace();
}
myMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
audioOutput.setEnabled(false);
}
});
}
break;
case R.id.buttonStopAudio:
mediaPlayerReleaseResources();
break;
}
}
private void createVisualizer() {
int rate = Visualizer.getMaxCaptureRate();
audioOutput = new Visualizer(myMediaPlayer.getAudioSessionId()); // get output audio stream
audioOutput.setDataCaptureListener(new Visualizer.OnDataCaptureListener() {
#Override
public void onWaveFormDataCapture(Visualizer visualizer, byte[] waveform, int samplingRate) {
int max = 0, min = 255;
for (int i = 0; i < waveform.length; i++) {
int w = (int) waveform[i] & 0xFF;
max = Math.max(w, max);
min = Math.min(w, min);
}
mWaveformView.addAmplitude((max - min)); // update the VisualizeView
mWaveformView.invalidate(); // refresh the VisualizerView
}
#Override
public void onFftDataCapture(Visualizer visualizer, byte[] fft, int samplingRate) {
}
}, rate, true, false); // waveform not freq data
audioOutput.setEnabled(true);
}
private void mediaPlayerReleaseResources() {
if(myMediaPlayer != null) {
if (myMediaPlayer.isPlaying()) {
myMediaPlayer.stop();
}
}
if( audioOutput != null)
audioOutput.setEnabled(false);
}
#Override
public void onBackPressed() {
super.onBackPressed();
mediaPlayerReleaseResources();
}
VisualizerView.class
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
public class VisualizerView extends View {
private static final int LINE_WIDTH = 3; // width of visualizer lines
private static final int LINE_SCALE = 4; // scales visualizer lines
private List<Float> amplitudes; // amplitudes for line lengths
private int width; // width of this View
private int height; // height of this View
private Paint linePaint; // specifies line drawing characteristics
private float temp_scale = 3;
float heighest = temp_scale;
// constructor
public VisualizerView(Context context, AttributeSet attrs) {
super(context, attrs); // call superclass constructor
linePaint = new Paint(); // create Paint for lines
linePaint.setColor(Color.BLACK); // set color to green
linePaint.setStrokeWidth(LINE_WIDTH); // set stroke width
}
// called when the dimensions of the View change
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
width = w; // new width of this View
height = h; // new height of this View
amplitudes = new ArrayList<Float>(width / LINE_WIDTH);
}
// clear all amplitudes to prepare for a new visualization
public void clear() {
heighest = 3;
amplitudes.clear();
}
// add the given amplitude to the amplitudes ArrayList
public void addAmplitude(float amplitude) {
amplitudes.add(amplitude); // add newest to the amplitudes ArrayList
// if the power lines completely fill the VisualizerView
if (amplitudes.size() * LINE_WIDTH >= width) {
amplitudes.remove(0); // remove oldest power value
}
}
// draw the visualizer with scaled lines representing the amplitudes
#Override
public void onDraw(Canvas canvas) {
int middle = height / 2; // get the middle of the View
float curX = 0; // start curX at zero
// for each item in the amplitudes ArrayList
for (float power : amplitudes) {
heighest = Math.max(power, heighest);
temp_scale = heighest / height;
float scaledHeight = power / temp_scale; // LINE_SCALE; // scale the power
curX += (LINE_WIDTH); // increase X by LINE_WIDTH
// draw a line representing this item in the amplitudes ArrayList
canvas.drawLine(curX, middle + scaledHeight / 2, curX, middle
- scaledHeight / 2, linePaint);
}
}
}
i have problem to build screen recording function when we are on video calling. i mean i want to start record screen and video calling at the same time. try to combine source code between this https://www.simplifiedcoding.net/video-call-android-tutorial/ and this http://www.truiton.com/2015/05/capture-record-android-screen-using-mediaprojection-apis/ but app suddenly crash when start record screen while on video call.
the code shown below
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode != REQUEST_CODE) {
Log.e(TAG, "Unknown request code: " + requestCode);
return;
}
if (resultCode != RESULT_OK) {
Toast.makeText(this,
"Screen Cast Permission Denied", Toast.LENGTH_SHORT).show();
mToggleButton.setChecked(false);
return;
}
mMediaProjectionCallback = new MediaProjectionCallback();
mMediaProjection = mProjectionManager.getMediaProjection(resultCode, data);
mMediaProjection.registerCallback(mMediaProjectionCallback, null);
mVirtualDisplay = createVirtualDisplay();
mMediaRecorder.start();
}
and this is the logcat
11-14 16:51:55.265 13200-13200/com.example.prasetyo.videocallapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.prasetyo.videocallapp, PID: 13200
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1000, result=-1, data=Intent { (has extras) }} to activity {com.example.prasetyo.videocallapp/com.example.prasetyo.videocallapp.Activities.CallScreenActivity}: java.lang.IllegalStateException
at android.app.ActivityThread.deliverResults(ActivityThread.java:3574)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:3617)
at android.app.ActivityThread.access$1300(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1352)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Caused by: java.lang.IllegalStateException
at android.media.MediaRecorder.start(Native Method)
at com.example.prasetyo.videocallapp.Activities.CallScreenActivity.onActivityResult(CallScreenActivity.java:214)
at android.app.Activity.dispatchActivityResult(Activity.java:6192)
at android.app.ActivityThread.deliverResults(ActivityThread.java:3570)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:3617)
at android.app.ActivityThread.access$1300(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1352)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
and last, this is the full java class
public class CallScreenActivity extends BaseActivity {
static final String TAG = CallScreenActivity.class.getSimpleName();
static final String CALL_START_TIME = "callStartTime";
static final String ADDED_LISTENER = "addedListener";
private AudioPlayer mAudioPlayer;
private Timer mTimer;
private UpdateCallDurationTask mDurationTask;
private String mCallId;
private long mCallStart = 0;
private boolean mAddedListener = false;
private boolean mVideoViewsAdded = false;
private TextView mCallDuration;
private TextView mCallState;
private TextView mCallerName;
private static final int REQUEST_CODE = 1000;
private int mScreenDensity;
private MediaProjectionManager mProjectionManager;
private static final int DISPLAY_WIDTH = 720;
private static final int DISPLAY_HEIGHT = 1280;
private MediaProjection mMediaProjection;
private VirtualDisplay mVirtualDisplay;
private MediaProjectionCallback mMediaProjectionCallback;
private ToggleButton mToggleButton;
private MediaRecorder mMediaRecorder;
private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
private static final int REQUEST_PERMISSIONS = 10;
static {
ORIENTATIONS.append(Surface.ROTATION_0, 90);
ORIENTATIONS.append(Surface.ROTATION_90, 0);
ORIENTATIONS.append(Surface.ROTATION_180, 270);
ORIENTATIONS.append(Surface.ROTATION_270, 180);
}
private class UpdateCallDurationTask extends TimerTask {
#Override
public void run() {
CallScreenActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
updateCallDuration();
}
});
}
}
#Override
protected void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putLong(CALL_START_TIME, mCallStart);
savedInstanceState.putBoolean(ADDED_LISTENER, mAddedListener);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
mCallStart = savedInstanceState.getLong(CALL_START_TIME);
mAddedListener = savedInstanceState.getBoolean(ADDED_LISTENER);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_call_screen);
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
mScreenDensity = metrics.densityDpi;
mMediaRecorder = new MediaRecorder();
mProjectionManager = (MediaProjectionManager) getSystemService
(Context.MEDIA_PROJECTION_SERVICE);
mAudioPlayer = new AudioPlayer(this);
mCallDuration = (TextView) findViewById(R.id.callDuration);
mCallerName = (TextView) findViewById(R.id.remoteUser);
mCallState = (TextView) findViewById(R.id.callState);
ImageButton endCallButton = (ImageButton) findViewById(R.id.hangupButton);
mToggleButton = (ToggleButton) findViewById(R.id.toggle);
mToggleButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (ContextCompat.checkSelfPermission(CallScreenActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE) + ContextCompat
.checkSelfPermission(CallScreenActivity.this,
Manifest.permission.RECORD_AUDIO)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale
(CallScreenActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) ||
ActivityCompat.shouldShowRequestPermissionRationale
(CallScreenActivity.this, Manifest.permission.RECORD_AUDIO)) {
mToggleButton.setChecked(false);
Snackbar.make(findViewById(android.R.id.content), R.string.label_permissions,
Snackbar.LENGTH_INDEFINITE).setAction("ENABLE",
new View.OnClickListener() {
#Override
public void onClick(View v) {
ActivityCompat.requestPermissions(CallScreenActivity.this,
new String[]{Manifest.permission
.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO},
REQUEST_PERMISSIONS);
}
}).show();
} else {
ActivityCompat.requestPermissions(CallScreenActivity.this,
new String[]{Manifest.permission
.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO},
REQUEST_PERMISSIONS);
}
} else {
onToggleScreenShare(v);
}
}
});
mCallId = getIntent().getStringExtra(SinchService.CALL_ID);
if (savedInstanceState == null) {
mCallStart = System.currentTimeMillis();
}
endCallButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
endCall();
mToggleButton.setChecked(false);
onToggleScreenShare(mToggleButton);
}
});
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode != REQUEST_CODE) {
Log.e(TAG, "Unknown request code: " + requestCode);
return;
}
if (resultCode != RESULT_OK) {
Toast.makeText(this,
"Screen Cast Permission Denied", Toast.LENGTH_SHORT).show();
mToggleButton.setChecked(false);
return;
}
mMediaProjectionCallback = new MediaProjectionCallback();
mMediaProjection = mProjectionManager.getMediaProjection(resultCode, data);
mMediaProjection.registerCallback(mMediaProjectionCallback, null);
mVirtualDisplay = createVirtualDisplay();
mMediaRecorder.start();
}
public void onToggleScreenShare(View view) {
if (((ToggleButton) view).isChecked()) {
initRecorder();
shareScreen();
} else {
mMediaRecorder.stop();
mMediaRecorder.reset();
Log.v(TAG, "Stopping Recording");
stopScreenSharing();
}
}
private void shareScreen() {
if (mMediaProjection == null) {
startActivityForResult(mProjectionManager.createScreenCaptureIntent(), REQUEST_CODE);
return;
}
mVirtualDisplay = createVirtualDisplay();
mMediaRecorder.start();
}
private VirtualDisplay createVirtualDisplay() {
return mMediaProjection.createVirtualDisplay("CallScreenActivity",
DISPLAY_WIDTH, DISPLAY_HEIGHT, mScreenDensity,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
mMediaRecorder.getSurface(), null /*Callbacks*/, null
/*Handler*/);
}
private void initRecorder() {
try {
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mMediaRecorder.setOutputFile(Environment
.getExternalStorageDirectory().getAbsolutePath() + "/video.mp4");
mMediaRecorder.setVideoSize(DISPLAY_WIDTH, DISPLAY_HEIGHT);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mMediaRecorder.setVideoEncodingBitRate(512 * 1000);
mMediaRecorder.setVideoFrameRate(30);
int rotation = getWindowManager().getDefaultDisplay().getRotation();
int orientation = ORIENTATIONS.get(rotation + 90);
mMediaRecorder.setOrientationHint(orientation);
mMediaRecorder.prepare();
} catch (IOException e) {
e.printStackTrace();
}
}
private class MediaProjectionCallback extends MediaProjection.Callback {
#Override
public void onStop() {
if (mToggleButton.isChecked()) {
mToggleButton.setChecked(false);
mMediaRecorder.stop();
mMediaRecorder.reset();
Log.v(TAG, "Recording Stopped");
}
mMediaProjection = null;
stopScreenSharing();
}
}
private void stopScreenSharing() {
if (mVirtualDisplay == null) {
return;
}
mVirtualDisplay.release();
//mMediaRecorder.release(); //If used: mMediaRecorder object cannot
// be reused again
destroyMediaProjection();
}
#Override
public void onDestroy() {
super.onDestroy();
destroyMediaProjection();
}
private void destroyMediaProjection() {
if (mMediaProjection != null) {
mMediaProjection.unregisterCallback(mMediaProjectionCallback);
mMediaProjection.stop();
mMediaProjection = null;
}
Log.i(TAG, "MediaProjection Stopped");
}
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String permissions[],
#NonNull int[] grantResults) {
switch (requestCode) {
case REQUEST_PERMISSIONS: {
if ((grantResults.length > 0) && (grantResults[0] +
grantResults[1]) == PackageManager.PERMISSION_GRANTED) {
onToggleScreenShare(mToggleButton);
} else {
mToggleButton.setChecked(false);
Snackbar.make(findViewById(android.R.id.content), R.string.label_permissions,
Snackbar.LENGTH_INDEFINITE).setAction("ENABLE",
new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setData(Uri.parse("package:" + getPackageName()));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
startActivity(intent);
}
}).show();
}
return;
}
}
}
#Override
public void onServiceConnected() {
Call call = getSinchServiceInterface().getCall(mCallId);
if (call != null) {
if (!mAddedListener) {
call.addCallListener(new SinchCallListener());
mAddedListener = true;
}
} else {
Log.e(TAG, "Started with invalid callId, aborting.");
finish();
}
updateUI();
}
//method to update video feeds in the UI
private void updateUI() {
if (getSinchServiceInterface() == null) {
return; // early
}
Call call = getSinchServiceInterface().getCall(mCallId);
if (call != null) {
mCallerName.setText(call.getRemoteUserId());
mCallState.setText(call.getState().toString());
if (call.getState() == CallState.ESTABLISHED) {
//when the call is established, addVideoViews configures the video to be shown
addVideoViews();
}
}
}
//stop the timer when call is ended
#Override
public void onStop() {
super.onStop();
mDurationTask.cancel();
mTimer.cancel();
removeVideoViews();
}
//start the timer for the call duration here
#Override
public void onStart() {
super.onStart();
mTimer = new Timer();
mDurationTask = new UpdateCallDurationTask();
mTimer.schedule(mDurationTask, 0, 500);
updateUI();
}
#Override
public void onBackPressed() {
// User should exit activity by ending call, not by going back.
}
//method to end the call
private void endCall() {
mAudioPlayer.stopProgressTone();
Call call = getSinchServiceInterface().getCall(mCallId);
if (call != null) {
call.hangup();
}
finish();
}
private String formatTimespan(long timespan) {
long totalSeconds = timespan / 1000;
long minutes = totalSeconds / 60;
long seconds = totalSeconds % 60;
return String.format(Locale.US, "%02d:%02d", minutes, seconds);
}
//method to update live duration of the call
private void updateCallDuration() {
if (mCallStart > 0) {
mCallDuration.setText(formatTimespan(System.currentTimeMillis() - mCallStart));
}
}
//method which sets up the video feeds from the server to the UI of the activity
private void addVideoViews() {
if (mVideoViewsAdded || getSinchServiceInterface() == null) {
return; //early
}
final VideoController vc = getSinchServiceInterface().getVideoController();
if (vc != null) {
RelativeLayout localView = (RelativeLayout) findViewById(R.id.localVideo);
localView.addView(vc.getLocalView());
localView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//this toggles the front camera to rear camera and vice versa
vc.toggleCaptureDevicePosition();
}
});
LinearLayout view = (LinearLayout) findViewById(R.id.remoteVideo);
view.addView(vc.getRemoteView());
mVideoViewsAdded = true;
}
}
//removes video feeds from the app once the call is terminated
private void removeVideoViews() {
if (getSinchServiceInterface() == null) {
return; // early
}
VideoController vc = getSinchServiceInterface().getVideoController();
if (vc != null) {
LinearLayout view = (LinearLayout) findViewById(R.id.remoteVideo);
view.removeView(vc.getRemoteView());
RelativeLayout localView = (RelativeLayout) findViewById(R.id.localVideo);
localView.removeView(vc.getLocalView());
mVideoViewsAdded = false;
}
}
private class SinchCallListener implements VideoCallListener {
#Override
public void onCallEnded(Call call) {
CallEndCause cause = call.getDetails().getEndCause();
Log.d(TAG, "Call ended. Reason: " + cause.toString());
mAudioPlayer.stopProgressTone();
setVolumeControlStream(AudioManager.USE_DEFAULT_STREAM_TYPE);
String endMsg = "Call ended: " + call.getDetails().toString();
Toast.makeText(CallScreenActivity.this, endMsg, Toast.LENGTH_LONG).show();
endCall();
mToggleButton.setChecked(false);
onToggleScreenShare(mToggleButton);
}
#Override
public void onCallEstablished(Call call) {
Log.d(TAG, "Call established");
mAudioPlayer.stopProgressTone();
mCallState.setText(call.getState().toString());
setVolumeControlStream(AudioManager.STREAM_VOICE_CALL);
AudioController audioController = getSinchServiceInterface().getAudioController();
audioController.enableSpeaker();
mCallStart = System.currentTimeMillis();
Log.d(TAG, "Call offered video: " + call.getDetails().isVideoOffered());
}
#Override
public void onCallProgressing(Call call) {
Log.d(TAG, "Call progressing");
mAudioPlayer.playProgressTone();
}
#Override
public void onShouldSendPushNotification(Call call, List pushPairs) {
// Send a push through your push provider here, e.g. GCM
}
#Override
public void onVideoTrackAdded(Call call) {
Log.d(TAG, "Video track added");
addVideoViews();
}
}
}
hope someone can help me, thanksa lot!
I was facing the same issue.
java.lang.IllegalStateException is due to that you are accessing the main thread view from another thread, // Play dial tones mDialTone.start();, which is giving the exception. Just call initRecorder() on main thread. It will resolve your problem.
I have a thread named runner. I want to stop this thread onBackPressed but this is not happening. Here is the code:
public class StrobeLightConfig extends Activity {
Camera cam;
StrobeRunner runner;
Thread bw;
CheckBox strobe;
private boolean isFlashOn;
private boolean hasFlash;
private Parameters params;
private MediaPlayer mp;
VerticalSeekBar skbar, skbaroff;
ToggleButton togglebutton;
public final Handler mHandler = new Handler();
public final Runnable mShowToastRunnable = new Runnable() {
public void run() {
showMessage();
}
};
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
skbar = (VerticalSeekBar) findViewById(R.id.SeekBar01);
strobe = (CheckBox) findViewById(R.id.checkBox1);
togglebutton = (ToggleButton) findViewById(R.id.ToggleButton01);
skbaroff = (VerticalSeekBar) findViewById(R.id.SeekBar02);
hasFlash = getApplicationContext().getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
turnOnFlash();
strobe.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
if (buttonView.isChecked()) {
cam.release();
Toast.makeText(getApplicationContext(), "Released 1", 0)
.show();
} else {
cam.release();
Toast.makeText(getApplicationContext(), "Released 2", 0)
.show();
}
}
});
runner = StrobeRunner.getInstance();
runner.controller = this;
if (runner.isRunning) {
} else {
try {
if (cam == null) {
cam = Camera.open();
}
} catch (RuntimeException ex) {
togglebutton.setEnabled(false);
TextView t = (TextView) findViewById(R.id.TextViewHW2);
t.setText(R.string.nocamera);
Toast.makeText(getApplicationContext(),
"Error connecting to camera flash.", Toast.LENGTH_LONG)
.show();
return;
}
}
togglebutton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// Perform action on clicks
if (strobe.isChecked()) {
if (togglebutton.isChecked()) {
turnOnStrobe();
} else {
turnOffStrobe();
}
} else {
if (isFlashOn) {
// turn off flash
turnOffFlash();
} else {
----------------- runner.requeststop working here---------------------
turnOnFlash();
}
}
}
});
skbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
runner.delay = progress;
}
});
skbaroff.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
runner.delayoff = progress;
}
});
}
private void getCamera() {
if (cam == null) {
try {
cam = Camera.open();
params = cam.getParameters();
} catch (RuntimeException e) {
Log.e("Camera Error. Failed to Open. Error: ", e.getMessage());
}
}
}
/*
* Turning On flash
*/
private void turnOnFlash() {
if (!isFlashOn) {
togglebutton.setChecked(true);
cam = Camera.open();
params = cam.getParameters();
params.setFlashMode(Parameters.FLASH_MODE_TORCH);
cam.setParameters(params);
cam.startPreview();
isFlashOn = true;
strobe.setEnabled(false);
}
}
private void turnOffFlash() {
if (isFlashOn) {
togglebutton.setChecked(false);
params = cam.getParameters();
params.setFlashMode(Parameters.FLASH_MODE_OFF);
cam.setParameters(params);
cam.stopPreview();
cam.release();
isFlashOn = false;
strobe.setEnabled(true);
}
}
private void turnOnStrobe() {
if (!isFlashOn) {
strobe.setEnabled(false);
bw = new Thread(runner);
bw.start();
}
}
private void turnOffStrobe() {
if (isFlashOn) {
runner.requestStop = true;
strobe.setEnabled(true);
}
}
#Override
protected void onDestroy() {
super.onDestroy();
}
#Override
protected void onPause() {
super.onPause();
}
#Override
protected void onRestart() {
super.onRestart();
}
public void showMessage() {
String err = runner.errorMessage;
runner.errorMessage = "";
if (!err.equals("")) {
Context context = getApplicationContext();
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, err, duration);
toast.show();
}
ToggleButton togglebutton = (ToggleButton) findViewById(R.id.ToggleButton01);
togglebutton.setChecked(false);
}
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
super.onBackPressed();
if (strobe.isChecked()) {
turnOffStrobe();
} else {
if (isFlashOn) {
----------------- runner.requeststop needs to work here---------------------
turnOffFlash();
finish();
moveTaskToBack(true);
}
}
}
}
However if I write
runner.requestStop = true;
strobe.setEnabled(true);
at the place of TurnoffStrobe in the oncreate (not onBackPressed), its working. What can I do to have runner.requeststop working outside onCreate.?
Try
your_thread.isInterrupted(); inside onBackpress()
i created audio activity with seekbar, it was played but i have problem when seekbar in progress there is cutting each 1 second in sound because i used (Thread.sleep).
i check another solution in Internet, all codes i checked were use same concept.
this is my code
public class PlaySounds extends Activity implements Runnable {
SeekBar seeksounds;
MediaPlayer mp;
Handler handler = new Handler();
int id;
public boolean isFileExists(String fileName) {
try {
File myFile = new File(fileName);
FileInputStream fIn = new FileInputStream(myFile);
BufferedReader myReader = new BufferedReader(new InputStreamReader(fIn));
return true;
} catch (Exception e) {
return false;
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.playsounds);
seeksounds = (SeekBar) findViewById(R.id.seeksounds);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
String path = Environment.getExternalStorageDirectory().toString() + "/dowload/splash.mp3";
if (isFileExists(path)) {
mp = new MediaPlayer();
try {
mp.setDataSource(path);
mp.prepare();
mp.start();
int maxD = mp.getDuration();
int currentD = mp.getCurrentPosition();
seeksounds.setMax(maxD);
seeksounds.setProgress(currentD);
new Thread(this).start();
seeksounds.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar arg0, int progress,
boolean arg2) {
mp.seekTo(progress);
seeksounds.setProgress(progress);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
});
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
super.onBackPressed();
mp.release();
}
#Override
public void run() {
int currentPosition= 0;
int total = mp.getDuration();
while (mp!=null && currentPosition<total) {
try {
Thread.sleep(1000);
currentPosition= mp.getCurrentPosition();
seeksounds.setProgress(currentPosition);
} catch (Exception e) {
return;
}
}
}
}
Try to add mp = null; here
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
super.onBackPressed();
mp.release();
mp = null;
}