Still trying to make my screen record app. I keep on working with MediaRecorder, as I was told some time ago, so I got stuck with another problem.
I just need to initialize a MediaProjection object to make my code work, that's what I do in onActivityResult(), as it's written in this guide:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == RECORD_REQUEST_CODE && resultCode == RESULT_OK) {
mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, data);
screenRecorder.setMediaProject(mediaProjection);
}
}
The setMediaProjection() looks like
public void setMediaProject(MediaProjection project) {
mediaProjection = project;
}
, so it shouldnt't cause any trouble.
And that's how I try to call onActivityResult():
/* start transmission */
if(screenRecorder.isRunning()) {
screenRecorder.stopRecord();
} else {
Intent captureIntent = mediaProjectionManager.createScreenCaptureIntent();
startActivityForResult(captureIntent, RECORD_REQUEST_CODE);
}
The fun and crazy thing is that when I first launched the debug, it worked! After startActivityForResult() I got to onActivityResult() and initialized mediaProjection: my phone showed me a dialog window whether I allow to capture the screen or not, so I allowed that and got a special symbol (smth like screen with displayed waves) at my status bar.
But a few moments later I found an issue when stopping the record and restarted the debug session to trace it more exactly. After that onActivityResult() is just ignored: startActivityForResult() is called, the dialog window is shown, but after allowing the record onActivityResult() is completely skipped and mediaProjection is null. The restarting and re-installing the apk with the same code didn't fix anything.
Thank you very much for any suggestions.
Your onActivityResult only does something when the result code is OK, try this:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == RECORD_REQUEST_CODE && resultCode == RESULT_OK) {
mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, data);
screenRecorder.setMediaProject(mediaProjection);
} else {
//TODO: Do something
Toast.makeText(getBaseContext(), "Result code is not RESULT_OK, ", Toast.LENGTH_LONG).show();
}
There was a very simple solution. I just initialized the record service that put null into mediaRecorder's mediaProjection, so after that I was unable to re-initialize it. Putting intent which called onActivivtyResult() into activity's onCreate() before starting the service fixed that.
I got same problem. This could bu about threading. In my project I started an activity and opening activity try to start chrome intent. Chrome is opening in debug mode but not opened real mode.
I added a delay when opening chrome
final Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
#Override
public void run() {
startAuth();
}
}, 100);
Related
I created an activity, which takes a photo using the default camera app. I used the code from this tutorial: https://developer.android.com/training/camera/photobasics#TaskPath
I create the intent like this:
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
And then I set the path of the output:
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, currentPhotoPath);
In the tutorial, they save currentPhotoPath to a private variable in the activity. I would like to avoid that, and get the path from the intent in the onActivityResult function, here:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
if (requestCode == REQUEST_TAKE_PHOTO && resultCode == RESULT_OK) {
// How to access the path here?
}
}
I tried intent.getStringExtra(MediaStore.EXTRA_OUTPUT), but it returns null.
I would like to avoid storing the path in a class member, because the activity might be destroyed and recreated by the android system, and then that variable will be null.
I was able to find a similar question, but the answers are for Android 2, and they use deprecated apis, like managedQuery.
I would like to avoid that, and get the path from the intent in the onActivityResult function, here
That is not possible, sorry. It would require rewriting every camera app.
I would like to avoid storing the path in a class member, because the activity might be destroyed and recreated by the android system, and then that variable will be null.
Save it in the saved instance state Bundle. This sample app is a bit old, but it demonstrates the basic technique. Save the File in onSaveInstanceState():
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable(EXTRA_FILENAME, output);
}
...and get it back in onCreate(), if the passed-in savedInstanceState Bundle is not null:
output=(File)savedInstanceState.getSerializable(EXTRA_FILENAME);
I have a search button in MainActivity which launches SearchActivity. In SearchActivity, the user can either choose from one of the predefined categories listed, or can enter in a search query. The SearchActivity will return a different extra depending on which way the user searches. The code that runs in MainActivity will depend on which extra is returned.
I'm debating which way is better or more "correct". I've coded it both ways, and it works either way.
The first way I coded it was to check for the existence of the intent extra:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == GET_SEARCH_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
if (data.getExtras().containsKey("extra1")) {
extra1 = data.getStringExtra("extra1");
}
if (data.getExtras().containsKey("extra2")) {
extra2 = data.getStringExtra("extra2");
}
}
// plus rest of code for checking for RESULT_CANCELED
}
}
The other way I coded it is by using custom result codes. The result codes RESULT_OK_CATEGORY and RESULT_OK_SEARCH are public static variables in MainActivity so that they can be accessed from SearchActivity, and sent back as a result code through setResult(MainActivity.RESULT_OK_CATEGORY, intent) or setResult(MainActivity.RESULT_OK_SEARCH, intent) respectively.
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == GET_SEARCH_REQUEST_CODE) {
if (resultCode == RESULT_OK_CATEGORY) {
extra1 = data.getStringExtra("extra1");
} else if (resultCode == RESULT_OK_SEARCH) {
extra2 = data.getStringExtra("extra2");
}
// plus rest of code for checking for RESULT_CANCELED
}
}
Which way is better, and why? Checking for the existence of the extra, or checking for a custom result code?
You should use resultCode because it's completely under your control. You may lose values set in Intent's extras, as revealed in this question (referenced by Ajay in the comments).
Note, if you use many custom result codes, it has been recommended to use a switch statement for code clarity.
I am trying to setResult on my "Register" Button, but nothing happens:
SignInActivity:
Start activity for result:
Intent intent = RegisterActivity_.intent(this).get();
this.startActivityForResult(intent, REQUEST_CODE_USER_REGISTER);
On Activity Result
#OnActivityResult(REQUEST_CODE_USER_REGISTER)
protected void onResult(int resultCode) {
if (resultCode == RESULT_OK)
DashboardActivity_.intent(this).start();
else if (resultCode == RESULT_CANCELED) {
this.showDialogAlert("Unexpected error", null);
}
RegisterActivity:
this.setResult(RESULT_OK);
I am using AndroidAnnotations and I'm not using the this.finish() method because it set the property android:noHistory="true" in all Activities on AndroidManifest.xml. I am also setting the parent of each activity there. Have tried to remove these settings and setResult continued without work. Has anyone experienced this?
I am using AndroidAnnotations and I'm not using the this.finish() method because it set the property android:noHistory="true"in all Activities on AndroidManifest.xml.
I think your issue is here. When you're using startActivityForRestult, the expected workflow is to launch a new activity, do some work and then close this activity to go back to the previous one with the result of the work. So, you can't use android:noHistory="true" here because it doesn't make any sense.
Also, if you look at Activity's source code, you'll see that result is propagated from the finish method.
Start Activity for Result. your code is Ok
Intent intent = RegisterActivity_.intent(this).get();
this.startActivityForResult(intent, REQUEST_CODE_USER_REGISTER);
Now Inside the Activity that you start for the result set the result status like below code.
setResult(resultCode); result status possible values are like RESULT_CANCELED,RESULT_OK.etc
Activity that starts the new activity for result must override the below method and this method work when the activity that started for result finish.
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
}
I think the method is..
onActivityResult(int requestCode, int resultCode, Intent data)
not onResult
Currently we open Achievements View with
startActivityForResult(mHelper.getGamesClient().getAchievementsIntent(),
REQUEST_ACHIEVEMENTS);
Can we get some kind of callback when achievements view was closed? Or if it is possible - to get a callback when user Exits GPG within the achievements view. GameHelper's "onDisconnected()" is not firing for some reason - when that happens.
I've googled this - but found nothing
Edit: should i look for some specific responseCode inside onActivityResult
?
Declare this variable and this method in your class.
private static int achievementsIntent = 10001;
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == achievementsIntent) {
//you are in your callback
if (resultCode == GamesActivityResultCodes.RESULT_RECONNECT_REQUIRED) {
// user logged out from achievements screen
}
}
}
Then call your achievements intent:
startActivityForResult(Games.Achievements.getAchievementsIntent(GoogleApiClient), achievementsIntent);
Good day to everyone!
I need to stop method execution until another activity will end.
At the moment I'm trying to do it in this way:
private boolean isPausedWhileSplash;
public void showSplashWorldChangeAd(String oldWorldName, String newWorldName) {
overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
Intent intent = new Intent(this, SplashScreen.class);
intent.putExtra(SplashScreen.MSG_STRING_KEY, oldWorldName + " -> "
+ newWorldName);
intent.putExtra(SplashScreen.OLD_WORLD, oldWorldName);
intent.putExtra(SplashScreen.NEW_WORLD, newWorldName);
startActivityForResult(intent, RESULT_OK);
isPausedWhileSplash = true;
while (isPausedWhileSplash) {
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
isPausedWhileSplash = false;
}
But it's not working.
Can you help me?
Thanks!
UPD: Maybe there is any way to prevent view from drawing? Because all what I need right now is delay calling of methods, which will redraw view of this activity. Now I have the new world drawn before the splash screen, saying about the world change, is shown, which is not looking good.
I'm a little rushed for time so here's a generic answer:
public class MonitorObject{
}
public class MyWaitNotify{
MonitorObject myMonitorObject = new MonitorObject(); //To be used for synch
public void doWait(){
synchronized(myMonitorObject){
try{
myMonitorObject.wait(); // Wait until the notify method is called by another thread
} catch(InterruptedException e){...}
}
}
public void doNotify(){ //Notify waiting threads that they can continue
synchronized(myMonitorObject){
myMonitorObject.notify();
}
}
}
I'll come back and get you a working example this afternoon if you haven't got a solution by then...
This article should get you started
EDIT: This article demonstrates other approaches, all of which should be an improvement on your current solution. It talks you through how to update the UI from events in different threads and the benefits/costs of the various solutions.
I guess you are trying to do something like this:
public void showSplashWorldChangeAd(String oldWorldName, String newWorldName){
/* You have done some initialization work */
startActivityForResult(intent, RESULT_OK);
/* This is what you want to do after the activity returns */
afterActivityReturns();
}
Then why not proceed this way?
public void showSplashWorldChangeAd(String oldWorldName, String newWorldName){
/* You have done some initialization task here*/
startActivityForResult(intent, RESULT_OK);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
/* This is what you want to do after the activity finishes */
afterActivityReturns();
}
But if you really want to stop the showSplashWorldChangeAd method for some reason, you need lock and key (as Basic says).