6.0联系人跳转到短信的逻辑
来源:互联网 发布:七天网络阅卷登录 编辑:程序博客网 时间:2024/05/30 22:43
Android 6.0中其他app跳转到messaging后,按back键无法返回原应用,分析了下原因,原来是处在messaging的启动方式上。
在Android 6.0中联系人的详情统一为了QuickContactActivity,乍看里面内容很多、很杂,整理了下,发现主要是onCreate里的这几个自定义的ExpandingEntryCardView。
@Override protected void onCreate(Bundle savedInstanceState) { …………………… mContactCard = (ExpandingEntryCardView) findViewById(R.id.communication_card); mNoContactDetailsCard = (ExpandingEntryCardView) findViewById(R.id.no_contact_data_card); mRecentCard = (ExpandingEntryCardView) findViewById(R.id.recent_card); mAboutCard = (ExpandingEntryCardView) findViewById(R.id.about_card); …………………… }
跳转到短信,必然是有点击事件的,这些内容和上面的代码一样都是在onCreate中:
mNoContactDetailsCard.setOnClickListener(mEntryClickHandler);mContactCard.setOnClickListener(mEntryClickHandler);mContactCard.setExpandButtonText( getResources().getString(R.string.expanding_entry_card_view_see_all)); mContactCard.setOnCreateContextMenuListener(mEntryContextMenuListener);mRecentCard.setOnClickListener(mEntryClickHandler); mRecentCard.setTitle(getResources().getString(R.string.recent_card_title));mAboutCard.setOnClickListener(mEntryClickHandler); mAboutCard.setOnCreateContextMenuListener(mEntryContextMenuListener);
跳转逻辑就在这个mEntryClickHandler中:
final OnClickListener mEntryClickHandler = new OnClickListener() { @Override public void onClick(View v) { final Object entryTagObject = v.getTag(); if (entryTagObject == null || !(entryTagObject instanceof EntryTag)) { Log.w(TAG, "EntryTag was not used correctly"); return; } final EntryTag entryTag = (EntryTag) entryTagObject; final Intent intent = entryTag.getIntent(); final int dataId = entryTag.getId(); if (dataId == CARD_ENTRY_ID_EDIT_CONTACT) { editContact(); return; } //????? //intent.setAction(Intent.ACTION_DIAL); //-----------------------------------// // Pass the touch point through the intent for use in the InCallUI if (Intent.ACTION_CALL.equals(intent.getAction())) { if (TouchPointManager.getInstance().hasValidPoint()) { Bundle extras = new Bundle(); extras.putParcelable(TouchPointManager.TOUCH_POINT, TouchPointManager.getInstance().getPoint()); intent.putExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, extras); } } intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mHasIntentLaunched = true; try { startActivity(intent); } catch (SecurityException ex) { Toast.makeText(QuickContactActivity.this, R.string.missing_app, Toast.LENGTH_SHORT).show(); Log.e(TAG, "QuickContacts does not have permission to launch " + intent); } catch (ActivityNotFoundException ex) { Toast.makeText(QuickContactActivity.this, R.string.missing_app, Toast.LENGTH_SHORT).show(); } // Default to USAGE_TYPE_CALL. Usage is summed among all types for sorting each data id // so the exact usage type is not necessary in all cases String usageType = DataUsageFeedback.USAGE_TYPE_CALL; final Uri intentUri = intent.getData(); if ((intentUri != null && intentUri.getScheme() != null && intentUri.getScheme().equals(ContactsUtils.SCHEME_SMSTO)) || (intent.getType() != null && intent.getType().equals(MIMETYPE_SMS))) { usageType = DataUsageFeedback.USAGE_TYPE_SHORT_TEXT; } // Data IDs start at 1 so anything less is invalid if (dataId > 0) { final Uri dataUsageUri = DataUsageFeedback.FEEDBACK_URI.buildUpon() .appendPath(String.valueOf(dataId)) .appendQueryParameter(DataUsageFeedback.USAGE_TYPE, usageType) .build(); try { final boolean successful = getContentResolver().update( dataUsageUri, new ContentValues(), null, null) > 0; if (!successful) { Log.w(TAG, "DataUsageFeedback increment failed"); } } catch (SecurityException ex) { Log.w(TAG, "DataUsageFeedback increment failed", ex); } } else { Log.w(TAG, "Invalid Data ID"); } } };
在onClick中,intent的获取是通过view -> getTag -> getIntent来获取的。发送短信这个button对应view获取到的intent的action自然为ACTION_SENDTO,这个action是会由默认的短信应用来处理的。在Android 6.0中,我们将老旧的Mms替换为了messaging,因此被启动的activity为LaunchConversationActivity,到了这里就开始有趣了。
本来我以为这个activity就是编辑短信并发送的activity,查看源码发现其仅有区区137行代码,而且还在onCreate中把自己finish了!?!
@Override protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (UiUtils.redirectToPermissionCheckIfNeeded(this)) { return; } final Intent intent = getIntent(); final String action = intent.getAction(); if (Intent.ACTION_SENDTO.equals(action) || Intent.ACTION_VIEW.equals(action)) { String[] recipients = UriUtil.parseRecipientsFromSmsMmsUri(intent.getData()); final boolean haveAddress = !TextUtils.isEmpty(intent.getStringExtra(ADDRESS)); final boolean haveEmail = !TextUtils.isEmpty(intent.getStringExtra(Intent.EXTRA_EMAIL)); if (recipients == null && (haveAddress || haveEmail)) { if (haveAddress) { recipients = new String[] { intent.getStringExtra(ADDRESS) }; } else { recipients = new String[] { intent.getStringExtra(Intent.EXTRA_EMAIL) }; } } mSmsBody = intent.getStringExtra(SMS_BODY); if (TextUtils.isEmpty(mSmsBody)) { // Used by intents sent from the web YouTube (and perhaps others). mSmsBody = getBody(intent.getData()); if (TextUtils.isEmpty(mSmsBody)) { // If that fails, try yet another method apps use to share text if (ContentType.TEXT_PLAIN.equals(intent.getType())) { mSmsBody = intent.getStringExtra(Intent.EXTRA_TEXT); } } } if (recipients != null) { mBinding.bind(DataModel.get().createLaunchConversationData(this)); mBinding.getData().getOrCreateConversation(mBinding, recipients); } else { // No recipients were specified in the intent. // Start a new conversation with contact picker. The new conversation will be // primed with the (optional) message in mSmsBody. onGetOrCreateNewConversation(null); } } else { LogUtil.w(LogUtil.BUGLE_TAG, "Unsupported conversation intent action : " + action); } // As of M, activities without a visible window must finish before onResume completes. finish(); }
原来这是一个没有UI的activity,它的作用就是启动ConversationActivity,启动代码如下:
@Override public void onGetOrCreateNewConversation(final String conversationId) { final Context context = Factory.get().getApplicationContext(); UIIntents.get().launchConversationActivityWithParentStack(context, conversationId, mSmsBody); }
launchConversationActivityWithParentStack就是这个方法导致了back无法退回,其实现在UIIntentsImpl.java中:
@Override public void launchConversationActivityWithParentStack(final Context context, final String conversationId, final String smsBody) { final MessageData messageData = TextUtils.isEmpty(smsBody) ? null : MessageData.createDraftSmsMessage(conversationId, null, smsBody); TaskStackBuilder.create(context) .addNextIntentWithParentStack( getConversationActivityIntent(context, conversationId, messageData, false /* withCustomTransition */)) .startActivities(); }
做过通知栏的朋友可能很早就猜到原因了,就是TaskStackBuilder设置了回退栈的内容,虽然这是在Android 4.1就引入了的内容,以前还真没遇到:
<activity android:name=".ui.conversation.ConversationActivity" android:configChanges="orientation|screenSize|keyboardHidden" android:screenOrientation="user" android:windowSoftInputMode="stateHidden|adjustResize" android:theme="@style/BugleTheme.ConversationActivity" android:parentActivityName="com.android.messaging.ui.conversationlist.ConversationListActivity"> <meta-data android:name="android.support.PARENT_ACTIVITY" android:value="com.android.messaging.ui.conversationlist.ConversationListActivity" /> </activity>
parentActivityName设置为了ConversationListActivity. So,只要回退,肯定是回到短信列表页面。
- 6.0联系人跳转到短信的逻辑
- 跳转到拨号、联系人、短信界面
- 关于日历点击跳转以及短信点击跳转到指定联系人界面的一些记录
- 跳转到联系人
- Intent跳转到系统应用中的拨号界面、联系人界面、短信界面及其他
- 使用intent跳转到系统应用中的拨号界面、联系人界面、短信界面及其他
- Intent跳转到系统应用中的拨号界面、联系人界面、短信界面及其他
- Intent跳转到系统应用中的拨号界面、联系人界面、短信界面及其他
- Intent跳转到系统应用中的拨号界面、联系人界面、短信界面及其他
- Intent跳转到系统应用中的拨号界面、联系人界面、短信界面及其他
- Android开发之Intent跳转到系统应用中的拨号界面、联系人界面、短信界面
- Intent跳转到系统应用中的拨号界面、联系人界面、短信界面及其他
- Intent跳转到系统应用中的拨号界面、联系人界面、短信界面及其他
- Intent跳转到系统应用中的拨号界面、联系人界面、短信界面及其他
- Intent跳转到系统应用中的拨号界面、联系人界面、短信界面及其他
- Intent跳转到系统应用中的拨号界面、联系人界面、短信界面及其他
- Intent跳转到系统应用中的拨号界面、联系人界面、短信界面及其他
- 通过Intent跳转到系统应用中的activity:拨号界面、联系人界面、短信界面 .相机.录影机
- GCD详解
- Redis命令之Object
- 深入剖析消息中间件
- 多线程下载文件(支持暂停、取消、断点续传)
- svn中如何彻底删除一个文件
- 6.0联系人跳转到短信的逻辑
- 编译器 第一周
- NodeJS、NPM安装配置步骤(windows版本)
- 软件测试的几个误区
- 通信信号处理中为什么要分为I、Q两路
- iOS 解决Xcode引入第三方Framework 找不到头文件
- 喷水装置(一)(贪心)
- LINUX虚拟机实现与主机文件共享
- Nginx安装配置详解