Skip to content

Native android code that handles incoming calls

k00na edited this page Sep 27, 2020 · 1 revision

I'm quickly adding a sample of our native Android Activity that handles incoming calls. If you have some specific questions you can ask them here and we'll get back at you ASAP :)

package your.apps.id;

import android.app.Activity; import android.app.KeyguardManager; import android.app.NotificationManager; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.media.Ringtone; import android.media.RingtoneManager; import android.os.Bundle; import android.os.Vibrator; import android.util.Log; import android.view.View; import android.widget.TextView;

import com.google.android.gms.tasks.Continuation; import com.google.android.gms.tasks.Task; import com.google.firebase.firestore.DocumentReference; import com.google.firebase.firestore.DocumentSnapshot; import com.google.firebase.firestore.EventListener; import com.google.firebase.firestore.FirebaseFirestore; import com.google.firebase.firestore.FirebaseFirestoreException; import com.google.firebase.functions.FirebaseFunctions; import com.google.firebase.functions.HttpsCallableResult; import java.util.HashMap; import static android.os.Build.VERSION.SDK_INT; import static android.os.Build.VERSION_CODES; import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN; import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; import static android.view.WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;

public class IncomingCallActivity extends Activity { String callId; String callUuid; String callerHandle; int notificationId; Ringtone ringtone;

`Application application;`

`final private static String TAG = "IncomingCallActivity";`
`final private static long[] DEFAULT_VIBRATE_PATTERN = {0, 250, 250, 250};`

`@Override`
`protected void onCreate(Bundle savedInstanceState) {`
    `super.onCreate(savedInstanceState);`
    `try {`
        `Log.d("done", "Done, IncomingCallActivity, onCreate();");`
        `application = (Application)getApplication();`
        `Intent intent = getIntent();`

        `callId = intent.getStringExtra("your.apps.id.CALL_ID");`
        `callUuid = intent.getStringExtra("your.apps.id.CALL_UUID");`
        `callerHandle = intent.getStringExtra("your.apps.id.CALLER_HANDLE");`
        `notificationId = intent.getIntExtra("your.notification.callkeep.NOTIFICATION_ID", 0);`

        `if (SDK_INT >= VERSION_CODES.O_MR1) {`
            `setShowWhenLocked(true);`
            `setTurnScreenOn(true);`
        `} else {`
            `getWindow().addFlags(FLAG_SHOW_WHEN_LOCKED | FLAG_TURN_SCREEN_ON);`
        `}`

        `// Note that this shouldn't be needed on O_MR1 and higher, but `setTurnScreenOn` doesn't`
        `// seem to have any effect on our Samsung Galaxy A40.`
        `getWindow().addFlags(FLAG_TURN_SCREEN_ON);`

        `getWindow().addFlags(FLAG_KEEP_SCREEN_ON | FLAG_FULLSCREEN);`

        `String action = intent.getStringExtra("your.notification.callkeep.ACTION");`

        `switch (action != null ? action : "") {`
            `case "answer":`
                `onAnswer(null);`
                `break;`
            `case "decline":`
                `onDecline(null);`
                `break;`
            `default:`
                `setup();`
        `}`
    `} catch (Exception e){`
        `Log.d("done", "Done, IncomingCallActivity, onCreate " + e.toString());`
    `}`

`}`

`@Override`
`protected void onStart() {`
    `super.onStart();`
    `startRinging();`
`}`

`@Override`
`protected void onStop() {`
    `super.onStop();`
    `stopRinging();`
`}`

`@Override`
`public void onWindowFocusChanged(boolean hasFocus) {`
    `super.onWindowFocusChanged(hasFocus);`
    `if (hasFocus) {`
        `hideSystemUI();`
    `}`
`}`

`private void hideSystemUI() {`


    `try {`
        `// Enables regular immersive mode.`
        `// For "lean back" mode, remove SYSTEM_UI_FLAG_IMMERSIVE.`
        `// Or for "sticky immersive," replace it with SYSTEM_UI_FLAG_IMMERSIVE_STICKY`
        `Log.d("done", "done, IncomingCallActivity, hideSystemUI");`
        `View decorView = getWindow().getDecorView();`
        `decorView.setSystemUiVisibility(`
                `View.SYSTEM_UI_FLAG_IMMERSIVE`
                        `// Set the content to appear under the system bars so that the`
                        `// content doesn't resize when the system bars hide and show.`
                        `| View.SYSTEM_UI_FLAG_LAYOUT_STABLE`
                        `| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION`
                        `| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN`
                        `// Hide the nav bar and status bar`
                        `| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION`
                        `| View.SYSTEM_UI_FLAG_FULLSCREEN);`
    `}catch (Exception e){`
        `Log.e("done", "done, IncomingCallActivity, hidesystemui " + e.toString() );`
    `}`

`}`

`private void setup() {`
    `try {`
        `Log.d("done", "done, IncomingCallActivity, setup");`
        `setContentView(R.layout.activity_incoming_call);`

        `TextView caller = (TextView) findViewById(R.id.txt_caller);`
        `caller.setText(callerHandle);`

        `FirebaseFirestore db = FirebaseFirestore.getInstance();`
        `DocumentReference ref = db.collection("yourCallsCollection").document(callId);`

        `ref.addSnapshotListener(new EventListener<DocumentSnapshot>() {`
            `@Override`
            `public void onEvent(DocumentSnapshot snapshot, FirebaseFirestoreException e) {`
                `if (e != null) {`
                    `Log.e(TAG, "Listen to call snapshots failed", e);`
                    `return;`
                `}`

                `if (snapshot == null || !snapshot.exists() || snapshot.contains("answer")) {`
                    `dismissNotification();`
                    `finish();`
                `}`
            `}`
        `});`
    `} catch (Exception e){`
        `Log.e("done", "done, IncomingCallActivity, setup " + e.toString() );`
    `}`

`}`

`private void startRinging() {`
    `try {`
        `Log.d("done", "done, IncomingCallActivity, setup ");`
        `android.net.Uri toneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);`
        `ringtone = RingtoneManager.getRingtone(getApplicationContext(), toneUri);`
        `ringtone.play();`

        `Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);`
        `v.vibrate(DEFAULT_VIBRATE_PATTERN, 0);`
    `} catch (Exception e) {`
        `e.printStackTrace();`
    `}`
`}`

`private void stopRinging() {`

    `try {`
        `Log.d("done", "done, IncomingCallActivity, stopRinging ");`
        `if (ringtone != null) {`
            `ringtone.stop();`
        `}`
        `Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);`
        `v.cancel();`
    `} catch (Exception e){`
        `Log.e("done", "done, IncomingCallActivity, stop ringing " + e.toString() );`
    `}`


`}`

`private void dismissNotification() {`
    `try {`
        `Log.d("done", "done, IncomingCallActivity, dismissNotification ");`
        `NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);`
        `notificationManager.cancel(notificationId);`
    `} catch (Exception e){`
        `Log.e("done", "done, IncomingCallActivity, dismissNotification " + e.toString() );`
    `}`

`}`

`private void launchMainActivity() {`

    `try {`
        `Log.d("done", "done, IncomingCallActivity, dismissNotification ");`


        `SharedPreferences preferences = getApplicationContext().getSharedPreferences("FlutterSharedPreferences", Context.MODE_PRIVATE);`
        `preferences.edit().putBoolean("flutter." + callUuid + ":answer", true).commit();`

        `Log.d("Done", "SharedPreferences committed");`

        `String packageName = getApplicationContext().getPackageName();`
        `Intent launchIntent = getApplicationContext().getPackageManager().getLaunchIntentForPackage(packageName).cloneFilter();`

        `launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);`

        `Log.d("Done", "Starting activity");`
        `getApplicationContext().startActivity(launchIntent);`
        `Log.d("Done", "Activity started");`
    `} catch (Exception e){`
        `Log.e("done", "done, IncomingCallActivity, launchMainActivity " + e.toString() );`
    `}`

`}`

`public void onAnswer(View view) {`

    `try {`

        `Log.d("Done", "done, IncomingCallActivity, onAnswer started");`
        `dismissNotification();`

        `//1) check if MainActivity already present in stack`
        `//* if the app is already running it means we've answered trough notification`
        `if(application.isAppRunning()){`
            `CallAnsweredTroughNotification call = new CallAnsweredTroughNotification(this.callId, this.callUuid, this.callerHandle, this.notificationId);`
            `application.setCallAnsweredTroughNotification(call);`
            `Log.d("done", "IncomingCallActivity about to finish with call");`
            `finish();`
            `return;`
        `}`

        `KeyguardManager manager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);`

        `if (!manager.isKeyguardLocked()) {`
            `Log.d("Done", "Keyguard not locked, launch main activity");`

            `launchMainActivity();`
            `return;`
        `}`

        `if (SDK_INT >= VERSION_CODES.O) {`
            `manager.requestDismissKeyguard(this, new KeyguardManager.KeyguardDismissCallback() {`
                `@Override`
                `public void onDismissSucceeded() {`
                    `super.onDismissSucceeded();`
                    `launchMainActivity();`
                `}`

                `@Override`
                `public void onDismissError() {`
                    `launchMainActivity();`
                    `super.onDismissError();`
                `}`

                `@Override`
                `public void onDismissCancelled() {`
                    `launchMainActivity();`
                    `super.onDismissCancelled();`
                `}`
            `});`
        `} else {`
            `// Just launch the activity and rely on it setting `FLAG_DISMISS_KEYGUARD` to trigger keyguard unlock`
            `launchMainActivity();`
        `}`

    `} catch (Exception e){`
        `Log.e("done", "done, IncomingCallActivity, onAnswer " + e.toString() );`
    `}`

`}`

`public void onDecline(View view) {`
    `endCallOnFirebase();`
    `dismissNotification();`
    `finish();`
`}`


`void endCallOnFirebase(){`

    `FirebaseFunctions functions = FirebaseFunctions.getInstance("europe-west1");`
    `HashMap<String, Object> data = new HashMap();`
    `data.put("callId", callId);`
    `//* backend logic, we call cloud functions to end call`

`}`

}

Clone this wiki locally