How to open specific contact chat screen in various popular chat/social-networks apps?
Asked Answered
R

3

4

Background

I've found that there is a way to open a specific contact conversation screen on WhatsApp, here .

Not only that, but I've found that an app called "Drupe" does the same, and maybe even more :

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

The problem

I can't find any official API of opening it this way, so I'm not sure how safe it is.

I've found SDKs, but not intents instructions.

The questions

I'd like to know more about what's available for various social-networks and chatting apps :

  • WhatsApp
  • Facebook Messenger
  • Viber
  • Line
  • Telegram
  • Hangouts

Possible features may be:

  • open the conversation of a contact, when input is his phone number
  • have a new text that will be ready to be sent in the new screen
  • for Facebook, maybe also be able to open using the Facebook-ID of the person (meaning this is the input), instead of a phone number.

Are such features available for each of those social networks and chatting apps?

Roselani answered 13/3, 2016 at 15:50 Comment(2)
Why the vote for closing this? For whatsapp it's ok, but for others it's not?Roselani
For Facebook there is no official way. And prefilling the text is also not allowed by Facebook Platform PolicySavitt
R
22

For Facebook-messenger, I've found this (from 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));

It works, but I wonder if there is another way to access it (using phone number, for example).


For WhatsApp, I've found this (from 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;
}

It works, but it doesn't add the message. It also might say the contact doesn't have WhatsApp.

It's also possible to just use the phone number, as I wrote here.


For Viber, I've found this (from 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;
}

For Hangouts, it seems it's similar to Viber, but with this mimetype: "vnd.android.cursor.item/vnd.googleplus.profile.comm". Yet, it doesn't work as it probably needs additional steps (setting G+ to keep contacts updated and have the contacts in the G+ circles). However, I've somehow succeeded to open the video chat of a person:

        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);

For Telegram, someone (here) suggested using the next code, but it doesn't work:

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

It's also possible to just use the phone number, as I wrote here.

For Line, I've found these (based on here and here), but none work:

    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: this one works (found from various links, here, for example):

        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;
    }
Roselani answered 14/3, 2016 at 9:8 Comment(8)
Thanks, but if user never login in FB messenger app, then it navigate to messenger login process but at last it wont open the particular user chat window with whom I have to chat .How to handle such scenario?Adjourn
@SuhasBachewar Well, it makes sense no? In order to chat, you have to login first... Anyway, since this is within FB's chat app, I don't think you can do anything about it. You might be able to know if FB's chat app was opened before, but I don't know if you can check if it's logged in.Roselani
A bit off topic... Do you how I could initiate a Messenger Audio call programmatically from within my app?Hateful
If facebookId is NOT your user ID, all this will do is launch Messenger as you; it will not enable you to chat with the person you're intending to. You still need to locate that person and therein lies the problem. For example, if you only know the name, you can search for that person by name, but there could be a thousand people having the same name.Steato
@Steato It's not "your user ID". It's of the person you wish to contact with.Roselani
any idea about Google dou video calling intent the one truecaller is using?Argumentation
@AnwarKamal No, but if you do, could be nice if you publish it here ...Roselani
@Webserveis I already wrote that it didn't work for me. If you have a better one, please write it.Roselani
S
0

it works for me

 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();

        }
Stellastellar answered 27/9, 2017 at 11:36 Comment(8)
This is a part of what I wrote. I added protection against the case that the contact doesn't exist there.Roselani
if "toNumber" is added or not in your contact list yet it will add you automaticallyStellastellar
Are you sure? I remember that it doesn't. Instead, I remember it asks you if you wish to add it.Roselani
i checked then after i have postedStellastellar
Tried it now. Doesn't automatically add. That's why I added the check, to avoid this dialog. It shows a dialog asking to invite or send SMS. The dialog has a long text : "You seem to be trying to send a WhatsApp message to a phone number that is not registered with WhatsApp. Your contact must have WhatsApp installed in order to chat in WhatsApp. Press 'SMS' to send a normal SMS to this contact, or press 'invite' to send WhatsApp invitation via SMS".Roselani
without whats app how it will add no. in whats app 's contactStellastellar
Let us continue this discussion in chat.Stellastellar
That's why the condition is needed. To ensure you can reach this contact, you have to check that it's a WhatsApp-contact. Otherwise you can reach this dialog and can't really chat with this person.Roselani
P
0

Other posts here have good information. I wanted to add for LINE because the information is lacking in many places.

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);
Precondition answered 17/11, 2017 at 20:26 Comment(6)
How do you get userId ? What's the code for it? Is it the phone number of the user?Roselani
The userId is the id that you set in the app personally. It's something that you choose so that you can give to friends. If you search for someone in the app it's by the set userId that you create, or first and last name. The userId in the code is the same as the userId that you set in the app.Precondition
You mean userId is the nickname the person chose for himself? If so, what happens if multiple ones have the same nickname? Can you get the userId of all of the people of this app, using some code? What is the code of findUserId ?Roselani
The app makes it so that you have to have a unique id. If someone is already using that id then you can't register it for your account. The original post said that you would like to "open the conversation of a contact". This is how. It will go to a screen with the contact and all you have to do it tap on the contact to open the conversation. As for "findUserId()" if would be what ever you want it to be. It was just an example of what you would need to do to open the app. The only way that I know of to get that userId is to ask a friend, and they will tell you.Precondition
So you say it's impossible to know the id of the user, using code? Only by manually checking, as a user, what's the id? Where is it found? In the app?Roselani
Not that it's impossible, just that this is not what the code does. I personally don't know how if there is in fact a way. Yes the ID is found in the app. If your friend wants you to find you, he gives it to you and then you are friends.Precondition

© 2022 - 2024 — McMap. All rights reserved.