How to start Viber call from an Android app [new v

2019-01-23 18:46发布

问题:

A while ago I created this post, and my colleague and I have found two different answers to it (both of them worked):

  1. First solution was to use

    Intent callIntent = new Intent("android.intent.action.CALL_PRIVILEGED");

    which would open new window offering for call to be made by all possible means for placing call - in this particular case, they were Dialer and Viber and Skype (or any other method added later).

  2. Second solution was to explicitly call Viber and place a phone number to be called as well

    Intent viberCallIntent = new Intent("com.viber.voip.action.CALL"); viberCallIntent.setType("vnd.android.cursor.item/vnd.com.viber.voip.call"); viberCallIntent.setData(Uri.parse("tel:" + dialNumber)); viberCallIntent.putExtra("external_call", true); viberCallIntent.putExtra("contact_id", -1L); startActivity(viberCallIntent);

Since last Viber update (we noticed it yesterday), none of those methods work. First one just calls using Skype, not even offering Dialer (!?!), but if Skype is not installed then it will fall back to Dialer and place call. Second one crashes claiming that there is no Activity found to handle Intent?

Any idea what is happening and how could this be resolved ?

Error log is as follows:

01-27 17:35:03.794: E/AndroidRuntime(7738): FATAL EXCEPTION: main
01-27 17:35:03.794: E/AndroidRuntime(7738): android.content.ActivityNotFoundException: No Activity found to handle Intent { act=com.viber.voip dat=tel:xxxxxxxxx (has extras) }
01-27 17:35:03.794: E/AndroidRuntime(7738):     at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1628)
01-27 17:35:03.794: E/AndroidRuntime(7738):     at android.app.Instrumentation.execStartActivity(Instrumentation.java:1423)
01-27 17:35:03.794: E/AndroidRuntime(7738):     at android.app.Activity.startActivityForResult(Activity.java:3388)
01-27 17:35:03.794: E/AndroidRuntime(7738):     at android.app.Activity.startActivityForResult(Activity.java:3349)
01-27 17:35:03.794: E/AndroidRuntime(7738):     at android.app.Activity.startActivity(Activity.java:3584)
01-27 17:35:03.794: E/AndroidRuntime(7738):     at android.app.Activity.startActivity(Activity.java:3552)
01-27 17:35:03.794: E/AndroidRuntime(7738):     at rs.limitline.maxitaxins.MainActivity.callViber(MainActivity.java:96)
01-27 17:35:03.794: E/AndroidRuntime(7738):     at rs.limitline.maxitaxins.MainActivity.onClick(MainActivity.java:186)
01-27 17:35:03.794: E/AndroidRuntime(7738):     at android.view.View.performClick(View.java:4212)
01-27 17:35:03.794: E/AndroidRuntime(7738):     at android.view.View$PerformClick.run(View.java:17476)
01-27 17:35:03.794: E/AndroidRuntime(7738):     at android.os.Handler.handleCallback(Handler.java:800)
01-27 17:35:03.794: E/AndroidRuntime(7738):     at android.os.Handler.dispatchMessage(Handler.java:100)
01-27 17:35:03.794: E/AndroidRuntime(7738):     at android.os.Looper.loop(Looper.java:194)
01-27 17:35:03.794: E/AndroidRuntime(7738):     at android.app.ActivityThread.main(ActivityThread.java:5431)
01-27 17:35:03.794: E/AndroidRuntime(7738):     at java.lang.reflect.Method.invokeNative(Native Method)
01-27 17:35:03.794: E/AndroidRuntime(7738):     at java.lang.reflect.Method.invoke(Method.java:525)
01-27 17:35:03.794: E/AndroidRuntime(7738):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
01-27 17:35:03.794: E/AndroidRuntime(7738):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
01-27 17:35:03.794: E/AndroidRuntime(7738):     at dalvik.system.NativeStart.main(Native Method)

[UPDATE] This shows as error as well:

01-27 19:46:56.704: D/Greska(19822): Permission Denial: starting Intent { act=com.viber.voip.action.CALL dat=tel:xxxxxxxxx cmp=com.viber.voip/com.viber.service.OutgoingCallBroadcaster (has extras) } from ProcessRecord{416c41b8 19822:rs.limitline.maxitaxins/u0a10065} (pid=19822, uid=10065) not exported from uid 10147

回答1:

According to Viber's manifest, there is activity "com.viber.voip.phone.PhoneActivity" that is responsible for action "com.viber.voip.action.CALL". In new version of Viber (4.2.1.1) this activity is marked by android:exported="false". As result, it's not possible anymore to start this activity from external applications...

Edit

This code opens welcome screen for specified contact

String sphone = "12345678";
Uri uri = Uri.parse("tel:" + Uri.encode(sphone)); 
Intent intent = new Intent("android.intent.action.VIEW");
intent.setClassName("com.viber.voip", "com.viber.voip.WelcomeActivity");
intent.setData(uri); 
context.startActivity(intent);

but user should click button "free call" to start call.



回答2:

It is possible to call per Viber direct (without WelcomeActivity), but user should have this number in Contacts.

public void callToViberContact(String phoneNumber, Context context) {
    Uri uri = getUriFromPhoneNumber(phoneNumber, context);
    if (uri != null) {
        Intent intent = new Intent("android.intent.action.VIEW");
        intent.setClassName("com.viber.voip", "com.viber.voip.SystemDialogActivityPublic");
        intent.setData(uri);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
    } else {
        Toast.makeText(context, "Number is not in Viber Contacts List", Toast.LENGTH_LONG).show();
    }
}

private Uri getUriFromPhoneNumber(String phoneNumber, Context context) {
    Uri uri = null;
    String contactId = getContactIdByPhoneNumber(phoneNumber, context);
    if (!TextUtils.isEmpty(contactId)) {
        Cursor cursor = context.getContentResolver().query(
                ContactsContract.Data.CONTENT_URI, new String[]{ContactsContract.Data._ID},
                ContactsContract.Data.DATA2 + "=? AND " + ContactsContract.Data.CONTACT_ID + " = ?",
                new String[]{"Viber", contactId}, null);
        if (cursor != null) {
            while (cursor.moveToNext()){
                String id = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.Data._ID));
                if (!TextUtils.isEmpty(id)) {
                    uri = Uri.parse(ContactsContract.Data.CONTENT_URI + "/" + id);
                    break;
                }
            }
            cursor.close();
        }
    }
    return uri;
}

private String getContactIdByPhoneNumber(String phoneNumber, Context context) {
    ContentResolver contentResolver = context.getContentResolver();
    String contactId = null;
    Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));

    String[] projection = new String[]{ContactsContract.PhoneLookup._ID};

    Cursor cursor =
            contentResolver.query(
                    uri,
                    projection,
                    null,
                    null,
                    null);

    if (cursor != null) {
        while (cursor.moveToNext()) {
            contactId = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.PhoneLookup._ID));
        }
        cursor.close();
    }
    return contactId;
}

READ_CONTACTS permission is required. Don't forget to add in Manifest:

<uses-permission android:name="android.permission.READ_CONTACTS" />


回答3:

String uriString = "content://com.android.contacts/data/" + _id;

Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse(uriString));
intent.setPackage(PKG_VIBER);
startActivity(intent);

_id can be queried from contacts2.db(Column ContactsContract.Data._ID)



标签: android viber