android testing onActivityResult - android

I am searching for a solution to get my test (which actually is an ActivityInstrumentationTextCase2) testing the onActivityResults method of my Activity with a special (mock) request- / resultcode and intent...
Code:
method should be tested:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
//In this case the user selected an image from his harddrive
case StartupActivity.PICK_IMAGE:
if (resultCode == Activity.RESULT_OK) {
this.processSelectedFile(data.getData());
}
break;
}
}
test class:
public void testOnActivityResult() {
//here I would like to call the onActivityResult method from my mActivity object.
}

To test a protected member, declare (in your test project) a new class that derives from your target:
public class TestMyActivity : MyActivity
{
//constructors
public void testOnActivityResult(int requestCode, int resultCode, Intent data) {
//call super one
super.onActivityResult(requestCode, resultCode, data);
}
}
Now in your test, create one of these and you can call the method.
Source of idea:
http://codebetter.com/karlseguin/2009/08/19/testing-protected-methods-is-easy/

Related

Android: How to use onActivityResult from activity object?

I have a helper class that takes an activity and does stuff with it.
public MyClass(AppCompatActivity activity, Callbacks callbacks) {
this.activity = activity;
this.callbacks = callbacks;
}
What I do in this class is basically call other activies/libraries in a certain order and use the results. I put this in a helper class so that I can easily reuse the code.
This is the problem I have:
With the new ActivityResultLauncher it's easy to "modularize" what I need:
ActivityResultLauncher<Intent> chooseImageLauncher = activity.registerForActivityResult(...);
...
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
chooseImageLauncher.launch(intent);
And in the implementation of chooseImageLauncher I do whatever I want next. In this case, I will call a library.
The problem is that the library I'm calling was last updated 2020 and doesn't provide a method for an ActivityResultLauncher. It only supports the old way with onActivityResult:
MyLibrary.init().start(activity);
And the result can be caught like this:
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
if (requestCode == MyLibrary.REQUEST_CODE && resultCode == RESULT_OK) {
...
}
}
But I can only implement that in each activity itself. How can I implement here?
You could add a private class inside your helper class that extends Activity. This way you can still catch the value emitted by your library.
private class MyLibraryActivityWrapper extends AppCompatActivity {
public void init() {
MyLibrary.init().start(activity);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == MyLibrary.REQUEST_CODE && resultCode == RESULT_OK) {
}
}
}

onActivityResult from Activity to Fragment

I have a problem regarding onActivityResult. First, I opened the Add New Message Fragment to select the image. When I select the image, it doesn't return the result to my current fragment. I put onActivityResult in both my MainActivity and AddMessageFragment but it doesn't call the result in my fragment. My MainActivity is used to set up the Navigation Controller. I use Matisse library for my image picker. Can someone please help me with me? Been stuck for the whole day with this issue.
MainActivity
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
}
AddMessageFragment
#OnClick({R.id.addImage})
public void openGallery()
{
permission.addOnStorageListener(new Permission.OnStorageSuccess()
{
#Override
public void OnStorageSuccess()
{
permission.requestCamera();
}
});
permission.addOnCameraListener(new Permission.OnCameraSuccess()
{
#Override
public void OnCameraSuccess()
{
Matisse.from(getActivity())
.choose(MimeType.of(MimeType.JPEG, MimeType.PNG))
.countable(false)
.capture(true)
.captureStrategy(new CaptureStrategy(true, "com.gprop.users.fileprovider"))
.maxSelectable(1)
.restrictOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
.thumbnailScale(0.85f)
.imageEngine(new Glide4Engine())
.originalEnable(false)
.forResult(99);
}
});
permission.requestStorage();
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 99 && resultCode == Main.RESULT_OK)
{
mSelected = Matisse.obtainPathResult(data);
if(mSelected.size() > 0)
{
Glide.with(this).load(mSelected.get(0)).into(addImage);
Luban.compress(new File(mSelected.get(0)), getActivity().getFilesDir())
.putGear(Luban.THIRD_GEAR)
.asObservable()
.subscribe(new Consumer<File>()
{
#Override
public void accept(File file) throws Exception
{
newfile = file;
}
}, new Consumer<Throwable>()
{
#Override
public void accept(Throwable throwable) throws Exception
{
throwable.printStackTrace();
Toast.makeText(getActivity(), throwable.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
else
{
Toast.makeText(getActivity(), "No image selected", Toast.LENGTH_SHORT).show();
}
}
}
You are calling Matisse.from() on the Activity which you are getting from the getActivity() method, tit must be returning you your MainActivity and the onActivityResult will be called for the MainActivity where you are doing nothing and calling super.onActivityResult().
Possible Solutions: .
Shift your onActivityResult code logic from your AddMessageFragment to MainActivity
Change you Matisse call from Matisse.from(getActivity()) to Matisse.from(this), because looking at the source code of Matisse it also supports Fragment context.
Using the second solution you should get your onActivityResult callback in the fragment and you won't need to change/shift any other code logic.
Hope this helps :)
An explicit call from fragment to the onActivityResult function is as follows.
In the parent Activity class, override the onActivityResult() method and even override the same in the Fragment Class and call as the following code.
In MainActivity class:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.layoutContainer);
fragment.onActivityResult(requestCode, resultCode, data);
}
In AddMessageFragment class:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// In fragment class callback
}
Replace your activity onActivityResult method by below code
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
Fragment fragment = (Fragment) getChildFragmentManager().findFragmentByTag(childTag);
if (fragment != null) {
fragment.onActivityResult(requestCode, resultCode, intent);
}
}
It will call your fragment onActivityResult after this execute.
OnActivityResult() function works on Activity. I suggest you call this function on your activity and implement your logic inside your fragment onResume() function. In order to get data from Activity use global val.

resultCode 0 and data zero in onActivityResult

I have activity with one fragment, and then that fragment call some activity which that activity will give some value into first activity. i use onActivityResult but i don't know why resultCode always 0 and data always zero,.
on Activity One i have
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d(TAG, "onActivityResult: "+ requestCode +" "+resultCode+" "+data);
}
Activity one have some fragmentX which call activity two
private final int REQUEST_CODE = 10;
private void start (){
Intent intent = new Intent(getContext(),Main2Activity.class);
intent.putExtra("xxx","test1");
getActivity().startActivityForResult(intent,REQUEST_CODE);
}
then in Activity Two, when i touch onBackpress, will pass some value.
public class Main2Activity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
}
#Override
public void onBackPressed() {
super.onBackPressed();
Intent intent = getIntent().putExtra("yyy","test2");
setResult(RESULT_OK,intent);
}
}
but, i don't know why, onActivityResult i can't get the data.
my final purpose is, i want to setArgument that data to fragmentX.
1.You can call onActivityResult in the fragment
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d(TAG, "onActivityResult: "+ requestCode +" "+resultCode+" "+data);
}
2.Use super.onBackPressed(); after setResult in your method
#Override
public void onBackPressed() {
Intent intent = getIntent().putExtra("yyy","test2");
setResult(RESULT_OK,intent);
super.onBackPressed();
}
In first activity write the below code:
1st method:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
for (Fragment fragment : getSupportFragmentManager().getFragments()) {
fragment.onActivityResult(requestCode, resultCode, data);
}
}
In Fragment
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// In fragment write your logic here
}
2nd method: (I didn't try but as per doc may be this is one of the reason try once) if it will not work go 1st method its 100 percent solution
Here when your calling second activity using getContext()
getContext() - Returns the context view only current running activity.
getActivity()- Return the Activity this fragment is currently associated with.
Try instead of getContext() use getActivity() when you calling intent to next activity
Ex:
private final int REQUEST_CODE = 10;
Intent intent = new Intent(getActivity(),Main2Activity.class);
intent.putExtra("xxx","test1");
getActivity().startActivityForResult(intent,REQUEST_CODE);
For start new activity
private final int REQUEST_CODE = 10;
private void start (){
Intent intent = new Intent(getContext(),Main2Activity.class);
intent.putExtra("xxx","test1");
getActivity().startActivityForResult(intent,REQUEST_CODE);
}
From Second activity
public class Main2Activity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
}
#Override
public void onBackPressed() {
super.onBackPressed();
Intent intent = getIntent().putExtra("yyy","test2");
setResult(10,intent);
}
}
you have to set the integer code using which you have started second activity. you have started second activity with the code "10".so use the same value when you setResult(10,intent);
onActivityResult you need to check Request code
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==10){
if(data!=null)
{
//you have to manage your own list of fragments for activity because getSupportFragmentManager().getFragments() is deprecated now.
//Send data to fragments
if (arrayFragments != null) {
for (Fragment fragment : arrayFragments) {
fragment.onActivityResult(requestCode, resultCode, data);
}
}
}
}
}
Remember you have to manage your own list of fragments using ArrayList or HashMap.
Hope this will help you if you need any other help inform me.
if you wants to send return data in onActivityResult then you should use super.onBackPressed() after data set in setResult() method
example:
#Override
public void onBackPressed() {
val intent = Intent()
intent.putExtra("IsReturnData", true)
setResult(RESULT_OK,intent);
super.onBackPressed(); //write this line at the end of method
}

Execute functions in order in Android

I'm trying to make program with functions.
Code is so simple, but I'm struggling with basic grammar in java.
OnClickListener voiceListener = new OnClickListener() {
public void onClick(View v) {
FA();//I want FB is operated after FA and onActivityResult are finished..
FB();
}
};
private void FA(){...startActivityForResult(intent,check);
}
private void FB(){}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == check && resultCode == RESULT_OK){
results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
}
super.onActivityResult(requestCode, resultCode, data);
}
}
//
The problem is, when I click the button, FA and FB are operating together and seems like it FA, FB
What I wanted to see was, after FA is performed( intent is passed), the program gets into onActivityResult and results are applied to FB.
Where should I touch for doing this? What am I going to do?
I'm expecting to seeing opinions! :)
Execute the operations of FB() method inside the onActivityResult method, just like this
OnClickListener voiceListener = new OnClickListener() {
public void onClick(View v) {
FA();//I want FB is operated after FA and onActivityResult are finished..
//Don't call FB over here
}
};
//FA method defined here which startActivityForResult
private void FA(){...startActivityForResult(intent,check);
}
//FB method defined here
private void FB(){}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == check && resultCode == RESULT_OK){
results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
//Call FB over here
FB();
}
super.onActivityResult(requestCode, resultCode, data);
}
}
I hope this helps. Still got doubts? Comment below.

onActivityResult(int, int, Intent) is undefined for the type Object

I am getting the error on "onActivityResult" stating "onActivityResult(int, int, Intent) is undefined for the type Object"
I've looked at people that have had the same problem and they've said that it's caused due to poorly placed curley braces. I have tried to re-position them but keep getting more and more errors.
hopefully someone could help me out with this:
package com.website.test;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.util.Log;
import android.widget.EditText;
public class ListmenuActivity extends Activity {
#Override
protected void onCreate(Bundle saveInstanceState) {
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(saveInstanceState);
setContentView(R.layout.activity_listmenu);
EditText CPU = (EditText) findViewById(R.id.autoCompleteTextView4);
CPU.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent CPUList = new Intent(getApplicationContext(),
CPUList.class);
startActivityForResult(CPUList, 1);
}
});
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == 1)
;
Intent i = getIntent();
String product = data.getStringExtra("product");
EditText CPU = ((EditText) findViewById(R.id.autoCompleteTextView4));
CPU.setText(product);
}
EditText RAMList = (EditText) findViewById(R.id.autoCompleteTextView1);
RAMList.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent RAMList = new Intent(getApplicationContext(),
RAMList.class);
startActivityForResult(RAMList,1);
}
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == 1)
;
Intent i = getIntent();
String product = data.getStringExtra("product");
EditText RAM = ((EditText) findViewById(R.id.autoCompleteTextView4));
RAM.setText(product);
}
}
});
}
}
RAMList.setOnClickListener(new View.OnClickListener() {
// ...
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// ...
}
});
This is not going to work as you expect. That onActivityResult method will never be called.
onActivityResult is a method of an Activity, invoked by the Android runtime whenever that activity receives the result of another activity which it launched through startActivity(ForResult). You are trying to define it on a class solely implementing the View.OnClickListener interface, which does not have an onActivityResult method. It does not override any method of a superclass or interface, it's just a new method which has no special purpose at all.
You are passing that class instance to setOnClickListener, which is only concerned with calling onClick - as that is in the View.OnClickListener interface. It doesn't know that there's an onActivityResult method in that object, and it simply doesn't care.
If you want to get this working, you need to put that code in the onActivityResult of your ListmenuActivity. Since that class inherits Activity, its onActivityResult will be called for all activities launched by startActivity(ForResult). You'll need to differentiate between your two separate launches so you know what to do for the given result. That's why Android provides you with a requestCode: give your different launches different requestCodes and you'll be able to separate them when you receive their results in onActivityResult.
Thus, your ListmenuActivity.onActivityResult method should look like:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) {
// Handle result of CPUList
} else if (requestCode == 2) {
// Handle result of RAMList
}
super.onActivityResult(requestCode, resultCode, data);
}
You would launch your subactivities with startActivityForResult(CPUList, 1) and startActivityForResult(RAMList, 2).
(Side note: it's very confusing if you name two different variables RAMList - an EditText and an Intent - in the same scope.)
I think you don't need to call:
super.onActivityResult(requestCode, resultCode, data);
and this code do nothing:
if (requestCode == 1)
;
You can remove it.
there is already onActivityResult() delared no need to define it two times.
another thing is you had mention 2nd onActivityResult() in onClickListener() which is wrong.
Wrong Points in your code
onClickListener() can not have onActivityResult() in it.
you don't need to do findViewById() at onActivityResult() as you had already done it at onCreate().
problem of missing brackates
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// your code
if (requestCode == 1) {
Intent i = getIntent();
String product = data.getStringExtra("product");
CPU.setText(product);
}
}
you just need to replace this onActivityResult() with these one.

Categories

Resources