如何在各种流行的聊天/社交网络应用程序中打开特定的联系人聊天屏幕?

Posted

技术标签:

【中文标题】如何在各种流行的聊天/社交网络应用程序中打开特定的联系人聊天屏幕?【英文标题】:How to open specific contact chat screen in various popular chat/social-networks apps? 【发布时间】:2016-06-28 14:14:46 【问题描述】:

背景

我发现有一种方法可以在 WhatsApp 上打开特定的联系人对话屏幕,here

不仅如此,我还发现一个名为“Drupe”的应用也能做到这一点,甚至更多:

https://lh3.googleusercontent.com/EQrs1jplMlP8SkOTdpqT4NzmgzGa5Wz2qageG1Pkjc6rKg0HBb-rwlOVW07_G7bAWgo=h900

问题

我找不到任何官方API可以这样打开它,所以我不确定它有多安全。

我找到了 SDK,但没有找到意图说明。

问题

我想了解更多关于各种社交网络和聊天应用程序可用的信息:

WhatsApp Facebook 信使 Viber 行 电报 环聊

可能的特征可能是:

打开联系人的对话,当输入的是他的电话号码时 有一个可以在新屏幕中发送的新文本 对于 Facebook,也许还可以使用该人的 Facebook-ID(这意味着这是输入)而不是电话号码来打开。

这些功能是否适用于这些社交网络和聊天应用程序?

【问题讨论】:

为什么要投票结束这个?对于whatsapp 可以,但对于其他人就不行? 对于 Facebook 没有官方的方式。 Facebook 平台政策也不允许预填充文本 【参考方案1】:

对于 Facebook 信使,我找到了这个(来自 https://developers.facebook.com/docs/messenger-platform/discovery/m-me-links#format):

final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://m.me/" + facebookId));

它有效,但我想知道是否有其他方法可以访问它(例如使用电话号码)。


对于 WhatsApp,我发现了这个(来自 here):

    final String formattedPhoneNumber = getFormattedPhoneNumber(this, phone);
    final String contactId = getContactIdFromPhoneNumber(phone);
    final String contactMimeTypeDataId = getContactMimeTypeDataId(contactId, "vnd.android.cursor.item/vnd.com.whatsapp.profile");
    if (contactMimeTypeDataId != null) 
        intent = new Intent(Intent.ACTION_SENDTO, Uri.parse("smsto:" + formattedPhoneNumber));
        intent.setPackage("com.whatsapp");
     else
        Toast.makeText(this, "cannot find this contact on whatsapp", Toast.LENGTH_SHORT).show();

public static String getFormattedPhoneNumber(Context context, String input) 
    final PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance();
    String normalizedPhone = input.replaceAll("[^0-9+]", "");
    try 
        TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        String countryCode = tm.getSimCountryIso();
        final PhoneNumber phoneNumber = phoneNumberUtil.parse(normalizedPhone, countryCode.toUpperCase());
        final String formattedPhoneNumber = phoneNumberUtil.format(phoneNumber, PhoneNumberFormat.E164).replaceAll("[^0-9]", "");
        return formattedPhoneNumber;
     catch (NumberParseException e) 
        e.printStackTrace();
    
    return null;


private String getContactIdFromPhoneNumber(String phone) 
    if (TextUtils.isEmpty(phone))
        return null;
    final Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phone));
    final ContentResolver contentResolver = getContentResolver();
    final Cursor phoneQueryCursor = contentResolver.query(uri, new String[]PhoneLookup._ID, null, null, null);
    if (phoneQueryCursor != null) 
        if (phoneQueryCursor.moveToFirst()) 
            String result = phoneQueryCursor.getString(phoneQueryCursor.getColumnIndex(PhoneLookup._ID));
            phoneQueryCursor.close();
            return result;
        
        phoneQueryCursor.close();
    
    return null;


public String getContactMimeTypeDataId(@NonNull Context context, String contactId, @NonNull String mimeType) 
    if (TextUtils.isEmpty(mimeType))
        return null;
    ContentResolver cr = context.getContentResolver();
    Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI, new String[]Data._ID, Data.MIMETYPE + "= ? AND "
            + ContactsContract.Data.CONTACT_ID + "= ?", new String[]mimeType, contactId, null);
    if (cursor == null)
        return null;
    if (!cursor.moveToFirst()) 
        cursor.close();
        return null;
    
    String result = cursor.getString(cursor.getColumnIndex(Data._ID));
    cursor.close();
    return result;

它可以工作,但它不会添加消息。它也可能会说联系人没有 WhatsApp。


对于 Viber,我找到了这个(来自 here):

        final String contactId = getContactIdFromPhoneNumber(phone);
        final String contactMimeTypeDataId = getContactMimeTypeDataId(contactId, "vnd.android.cursor.item/vnd.com.viber.voip.viber_number_message");
        if (contactMimeTypeDataId != null) 
            intent = new Intent(Intent.ACTION_VIEW, Uri.parse("content://com.android.contacts/data/" + contactMimeTypeDataId));
            intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET | Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
            intent.setPackage("com.viber.voip");
         else 
            intent = new Intent("android.intent.action.VIEW", Uri.parse("tel:" + Uri.encode(formattedPhoneNumber)));
            intent.setClassName("com.viber.voip", "com.viber.voip.WelcomeActivity");
        

private String getContactIdFromPhoneNumber(String phone) 
    final Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phone));
    final ContentResolver contentResolver = getContentResolver();
    final Cursor phoneQueryCursor = contentResolver.query(uri, new String[]PhoneLookup._ID, null, null, null);
    if (phoneQueryCursor != null) 
        if (phoneQueryCursor.moveToFirst()) 
            String result = phoneQueryCursor.getString(phoneQueryCursor.getColumnIndex(PhoneLookup._ID));
            phoneQueryCursor.close();
            return result;
        
        phoneQueryCursor.close();
    
    return null;


对于环聊,它似乎与 Viber 类似,但具有以下 mimetype:“vnd.android.cursor.item/vnd.googleplus.profile.comm”。然而,它不起作用,因为它可能需要额外的步骤(设置 G+ 以保持联系人更新并让联系人进入 G+ 圈子)。但是,我以某种方式成功打开了一个人的视频聊天:

        intent =new Intent(Intent.ACTION_VIEW,Uri.parse("content://com.android.contacts/data/"+contactMimeTypeDataId));
        intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT |Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET |Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);

对于 Telegram,有人 (here) 建议使用下一个代码,但它不起作用:

        intent = new Intent(android.content.Intent.ACTION_SENDUri.parse("http://telegram.me/"+profile)));
        intent.setPackage("org.telegram.messenger");

对于 Line,我找到了这些(基于 herehere),但没有一个工作:

    Intent intent = new Intent("jp.naver.line.android.intent.action.LINESHORTCUT");
    intent.putExtra("shortcutType", "chatmid");
    intent.putExtra("shortcutTargetId", target);
    intent.putExtra("shortcutTargetName", "");
    intent.putExtra("shortcutFromOS", false);
    startActivity(intent);

Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse("line://msg/text/" + getMongon()));

skype:这个有效(从各种链接中找到,例如here):

        final String skypeUserName = getSkypeUserName(phone);
        intent = new Intent(Intent.ACTION_VIEW, Uri.parse("skype:" + skypeUserName + "?chat"));

    public String getSkypeUserName(String phoneNumber) 
        if (TextUtils.isEmpty(phoneNumber))
            return null;
        ContentResolver cr = getContentResolver();
        final Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
        Cursor cursor = cr.query(uri, new String[]PhoneLookup.LOOKUP_KEY, null, null, null);
        if (cursor == null)
            return null;
        final Set<String> contactKeys = new HashSet<>();
        // get contact keys
        
            final int contactKeyIdx = cursor.getColumnIndex(PhoneLookup.LOOKUP_KEY);
            for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) 
                String contactKey = cursor.getString(contactKeyIdx);
                contactKeys.add(contactKey);
            
            cursor.close();
        
        if (contactKeys.isEmpty())
            return null;
        //get raw ids
        final Set<String> contactRawIdsSet = new HashSet<>();
        
            final StringBuilder sb = new StringBuilder();
            for (int i = 0; i < contactKeys.size(); ++i)
                sb.append(sb.length() == 0 ? "?" : ",?");
            String inParameters = sb.toString();
            final String[] selectionArgs = contactKeys.toArray(new String[contactKeys.size()]);
            cursor = cr.query(ContactsContract.Data.CONTENT_URI, new String[]ContactsContract.Data.RAW_CONTACT_ID, ContactsContract.Data.LOOKUP_KEY + " IN (" + inParameters + ")", selectionArgs, null);
            if (cursor == null)
                return null;
            final int rawContactColIdx = cursor.getColumnIndex(ContactsContract.Data.RAW_CONTACT_ID);
            for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) 
                String rawContactId = cursor.getString(rawContactColIdx);
                contactRawIdsSet.add(rawContactId);
            
            cursor.close();
        
        if (contactRawIdsSet.isEmpty())
            return null;
        //find the skype name
        //TODO think of a better way to query, as it looks weird to search within a set of ids...
        final StringBuilder sb = new StringBuilder();
        for (int i = 0; i < contactRawIdsSet.size(); ++i)
            sb.append(sb.length() == 0 ? "?" : ",?");
        String inParameters = sb.toString();
        final String[] selectionArgs = new String[2 + contactRawIdsSet.size()];
        selectionArgs[0] = "com.skype.contacts.sync";
        selectionArgs[1] = "vnd.android.cursor.item/name";
        int i = 2;
        for (String rawId : contactRawIdsSet)
            selectionArgs[i++] = rawId;
        cursor = cr.query(ContactsContract.Data.CONTENT_URI, new String[]RawContacts.SOURCE_ID, ContactsContract.RawContacts.ACCOUNT_TYPE + " = ? AND " + Data.MIMETYPE + " = ? AND " +
                ContactsContract.Data.CONTACT_ID + " IN (" + inParameters + ")", selectionArgs, null);
        if (cursor == null)
            return null;
        if (!cursor.moveToFirst()) 
            cursor.close();
            return null;
        
        String result = cursor.getString(cursor.getColumnIndex(RawContacts.SOURCE_ID));
        cursor.close();
        return result;
    

【讨论】:

谢谢,但是如果用户从未登录 FB messenger 应用程序,那么它会导航到 messenger 登录过程,但最后它不会打开我必须与之聊天的特定用户聊天窗口。如何处理这种情况? @SuhasBachewar 嗯,有道理,不是吗?为了聊天,你必须先登录......无论如何,因为这是在FB的聊天应用程序中,我认为你无能为力。你或许能知道FB的聊天应用之前有没有被打开过,但不知道你能不能检查它是否已经登录。 有点跑题了......你知道如何在我的应用程序中以编程方式发起 Messenger Audio 通话吗? 如果 facebookId 不是您的用户 ID,那么这一切都会像您一样启动 Messenger;它不会让您与您打算聊天的人聊天。你仍然需要找到那个人,这就是问题所在。例如,如果您只知道姓名,则可以按姓名搜索该人,但可能有一千个人同名。 @FractalBob 这不是“你的用户 ID”。这是您希望联系的人。【参考方案2】:

对我有用

 try 

            String toNumber = "+91 8*******36"; // contains spaces.
            toNumber = toNumber.replace("+", "").replace(" ", "");

 Intent sendIntent = new Intent(Intent.ACTION_SENDTO,Uri.parse("smsto:" + "" + toNumber + "?body=" + ""));
 sendIntent.putExtra(Intent.EXTRA_TEXT, "hello");
 sendIntent.setPackage("com.whatsapp");
 startActivity(sendIntent);

        
        catch (Exception e)
            Toast.makeText(getActivity(),"it may be you dont have whats app",Toast.LENGTH_LONG).show();

        

【讨论】:

这是我写的一部分。我添加了对联系人不存在的情况的保护。 如果您的联系人列表中添加了“toNumber”,但它会自动添加您 你确定吗?我记得它没有。相反,我记得它会询问您是否要添加它。 我发帖后检查了 现在试过了。不会自动添加。这就是我添加检查的原因,以避免出现此对话框。它显示一个对话框,要求邀请或发送短信。该对话框有很长的文字:“您似乎正试图向未在 WhatsApp 注册的电话号码发送 WhatsApp 消息。您的联系人必须安装 WhatsApp 才能在 WhatsApp 中聊天。按“短信”发送正常向此联系人发送短信,或按“邀请”以通过短信发送 WhatsApp 邀请”。【参考方案3】:

这里的其他帖子有很好的信息。我想为LINE添加,因为很多地方缺少信息。

String userId = findUserId();
String sendText = "line://ti/p/~" + userId;
Intent intent = null;
try 
    intent = Intent.parseUri(sendText, Intent.URI_INTENT_SCHEME);
 catch (URISyntaxException e) 
    e.printStackTrace();

startActivity(intent);

【讨论】:

你如何得到userId ?它的代码是什么?是用户的电话号码吗? userId是你个人在app中设置的id。这是您选择的东西,以便您可以送给朋友。如果您在应用程序中搜索某人,则使用您创建的 set userId 或名字和姓氏。代码中的userId与您在应用中设置的userId一致。 你的意思是userId是那个人给自己取的昵称?如果是这样,如果多个昵称具有相同的昵称怎么办?你能用一些代码得到这个应用程序所有人的userId吗? findUserId的代码是什么? 该应用程序使您必须拥有唯一的ID。如果有人已经在使用该 ID,则您无法将其注册到您的帐户中。原帖说你想“打开一个联系人的对话”。就是这样。它将与联系人一起进入屏幕,您只需点击联系人即可打开对话。至于“findUserId()”如果是你想要的。这只是打开应用程序所需要做的一个示例。据我所知,获取该 userId 的唯一方法是询问朋友,他们会告诉你。 所以你说不可能知道用户的id,用code?仅通过手动检查,作为用户,id 是什么?它在哪里找到?在应用中?

以上是关于如何在各种流行的聊天/社交网络应用程序中打开特定的联系人聊天屏幕?的主要内容,如果未能解决你的问题,请参考以下文章

婚恋交友网站开发社交聊天平台代码分享

婚恋交友网站开发社交聊天平台代码分享

如何在 Django 中设置访问受限的聊天室?也就是说,我们只允许来自在特定聊天室中注册的用户的连接?

求一个可以代替哇嘎的能用的软件

图的表示:如何存储微博、微信等社交网络中的好友关系?

BCP搭建制作开平台