Android onActivityResult永远不被调用

3

我的onActivityResult方法从未被调用。我正在使用Android 2.2。

我正在使用Tabhost,其中TabHost包含TabGroup,TabGroup包含单独的Activities。

我的一个单独的Activity运行以下Intent:

 Intent intent = new Intent(); 
 intent.setType("image/*");
 intent.setAction(Intent.ACTION_GET_CONTENT);
 startActivityForResult(Intent.createChooser(intent,
                    "Select Picture"), 0);

这会加载我的图库应用程序,我使用默认的Android图库选择一张图片,但当我返回我的活动时,我的onActivityResult没有被调用。
它看起来像这样 - 我在if(resultCode == 0)处设置了断点,所以现在,我的onActivityResult的逻辑不重要。
 public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == 0) {
        if (requestCode == 0) {
            Uri selectedImageUri = data.getData();

            //OI FILE Manager
            filemanagerstring = selectedImageUri.getPath();

            //MEDIA GALLERY
            selectedImagePath = getPath(selectedImageUri);

            //DEBUG PURPOSE - you can delete this if you want
            if(selectedImagePath!=null)
                System.out.println(selectedImagePath);
            else System.out.println("selectedImagePath is null");
            if(filemanagerstring!=null)
                System.out.println(filemanagerstring);
            else System.out.println("filemanagerstring is null");

            //NOW WE HAVE OUR WANTED STRING
            if(selectedImagePath!=null)
                System.out.println("selectedImagePath is the right one for you!");
            else
                System.out.println("filemanagerstring is the right one for you!");
        }
    }
}

生命周期函数在选项卡主机/选项卡组中的活动中经常以无序和间歇性的方式被调用,所以我检查了关闭画廊后正在调用哪些生命周期函数(这发生在我从Android画廊中选择图像后)。
唯一被调用的是TabHost活动中的onResume()。因此,我尝试将完全相同的onActivityResult()方法放在我的TabHost类和TabActivity类中。在方法开头都设置断点。
这两个类都没有被调用。
现在我不知道该怎么办,如果内置的任何接收方法都不会响应,则如何从我的应用程序中获取来自画廊应用程序的结果。
由于我知道我的主TabHost会调用onResume(),因此我尝试添加Intent graphics = getIntent()以查看它是否会接收来自画廊选择的数据,但它并不会,因此我也不知道如何在onResume()方法中运行逻辑。
欢迎提供解决方案! :)

您确定您在调用 startActivityForResult(..) 的同一活动中拥有 onActivityResult 吗? - dymmeh
它确实被加入了 tabgroup 和 tabactivity 页面,并且设置了断点以查看它们是否有被调用。讽刺的是,它说如果没有正确调用会抛出 ActivityNotFoundException 异常,但这也不起作用 :( 它根本就没有被调用。 - CQM
只是为了好玩,你是否尝试创建一个测试项目,并将你在上面的代码中拥有的intent和onActivityResult一起复制,以确保它能够正常工作。如果它不能正常工作,那么你的手机/模拟器可能有问题。如果它可以正常工作,那么你的代码中可能忽略了某些内容,或者你调用的Activity没有正确地调用setResult(...)。 - dymmeh
7个回答

18

尝试使用包含当前活动的选项卡组活动的上下文来调用startActivityForResult,然后在选项卡组活动中监听。

使用以下方法获取tabGroupActivity:

TabGroupActivity parentActivity = (TabGroupActivity)getParent();

接着从它(指上一个代码块中的Activity)调用startActivityForResult:

parentActivity.startActivityForResult(...);

最后,在tabGroupActivity中加入一个onActivityResult监听器:

protected void onActivityResult(int requestCode, int resultCode,Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);
    }

1
+1 我从一个片段中调用了startActivityForResult(),所以我必须在它之前加上父活动的上下文。 - charles young

16

从许多类似这样的问题来看,调用活动可能不会触发调用方的onActivityResult()方法,原因有很多。

我找到的一个原因是,当我使用小于0的 requestCode 值调用startActivityForResult(intent, requestCode)时。我的应用程序不需要requestCode,而Android文档说使用< 0将不会发送requestCode

但Android文档没有提及requestCode < 0的后果。后果是它会防止调用方的onActivityResult()方法被调用! 糟糕!

因此,即使您的应用程序不需要requestCode,您仍然可以使用值>=0的requestCode

这就是我今天学到的内容:-)


是的,我认为我看到了一个类似的答案,并最近在另一个应用程序中尝试过。 - CQM

4
解决方案是在主活动之上调用一个透明的活动。这个透明的活动在选项卡宿主前面,具有正常的生命周期函数。
这个透明活动调用画廊意图onCreate(),并像正常情况下一样返回所有内容,你将能够像往常一样将返回的信息传递回应用程序的其余部分。finish()在onActivityResult方法中,因此用户甚至不会注意到调用了一个透明的活动。
从评论中复制的更新: 活动A通过普通意图调用活动B。活动B没有xml,并像这样运行onCreate
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    //setContentView(R.layout.dialogpopper); 

    Intent intent = new Intent(Intent.ACTION_PICK); 
    intent.setType("image/*"); startActivityForResult(intent, 0);

}//end onCreate 

当 Activity C 完成后,它会调用 Activity B 的 onActivityResult。

2
这绝对应该被视为一种黑客技巧。 - Falmarri
同意@Falmarri的观点,这确实有些"hacky"。不过,很高兴听到你找到了一种让它工作的方法。 - dymmeh
这个黑客攻击的代码示例是否可能?我真的很想知道这是如何实现的! - David K
1
Activity A 通过普通意图调用 Activity B。Activity B 没有 XML,并像这样运行 onCreate `public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //setContentView(R.layout.dialogpopper); Intent intent = new Intent(Intent.ACTION_PICK); intent.setType("image/*"); startActivityForResult(intent, 0);}//end onCreate` 当 Activity C 完成后,它会调用 Activity B 的 onActivityResult。 - CQM

2
你只需要从你的清单文件中删除 android:noHistory="true" 这一行即可。

1

使用常量值作为结果代码:

Activity.RESULT_OK 和 Activity.RESULT_CANCELED

你会发现取消的值实际上是0。因此在你的代码中,你正在检查活动是否被取消。

将你的代码更改为:

if (resultCode == Activity.RESULT_OK) {
...
}

另外,将您的Intent操作更改为:

intent.setAction(Intent.ACTION_PICK);

如果你这样做,你只需要调用

    Intent intent = new Intent(Intent.ACTION_PICK);
    intent.setType("image/*");
    startActivityForResult(intent, 0); 

不需要创建选择器,它会自动选择与该意图和MIME类型相关联的活动,并将它们显示给您。


我将上述代码放在一个测试活动中,在我的手机上尝试了一下,它完美地工作了。我不确定是什么阻止了onActivityResult(..)的调用。你确定你在调用startActivityForResult(..)的同一个活动中有onActivityResult吗? - dymmeh

0

onActivityResult方法的调用方式取决于您的Activity的launchMode(在清单文件中)。我不确定这是否会成为一个问题。


-1

你的onActivityResult方法上面有@ Override吗?

(看了一下旧代码,不确定为什么需要它)在该方法中先调用super.onactivityresult(requestcode, resultscode, data)

我的意图没有那些其他的东西: startActivityForResult(Intent.createChooser(intent, "Select Picture"), 0); 我认为应该只是这样: startActivityForResult(source.class, destination.class); 当然,source和destination应该是类的名称。

public class ImageSwitcherView extends Activity {
    int pics[] = { R.drawable.image000, R.drawable.image001,
            R.drawable.image002};

    private int currentIndex = 0;
    SharedPreferences preferences;
    Gallery gallery;
    ImageView fullPicView;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.galleryview);
        Bundle extras = getIntent().getExtras();
        currentIndex = extras.getInt("bookmark");
        gallery = (Gallery) findViewById(R.id.Gallery01);

        gallery.setAdapter(new ImageAdapter(this));
        gallery.setSelection(currentIndex);
        gallery.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView parent, View v, int position,
                    long id) {
                currentIndex = position;
                // ---display the images selected---
                fullPicView = (ImageView) findViewById(R.id.imageView1);
                fullPicView.setImageResource(pics[currentIndex]);
                fullPicView.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        // TODO Auto-generated method stub
                        Intent myIntent = new Intent(ImageSwitcherView.this,
                                imageView.class);
                        int resID = pics[currentIndex];
                        myIntent.putExtra("resID", resID);
                        myIntent.putExtra("index", currentIndex);
                        startActivityForResult(myIntent, 1);
                    }
                });
            }
        });
    }

    public class ImageAdapter extends BaseAdapter {
        private Context context;
        private int itemBackground;

        public ImageAdapter(Context c) {
            context = c;
            // ---setting the style---
            TypedArray a = obtainStyledAttributes(R.styleable.Gallery1);
            itemBackground = a.getResourceId(
                    R.styleable.Gallery1_android_galleryItemBackground, 0);
            a.recycle();
        }

        // ---returns the number of images---
        public int getCount() {
            return pics.length;
        }

        // ---returns the ID of an item---
        public Object getItem(int position) {
            return position;
        }

        public long getItemId(int position) {
            return position;
        }

        // ---returns an ImageView view---
        public View getView(int position, View convertView, ViewGroup parent) {
            ImageView imageView = new ImageView(context);
            imageView.setImageResource(pics[position]);
            imageView.setScaleType(ImageView.ScaleType.FIT_XY);
            imageView.setLayoutParams(new Gallery.LayoutParams(150, 120));
            imageView.setBackgroundResource(itemBackground);
            return imageView;
        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        currentIndex = data.getIntExtra("bookmark", 0);
        gallery.setSelection(currentIndex);
        fullPicView.setImageResource(pics[currentIndex]);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK
                || keyCode == KeyEvent.KEYCODE_HOME) {
            preferences = PreferenceManager.getDefaultSharedPreferences(this);

            SharedPreferences.Editor editor = preferences.edit();
            editor.putInt("bookmark", gallery.getSelectedItemPosition());
            editor.commit();
            finish();
        }
        return super.onKeyDown(keyCode, event);
    }

}

我的活动中有覆盖,我会尝试您的其他建议。 - CQM
还可以尝试下面Dymmeh建议的内容吗? - owen gerig
关于意图(intents),我正在打开内置画廊,这会调用安卓应用程序,该应用程序位于我的应用程序之外。如果它在我的应用程序之外,我无法进行 source.class、destination.class 等操作。无论如何,我运气不好。我的活动仍然没有被调用。使用 Dymmeh 的结果代码和你的 super 建议都没有成功。 - CQM
请查看我的有关Intent操作的更新答案。我“认为”这就是你需要的。 - dymmeh
我不确定你所说的“超出我的应用程序”的安卓应用是什么意思,但从听起来的描述来看,你尝试做的项目与我过去完成的一个非常相似。我会编辑我的答案并提供一些代码,看看是否有帮助。 - owen gerig
我仍然不明白为什么您要调用一个图库意图而不是实例化图库类。如果您查看我发布的代码,那是图库类的一个实现,也应该是这样的。(我也不明白为什么有人给它打分,这是一个很好的示例,展示了相关主题的示例和实现) - owen gerig

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接