I'm using ShotWatch to capture screenshots events.
The included example only works while inside the aplication, but I want to capture the event and launch an Activity. My code seems to ignore the service.
The mainfest has all the services/activity defined.
MainActivity:
public class MainActivity extends AppCompatActivity {
private ImageView imageView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.imageView = findViewById(R.id.imageView);
// run-time permissions
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) {
// You can directly ask for the permission.
// The registered ActivityResultCallback gets the result of this request.
Toast.makeText(this, ":(", Toast.LENGTH_LONG).show();
ActivityCompat.requestPermissions(MainActivity.this, new String[] {Manifest.permission.READ_EXTERNAL_STORAGE}, 0);
}
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
// You can use the API that requires the permission.
Toast.makeText(this, "OK", Toast.LENGTH_LONG).show();
startService(new Intent(MainActivity.this, ScreenshotCaptureService.class));
}
}
}
ScreenshotCaptureService:
public class ScreenshotCaptureService extends Service implements ShotWatch.Listener {
private ShotWatch shotWatch;
#Override
public void onCreate() {
super.onCreate();
this.shotWatch = new ShotWatch(getContentResolver(), this);
this.shotWatch.register();
}
#Override
public void onDestroy() {
super.onDestroy();
this.shotWatch.unregister();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return Service.START_STICKY;
}
#Override
public void onScreenShotTaken(ScreenshotData data) {
Intent intent = new Intent(this, AddActivity.class);
intent.putExtra(AddActivity.CAPTURE_PATH, data.getPath());
startService(intent);
}
}
AddActivity:
public class AddActivity extends AppCompatActivity {
public static final String CAPTURE_PATH = "ADD_CAPTURE_PATH";
private ImageButton imageButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add);
Uri captura = Uri.fromFile(new File(getIntent().getStringExtra(AddActivity.CAPTURE_PATH)));
this.imageButton = findViewById(R.id.imageButton);
this.imageButton.setImageURI(captura);
this.imageButton.setOnClickListener((View v)->{
// ...
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != RESULT_OK) return;
switch (requestCode) {
// ...
}
}
}
Fixed.
I was using 'startService' instead of 'startActivity' inside onScreenShotTaken, on ScreenshotCaptureService.
Related
I have a FragmentActivity that is starting another activity for result. When the called activity finishes, onActivityResult is not called. Does it make a difference that I am using a AppCompatActivity activity (which extends from FragmentActivity)? The documentation says that results will be returned to the calling fragment, and in this case it's not a fragment, it's an activity. Here is the code, very simple:
MainActivity:
public class SMSEmailActivityNew extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setup activity....
Intent i = new Intent(this, EulaActivity.class);
i.putExtra(Globals.keyFileName,Globals.FILE_EULA );
startActivityForResult(i,RESULT_OK);
}
//this method is never called
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//dowork .....
}
}
Called activity:
EulaActivity extends AppCompatActivity implements OnClickListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//set up activity ....
}
public void onClick(View v) {
Intent result = new Intent();
if (bPermissionGranted) {
setResult(Activity.RESULT_OK, result);
// Determine if EULA was accepted this time
getSharedPreferences().edit().putBoolean(Globals.KEY_EULA_ACCEPTED, true).apply();
} else {
setResult(Activity.RESULT_CANCELED, result);
}
finish();
}
}
According to documentation you need to pass requestId bigger or equal thant 0. In your case RESULT_OK is -1. Also RESULT_OK acts like result code, not like request code and startActivityForResult needs a request code.
Something like this startActivityForResult(intent, 0);
Also finish EulaActivity using finishActivity(yourPreviousRequestCode);, in this case 0.
Try this solution:-
MainActivity.java
//Define variable
public static int REQUEST_CODE = 233;
public class SMSEmailActivityNew extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setup activity....
Intent i = new Intent(this, EulaActivity.class);
i.putExtra(Globals.keyFileName,Globals.FILE_EULA );
startActivityForResult(i, REQUEST_CODE); //Change here
}
//this method is never called
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == REQUEST_CODE) {
if(resultCode == RESULT_OK) {
if(data != null && data.hasExtra("MESSAGE")) {
String resStr = data.getStringExtra("MESSAGE");
Toast.makeText(MainActivity.this, resStr, Toast.LENGTH_SHORT).show();
}
}else if(resultCode == RESULT_CANCELED)
Toast.makeText(MainActivity.this, "Canceled", Toast.LENGTH_SHORT).show();
}
}
}
EulaActivity.java
EulaActivity extends AppCompatActivity implements OnClickListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//set up activity ....
}
public void onClick(View v) {
Intent result = new Intent();
result.putExtra("MESSAGE","Eula Accepted Set");
if (bPermissionGranted) {
setResult(Activity.RESULT_OK, result);
// Determine if EULA was accepted this time
getSharedPreferences().edit().putBoolean(Globals.KEY_EULA_ACCEPTED, true).apply();
} else {
setResult(Activity.RESULT_CANCELED, result);
}
finish();
}
}
If anyone could explain me why I am getting this error, and how to rectify it.
This is the second activity
public class Result_activity extends Activity {
#Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.result_activity);
Bundle extras = getIntent().getExtras();
String inputString = extras.getString("yourkey");
TextView view = (TextView) findViewById(R.id.textView1);
view.setText(inputString);
}
#Override
public void finish() {
Intent intent = new Intent();
EditText editText= (EditText) findViewById(R.id.result_value);
String string = editText.getText().toString();
intent.putExtra("returnkey", string);
setResult(RESULT_OK, intent);
super.finish();
}
}
This is my main Activity
public class MainActivity extends ActionBarActivity {
// constant to determine which sub-activity returns
private static final int REQUEST_CODE = 10;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onClick(View view) {
EditText text = (EditText) findViewById(R.id.editText1);
String string = text.getText().toString();
Intent i = new Intent(this, Result_activity.class);
i.putExtra("yourkey", string);
startActivityForResult(i, REQUEST_CODE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK && requestCode == REQUEST_CODE) {
if (data.hasExtra("returnkey")) {
String result = data.getExtras().getString("returnkey");
if (result != null && result.length() > 0) {
Toast.makeText(this, result, Toast.LENGTH_SHORT).show();
}
}
}
}
}
Intent intent = new Intent();
does not specify any action or class.
In your main activity you specified an intent with a class which is the correct way :
Intent i = new Intent(this, Result_activity.class);
My application starts with InitActivity that checks for login status, calls LoginActivity accordingly before proceeding to some logic.
I know I can use the startAcivityForResult() and onActivityResult() to ensure LoginActivity completes before doing doSomeMainLogic(), but my if check throws a curve in it. If I do this:
public class InitActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!userIsLoggedIn) {
Intent intent = new Intent("com.example.myapp.LOGINACTIVITY");
startActivityForResult(intent,1);
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) {
if (resultCode == RESULT_OK) {
doSomeMainLogic();
}
}
}
}
how do I get doSomeMainLogic() to fire if the user is already logged in?
Thanks much.
public class InitActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!userIsLoggedIn) {
Intent intent = new Intent("com.example.myapp.LOGINACTIVITY");
startActivityForResult(intent,1);
}
else {
doSomeMainLogic(); // this part is added
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) {
if (resultCode == RESULT_OK) {
doSomeMainLogic();
}
}
}
}
I want to call an Activity A from a Service in Android(and pass some Strings to it). This activity A inturns calls another activity B with startActivityForResult(). Basically, I want my service to wait till the result from activity B is obtained. Please give me some idea of how this implementation can be done(and which flag to set in intent)?
Service:
Intent intent = new Intent(getBaseContext(),ActivityA.class);
intent.putExtra("code",script);
intent.putExtra("type", type);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
ActivityA:
Intent intent = new Intent(this,ActivityB.class);
intent.putExtra("code",code);
intent.putExtra("type", type);
startActivityForResult(intent,REQUEST_CODE);
First Create an interface
public interface MyActions {
public void doActions();
}
Now let your service class implement that interface
public class MyService extends Service implements MyActions{
and override the method
#Override
public void doActions() {
//Some code
}
Now your Activity A is calling B via the startActivityForResult method so override the onActivityResult of A
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//Some code
}
In this A class now create a static instance of the interface
static MyActions mActions;
and now write a static method like this
public static void setMyListener(MyActions act){
mActions = act;
}
Now in the onActivityResult that you overrided for class A add this line of code
mActions.doActions();
so you get
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
mActions.doActions();
}
Now in your Service class in the onStart() method write this line before calling the activity
ActA.setMyListener(this);
Thats it done now when from Activity B the call goes to onActivityResult of A and from A the Serivce can listen to the overrided method of doActions()
Write all your code in doActions() method of service that you wanted to do
Here is the code
1st Activity : ActA.java
public class ActA extends Activity {
static MyActions mActions;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.act1);
Button btn = (Button) findViewById(R.id.button1);
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
startActivityForResult(new Intent(ActA.this,ActB.class), 15);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d("Response","requestCode" + requestCode + " resultCode" + resultCode);
mActions.doActions();
}
public static void setMyListener(MyActions act){
mActions = act;
}
}
2nd Activity : ActB.java
public class ActB extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.act2);
}
}
The MainActivity when app launchs
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Start the service
startService(new Intent(this, MyService.class));
}
}
The Interface : MyActions.java
public interface MyActions {
public void doActions();
}
The Serivce class : MyService.java
public class MyService extends Service implements MyActions{
#Override
public IBinder onBind(Intent arg0) {
return null;
}
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.d("Response", "Started");
ActA.setMyListener(this);
startActivity(new Intent(this,ActA.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
#Override
public void doActions() {
Log.d("Response", "Listener working");
}
}
we are trying to implement a simple quiz which should be controlled by VoiceRecognition. We have to Activities one QuestionActivity and one AnswerActivity. In the QuestionActivity the question is read by TextToSpeech and afterwards the user can answer to the VoiceRecognition Activity. Then the AnswerActivity is started by startActivityForResult(...) which also uses a VoiceRecognition to make it possible for the user to navigate back to the next Question. However, if the user returns to his second Question, the VoiceRecognizer wouldnt work because of an unknown error. See the sample code below:
public class QuestionActivity extends Activity implements OnClickListener, OnInitListener, OnUtteranceCompletedListener {
private static final int VOICE_RECOGNITION_REQUEST_CODE = 1234;
private TxtToSpeech toSpeech = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
toSpeech = new TxtToSpeech(this);
setContentView(R.layout.main);
// Get display items for later interaction
Button speakButton = (Button) findViewById(R.id.btn_speak);
// Check to see if a recognition activity is present
PackageManager pm = getPackageManager();
List<ResolveInfo> activities = pm.queryIntentActivities(
new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0);
if (activities.size() != 0) {
speakButton.setOnClickListener(this);
} else {
speakButton.setEnabled(false);
speakButton.setText("Recognizer not present");
}
}
public void onClick(View v) {
if (v.getId() == R.id.btn_speak) {
startVoiceRecognitionActivity();
}
}
private void startVoiceRecognitionActivity() {
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
intent.putExtra(RecognizerIntent.EXTRA_PROMPT, "Speech recognition demo");
intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
startActivityForResult(intent, VOICE_RECOGNITION_REQUEST_CODE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == VOICE_RECOGNITION_REQUEST_CODE && resultCode == RESULT_OK) {
//---Code to restart
//Without this code the recognizer wont work!
Intent i = getIntent();
finish();
startActivity(i);
//-----------------
Intent intent = new Intent(this, SubActivity.class);
startActivityForResult(intent , 2222);
}
else if( requestCode == 2222 )
{
saySomething();
}
super.onActivityResult(requestCode, resultCode, data);
}
void saySomething()
{
toSpeech.playVoice(new String[] {"My Question"}, true); //true == start Recognition afterwards
}
#Override
public void onInit(int status) {
toSpeech.mTts.setLanguage(Locale.US);
toSpeech.mTts.setOnUtteranceCompletedListener(this);
saySomething();
}
#Override
public void onUtteranceCompleted(String utteranceId) {
startVoiceRecognitionActivity();
}
public class AnswerActivity extends Activity implements OnInitListener, OnUtteranceCompletedListener{
public final static int VOICE_RECOGNITION_REQUEST_CODE = 4321;
private TxtToSpeech toSpeech = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
toSpeech = new TxtToSpeech(this);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
setResult(RESULT_OK);
finish();
super.onActivityResult(requestCode, resultCode, data);
}
#Override
public void onUtteranceCompleted(String utteranceId) {
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
intent.putExtra(RecognizerIntent.EXTRA_PROMPT, "Speech recognition demo");
startActivityForResult(intent, VOICE_RECOGNITION_REQUEST_CODE);
}
#Override
public void onInit(int status) {
toSpeech.mTts.setOnUtteranceCompletedListener(this);
toSpeech.mTts.setLanguage(Locale.US);
toSpeech.playVoice(new String[] {"correct answer"}, true); //again start recognition after voice
}
}
public class TxtToSpeech {
public TextToSpeech mTts = null;
public Context ctxt = null;
public boolean recordAnswer = false;
public TxtToSpeech(Context context){
mTts = new TextToSpeech(context, (OnInitListener)context);
ctxt = context;
}
public void playVoice(String[] sentences, boolean answer){
final HashMap<String, String> utteranceMap = new HashMap<String,String>();
utteranceMap.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "1");
recordAnswer = answer;
StringBuilder builder = new StringBuilder();
for( String s:sentences)
{
builder.append(s);
builder.append(",");
}
final String text = builder.toString();
if( recordAnswer )
mTts.speak(text, TextToSpeech.QUEUE_ADD, utteranceMap);
else
mTts.speak(text, TextToSpeech.QUEUE_ADD, null);
}
}
do I always have to restart the whole QuestionActivity in order to have a running VoiceRecognition? During the game the user only cycles between the Question- and the AnswerActivity is there a nicer way than just finish()-ing the Activities?
Please describe the error you get.
In general, restarting an activity should be a normal part of any Android activity since the user switches all the time. Also, if two activities are awkward, maybe you can get by with just a single one.