一个关于startActivityForResult的小问题
来源:互联网 发布:移动支付数据 编辑:程序博客网 时间:2024/06/11 12:55
之前开发需求时,需要调用系统相机拍照.并将拍照照片上传服务端.但拍照后死活获取不到返回的result.
@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) {if (requestCode == CAMERA_REQUEST_CODE && resultCode == Activity.RESULT_OK) {if (mCurrentCameraFile != null && mCurrentCameraFile.exists()) {....Log.v( TAG,"onActivityResult get pic success ");//通知MediaScan进行扫描添加数据库BitmapUtils.notifyAddPictureToSDCard(mContext, mCurrentCameraFile);}}}怎么都不打印日志:onActivityResult get pic success.这里我打印日志比较片面,仅打印了成功的日志....为了这个破问题折腾了好几个小时.太菜了呃...
首先上传调用相机的代码
<span style="white-space:pre"></span>mCurrentCameraFile = Utils.getOutputMediaFile();Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); Uri outputFileUri = Uri.fromFile(mCurrentCameraFile); cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);cameraIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);mParentFragment.startActivityForResult(cameraIntent, CAMERA_REQUEST_CODE);无意中发现,只要去掉cameraIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)这一行,就立马可以得到正确的ActivityResult了.为啥啊?不就是新起一个栈来启动相机吗?
直接看看startActivity的源码怎么对这个FLAG_ACTIVITY_NEW_TASK怎么处理的吧,源码位于(android4.4.2)frameworks\base\services\java\com\android\server\am\ActivityStackSupervisor.java
final int startActivityUncheckedLocked(ActivityRecord r, ActivityRecord sourceRecord, int startFlags, boolean doResume, Bundle options) { final Intent intent = r.intent; final int callingUid = r.launchedFromUid; int launchFlags = intent.getFlags(); ... if (sourceRecord == null) { // This activity is not being started from another... in this // case we -always- start a new task. if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) { Slog.w(TAG, "startActivity called from non-Activity context; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent); <span style="color:#ff0000;">launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;</span> } } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { // The original activity who is starting us is running as a single // instance... this new activity it is starting must go on its // own task. <span style="color:#ff0000;">launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;</span> } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) { // The activity being started is a single instance... it always // gets launched into its own task. <span style="color:#ff0000;">launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;</span> } ActivityInfo newTaskInfo = null; Intent newTaskIntent = null; final ActivityStack sourceStack; if (sourceRecord != null) { if (sourceRecord.finishing) { // If the source is finishing, we can't further count it as our source. This // is because the task it is associated with may now be empty and on its way out, // so we don't want to blindly throw it in to that task. Instead we will take // the NEW_TASK flow and try to find a task for it. But save the task information // so it can be used when creating the new task. if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) { Slog.w(TAG, "startActivity called from finishing " + sourceRecord + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent); <span style="color:#ff0000;">launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;</span> newTaskInfo = sourceRecord.info; newTaskIntent = sourceRecord.task.intent; } sourceRecord = null; sourceStack = null; } else { sourceStack = sourceRecord.task.stack; } } else { sourceStack = null; } if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { // For whatever reason this activity is being launched into a new // task... yet the caller has requested a result back. Well, that // is pretty messed up, so instead immediately send back a cancel // and let the new task continue launched as normal without a // dependency on its originator. Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result."); <span style="color:#ff0000;">r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho, r.requestCode, Activity.RESULT_CANCELED, null);</span> r.resultTo = null; } ..... if (newTask) { EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId); } ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task); targetStack.mLastPausedActivity = null; <span style="color:#ff0000;">targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);</span> mService.setFocusedActivityLocked(r); return ActivityManager.START_SUCCESS; }
上面的startActivityUncheckedLocked()方法我主要截取了前面对FLAG_ACTIVITY_NEW_TASK的处理.
1.对于一下场景,都会对intent的FLAG_ACTIVITY_NEW_TASK标志位置1.
(1)sourceRecord为空,即执行startActivity的哪个ActvityRecord为空;
(2)sourceRecord.launchMode为ActivityInfo.LAUNCH_SINGLE_INSTANCE;
(3)待启动的新ActivityRecord的launchMode为LAUNCH_SINGLE_INSTANCE或者LAUNCH_SINGLE_TASK;
2.若需要返回result,且intent的FLAG_ACTIVITY_NEW_TASK标志位为1,则首先给ResultToActivity一个RESULT_CANCELED(即-1)结果.这个逻辑比较简单,直接让ActivityThread来分发onActivityResult()
3.初始化好目标targetStack后,继续执行startActivity,具体可以参见老罗的android之旅Android应用程序内部启动Activity过程(startActivity)的源代码分析.
通过上面startActivityUncheckedLocked()方法的分析,直到只要设置了FLAG_ACTIVITY_NEW_TASK,源Activity就会收到RESULT_CANCELED结果回调.下面用demo测试下.
@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {Log.e("onActivityResult ", "requestCode:" + requestCode + "resultCode:" + resultCode + ",data" + data);Toast.makeText(this, "onActivityResult resultCode " + resultCode, Toast.LENGTH_SHORT).show();super.onActivityResult(requestCode, resultCode, data);}public static final int CAMERA_REQUEST_CODE = 111;@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.btn1:Intent intent = getContentProviderActivityIntent();intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);if (intent != null) {startActivityForResult(intent, CAMERA_REQUEST_CODE);}break;case R.id.btn2:Intent intent1 = getContentProviderActivityIntent();if (intent1 != null) {startActivityForResult(intent1, CAMERA_REQUEST_CODE);}break;}}private File mCurrentCameraFile;public Intent getContentProviderActivityIntent() {mCurrentCameraFile = getOutputMediaFile();if (mCurrentCameraFile != null) {return getCameraAppIntent(mCurrentCameraFile);} else {return null;}}public static Intent getCameraAppIntent(File outFile) {Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); Uri outputFileUri = Uri.fromFile(outFile); cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);return cameraIntent;}public static File getOutputMediaFile() {File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "Camera");if (!mediaStorageDir.exists()) {if (!mediaStorageDir.mkdirs()) {return null;}}// Create a media file nameString timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA).format(new Date());File mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg");return mediaFile;}
两个按钮,分别为添加和不添加FLAG_ACTIVITY_NEW_TASK标志.打印日志如下:
btn1:在相机页面还没起来前就打印了:12-31 09:51:39.566: E/onActivityResult(20938): requestCode:111resultCode:0,datanull
btn2:在相机页面结束后才打印了:12-31 09:53:01.880: E/onActivityResult(20938): requestCode:111resultCode:-1,datanull
就这样了,startActivityForResult时不能设置FLAG_ACTIVITY_NEW_TASK标志
- 一个关于startActivityForResult的小问题
- 【Android】关于startActivityForResult的问题
- 关于startActivityForResult问题
- 关于JAVA import 的一个小问题
- 关于csdn博客的一个小问题
- 关于csdn博客的一个小问题
- 关于csdn博客的一个小问题
- 关于csdn博客的一个小问题
- 关于csdn博客的一个小问题
- 关于csdn博客的一个小问题
- 关于csdn博客的一个小问题
- 关于csdn博客的一个小问题
- 关于csdn博客的一个小问题
- 关于JAVA的一个小问题--请老鸟们帮下忙
- 关于strcmp的一个小问题
- 关于一个小问题的联想
- 号外:关于包的一个小问题
- 关于转型的一个小问题
- nyoj 85 有趣的数
- 【POJ3659】【USACO 2008 Jan Gold】 3.Cell Phone Network 树上最小支配集/贪心 两种做法
- Junit4使用注意事项
- 条款 30: 避免这样的成员函数:其返回值是指向成员的非 const 指针或引用, 但成员的访问级比这个函数要低
- 比较好用的Lucene中文分词
- 一个关于startActivityForResult的小问题
- 高级图形编程(基于opengl)2
- 学习Unity3D之GUI基础。
- Spring IOC容器基本原理
- ARM Cortex A8处理器和A9有哪些区别呢
- 锋利的SQL2014: 内存优化表
- tinyhttpd跨平台代码兼容linux和solaris
- MVC中前台如何向后台传递数据------$.get(),$post(),$ajax(),$.getJSON()总结
- 【SpringMVC系列三】 EasyUI +springMVC 乱码问题