Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ready to consume beta5. #24

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
33 changes: 12 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Get started with Voice on Android:

## Quickstart

To get started with the Quickstart application follow these steps. Steps 1-6 will allow you to make a call. The remaining steps 7-8 will enable push notifications using GCM.
To get started with the Quickstart application follow these steps. Steps 1-6 will allow you to make a call. The remaining steps 7-8 will enable push notifications using FCM.


1. [Open this project in Android Studio](#bullet1)
Expand All @@ -18,18 +18,14 @@ To get started with the Quickstart application follow these steps. Steps 1-6 wil
4. [Create a TwiML application](#bullet4)
5. [Configure your application server](#bullet5)
6. [Run the app](#bullet6)
7. [Generate google-services.json from the Google Developer Console](#bullet7)
8. [Add a Push Credential using your GCM Server API Key](#bullet8)
7. [Generate google-services.json](#bullet7)
8. [Add a Push Credential using your FCM Server API Key](#bullet8)
9. [Receiving an Incoming Notification](#bullet9)


### <a name="bullet1"></a>1. Open the project in Android Studio
<img width="700px" src="images/quickstart/import_project.png"/>

For now you will see an error in the console stating `Failed to retrieve GCM token` and this is because you don’t have a valid `google-services.json` file yet to enable push notifications. We will obtain it in step 7.

<img width="700px" src="images/quickstart/invalid_sender.png"/>

### <a name="bullet2"></a>2. Create a Voice API key

Go to the [API Keys page](https://www.twilio.com/console/voice/dev-tools/api-keys) and create a new API key.
Expand Down Expand Up @@ -92,31 +88,28 @@ Press the call button to connect to Twilio

<img height="500px" src="images/quickstart/voice_make_call.png">

### <a name="bullet7"></a>7. Generate `google-services.json` from the Google Developer Console

The Programmable Voice Android SDK uses Google Cloud Messaging push notifications to let your application know when it is receiving an incoming call. If you want your users to receive incoming calls, you’ll need to enable GCM in your application.
### <a name="bullet7"></a>7. Generate `google-services.json`

Follow the steps in the [Google Developers Console](https://developers.google.com/mobile/add). You must enter the correct Android package name, in this case `com.twilio.voice.quickstart` .
The Programmable Voice Android SDK uses Firebase Cloud Messaging push notifications to let your application know when it is receiving an incoming call. If you want your users to receive incoming calls, you’ll need to enable FCM in your application.

<img width="700px" src="images/quickstart/create_choose_app.png">
Follow the steps under **Use the Firebase Assistant** in the [Firebase Developers Guide](https://firebase.google.com/docs/android/setup). Once you connect and sync to Firebase successfully, you will be able to download the `google-services.json` for your application.

Login to Firebase console and make a note of generated `Server API Key` and `Sender ID` in your notepad. You will need them in the next step.

Save the generated `Server API Key` and `Sender ID` in your notepad. You will need them in the next step.
<img width="700px" src="images/quickstart/server_key_sender_id.png">"

<img width="700px" src="images/quickstart/save_server_api_key.png">"
Make sure the generated `google-services.json` is downloaded to the `/app` directory of the quickstart project to replace the existing `/app/google-services.json` .

Copy the generated `google-services.json` into the `/app` directory of the quickstart project to replace the existing `/app/google-services.json` .

### <a name="bullet8"></a>8. Add a Push Credential using your FCM `Server API Key`

### <a name="bullet8"></a>8. Add a Push Credential using your GCM `Server API Key`

You will need to store the GCM `Server API Key` with Twilio so that we can send push notifications to your app on your behalf. Once you store the API Key with Twilio it will get assigned a Push Credential SID so that you can later specify which key we should use to send push notifications.
You will need to store the FCM `Server API Key` with Twilio so that we can send push notifications to your app on your behalf. Once you store the API Key with Twilio, it will get assigned a Push Credential SID so that you can later specify which key we should use to send push notifications.

Go to the Push Credentials page and create a new Push Credential.

Paste in the `Server API Key` and press Save.

<img width="700px" src="images/quickstart/add_push_cred.png">"
<img width="700px" src="images/quickstart/add_fcm_push_cred.png">"

### <a name="bullet9"></a>9. Receiving an Incoming Notification

Expand All @@ -134,8 +127,6 @@ Once you’ve done that, restart the server so it uses the new configuration inf





## Reducing APK Size

Our library is built using native libraries. As a result, if you use the default gradle build you will generate an APK with all four architectures(armeabi-v7a, arm64-v8a, x86, x86_64) in your APK.
Expand Down
6 changes: 3 additions & 3 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ android {
}

dependencies {
testCompile 'junit:junit:4.12'
compile 'com.twilio:voice-android:2.0.0-beta4'
compile 'com.twilio:voice-android:2.0.0-beta5'
compile 'com.android.support:design:24.2.1'
compile 'com.android.support:appcompat-v7:24.2.1'
compile "com.google.android.gms:play-services-gcm:9.4.0"
compile 'com.squareup.retrofit:retrofit:1.9.0'
compile 'com.koushikdutta.ion:ion:2.1.8'
compile 'com.google.firebase:firebase-messaging:10.0.1'
testCompile 'junit:junit:4.12'
}

apply plugin: 'com.google.gms.google-services'
36 changes: 0 additions & 36 deletions app/google-services.json

This file was deleted.

6 changes: 3 additions & 3 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,23 +35,23 @@
</receiver>

<service
android:name=".gcm.VoiceGCMListenerService"
android:name=".fcm.VoiceGCMListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>

<service
android:name=".gcm.VoiceInstanceIDListenerService"
android:name=".fcm.VoiceInstanceIDListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID" />
</intent-filter>
</service>

<service
android:name=".gcm.GCMRegistrationService"
android:name=".fcm.GCMRegistrationService"
android:exported="false"></service>

<meta-data
Expand Down
69 changes: 8 additions & 61 deletions app/src/main/java/com/twilio/voice/quickstart/VoiceActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,13 @@
import android.view.View;
import android.widget.Chronometer;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.firebase.iid.FirebaseInstanceId;
import com.twilio.voice.Call;
import com.twilio.voice.CallException;
import com.twilio.voice.CallInvite;
import com.twilio.voice.RegistrationException;
import com.twilio.voice.RegistrationListener;
import com.twilio.voice.VoiceClient;
import com.twilio.voice.quickstart.gcm.GCMRegistrationService;
import com.twilio.voice.Voice;

import java.util.HashMap;

Expand All @@ -46,7 +44,6 @@ public class VoiceActivity extends AppCompatActivity {
private static final String TWILIO_ACCESS_TOKEN = "TWILIO_ACCESS_TOKEN";

private static final int MIC_PERMISSION_REQUEST_CODE = 1;
private static final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;

private boolean speakerPhone;
private AudioManager audioManager;
Expand All @@ -69,10 +66,8 @@ public class VoiceActivity extends AppCompatActivity {
public static final String INCOMING_CALL_NOTIFICATION_ID = "INCOMING_CALL_NOTIFICATION_ID";
public static final String ACTION_INCOMING_CALL = "INCOMING_CALL";

public static final String KEY_GCM_TOKEN = "GCM_TOKEN";

private NotificationManager notificationManager;
private String gcmToken;
private AlertDialog alertDialog;
private CallInvite activeCallInvite;
private Call activeCall;
Expand Down Expand Up @@ -123,8 +118,6 @@ protected void onCreate(Bundle savedInstanceState) {
*/
if (!checkPermissionForMicrophone()) {
requestPermissionForMicrophone();
} else {
startGCMRegistration();
}
}

Expand All @@ -134,13 +127,6 @@ protected void onNewIntent(Intent intent) {
handleIncomingCallIntent(intent);
}

private void startGCMRegistration() {
if (checkPlayServices()) {
Intent intent = new Intent(this, GCMRegistrationService.class);
startService(intent);
}
}

private RegistrationListener registrationListener() {
return new RegistrationListener() {
@Override
Expand All @@ -163,12 +149,6 @@ public void onConnected(Call call) {
activeCall = call;
}

@Override
public void onDisconnected(Call call) {
resetUI();
Log.d(TAG, "Disconnect");
}

@Override
public void onDisconnected(Call call, CallException error) {
resetUI();
Expand Down Expand Up @@ -227,7 +207,7 @@ private void handleIncomingCallIntent(Intent intent) {

if (intent != null && intent.getAction() != null && intent.getAction() == ACTION_INCOMING_CALL) {
activeCallInvite = intent.getParcelableExtra(INCOMING_CALL_INVITE);
if (!activeCallInvite.isCancelled()) {
if (activeCallInvite != null && (activeCallInvite.getState() == CallInvite.State.PENDING)) {
SoundPoolManager.getInstance(this).playRinging();
alertDialog = createIncomingCallDialog(VoiceActivity.this,
activeCallInvite,
Expand Down Expand Up @@ -260,20 +240,7 @@ private class VoiceBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(ACTION_SET_GCM_TOKEN)) {
String gcmToken = intent.getStringExtra(KEY_GCM_TOKEN);
Log.i(TAG, "GCM Token : " + gcmToken);
VoiceActivity.this.gcmToken = gcmToken;
if(gcmToken == null) {
Snackbar.make(coordinatorLayout,
"Failed to get GCM Token. Unable to receive calls",
Snackbar.LENGTH_LONG).show();
}
callActionFab.show();
if (VoiceActivity.this.gcmToken != null) {
register();
}
} else if (action.equals(ACTION_INCOMING_CALL)) {
if (action.equals(ACTION_INCOMING_CALL)) {
/*
* Handle the incoming call invite
*/
Expand Down Expand Up @@ -319,14 +286,15 @@ public static AlertDialog createIncomingCallDialog(Context context, CallInvite c
* Register your GCM token with Twilio to enable receiving incoming calls via GCM
*/
private void register() {
VoiceClient.register(getApplicationContext(), TWILIO_ACCESS_TOKEN, gcmToken, registrationListener);
final String fcmToken = FirebaseInstanceId.getInstance().getToken();
Voice.register(getApplicationContext(), TWILIO_ACCESS_TOKEN, fcmToken, registrationListener);
}

private View.OnClickListener callActionFabClickListener() {
return new View.OnClickListener() {
@Override
public void onClick(View v) {
activeCall = VoiceClient.call(getApplicationContext(), TWILIO_ACCESS_TOKEN, twiMLParams, callListener);
activeCall = Voice.call(getApplicationContext(), TWILIO_ACCESS_TOKEN, twiMLParams, callListener);
setCallUI();
}
};
Expand Down Expand Up @@ -433,33 +401,12 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis
if (requestCode == MIC_PERMISSION_REQUEST_CODE && permissions.length > 0) {
boolean granted = true;
if (granted) {
startGCMRegistration();
register();
} else {
Snackbar.make(coordinatorLayout,
"Microphone permissions needed. Please allow in your application settings.",
Snackbar.LENGTH_LONG).show();
}
}
}

/**
* Check the device to make sure it has the Google Play Services APK. If
* it doesn't, display a dialog that allows users to download the APK from
* the Google Play Store or enable it in the device's system settings.
*/
private boolean checkPlayServices() {
GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
int resultCode = apiAvailability.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (apiAvailability.isUserResolvableError(resultCode)) {
apiAvailability.getErrorDialog(this, resultCode, PLAY_SERVICES_RESOLUTION_REQUEST)
.show();
} else {
Log.e(TAG, "This device is not supported.");
finish();
}
return false;
}
return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.twilio.voice.quickstart.fcm;

import android.util.Log;

import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;


public class AppFirebaseInstanceIDService extends FirebaseInstanceIdService {

private static final String TAG = "AppFirebaseInsIDSvc";

/**
* Called if InstanceID token is updated. This may occur if the security of
* the previous token had been compromised. Note that this is called when the InstanceID token
* is initially generated so this is where you would retrieve the token.
*/
// [START refresh_token]
@Override
public void onTokenRefresh() {
// Get updated InstanceID token.
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
Log.d(TAG, "Refreshed token: " + refreshedToken);

// If you want to send messages to this application instance or
// manage this apps subscriptions on the server side, send the
// Instance ID token to your app server.
sendRegistrationToServer(refreshedToken);
}
// [END refresh_token]

/**
* Persist token to third-party servers.
*
* Modify this method to associate the user's FCM InstanceID token with any server-side account
* maintained by your application.
*
* @param token The new token.
*/
private void sendRegistrationToServer(String token) {
// TODO: Implement this method to send token to your app server.
}
}