From 69b1eb2f7489060350ecdc711b5cb7a4fd1503ea Mon Sep 17 00:00:00 2001 From: Margaux Clerc Date: Thu, 10 Mar 2016 17:30:08 +0100 Subject: [PATCH] Add android permission support for sdk 23 --- build.gradle | 2 +- res/values/strings.xml | 2 +- src/org/linphone/CallActivity.java | 85 +++++++++++++++---- src/org/linphone/LinphoneActivity.java | 72 ++++++++++++++-- src/org/linphone/LinphonePreferences.java | 16 ++++ .../linphone/assistant/AssistantActivity.java | 35 ++++++-- 6 files changed, 180 insertions(+), 32 deletions(-) diff --git a/build.gradle b/build.gradle index afc438434..1bad48fd3 100644 --- a/build.gradle +++ b/build.gradle @@ -13,7 +13,7 @@ dependencies { } android { - compileSdkVersion 22 + compileSdkVersion 23 buildToolsVersion "20.0.0" sourceSets { diff --git a/res/values/strings.xml b/res/values/strings.xml index 2b3237b5c..ef801b322 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -346,7 +346,7 @@ Default account Deselect all Select all - Select all + Delete selection First name Last name Back to call diff --git a/src/org/linphone/CallActivity.java b/src/org/linphone/CallActivity.java index e8e51c5ef..8a3ab4e73 100644 --- a/src/org/linphone/CallActivity.java +++ b/src/org/linphone/CallActivity.java @@ -32,11 +32,13 @@ import org.linphone.mediastream.Log; import org.linphone.mediastream.video.capture.hwconf.AndroidCameraConfiguration; import org.linphone.ui.Numpad; +import android.Manifest; import android.app.Activity; import android.app.Dialog; import android.app.FragmentTransaction; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.drawable.ColorDrawable; @@ -51,6 +53,7 @@ import android.os.Handler; import android.os.PowerManager; import android.os.SystemClock; import android.app.Fragment; +import android.support.v4.app.ActivityCompat; import android.support.v4.widget.DrawerLayout; import android.view.Gravity; import android.view.KeyEvent; @@ -76,9 +79,11 @@ import android.widget.Toast; /** * @author Sylvain Berfini */ -public class CallActivity extends Activity implements OnClickListener, SensorEventListener { +public class CallActivity extends Activity implements OnClickListener, SensorEventListener, ActivityCompat.OnRequestPermissionsResultCallback { private final static int SECONDS_BEFORE_HIDING_CONTROLS = 4000; private final static int SECONDS_BEFORE_DENYING_CALL_UPDATE = 30000; + private static final int PERMISSIONS_REQUEST_CAMERA = 202; + private static final int PERMISSIONS_ENABLED_CAMERA = 203; private static CallActivity instance; @@ -152,7 +157,6 @@ public class CallActivity extends Activity implements OnClickListener, SensorEve mProximity = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); mListener = new LinphoneCoreListenerBase(){ - @Override public void callState(LinphoneCore lc, final LinphoneCall call, LinphoneCall.State state, String message) { if (LinphoneManager.getLc().getCallsNb() == 0) { @@ -201,22 +205,31 @@ public class CallActivity extends Activity implements OnClickListener, SensorEve boolean videoEnabled = LinphonePreferences.instance().isVideoEnabled(); if (!videoEnabled) { acceptCallUpdate(false); - return; } boolean remoteVideo = call.getRemoteParams().getVideoEnabled(); boolean localVideo = call.getCurrentParamsCopy().getVideoEnabled(); boolean autoAcceptCameraPolicy = LinphonePreferences.instance().shouldAutomaticallyAcceptVideoRequests(); if (remoteVideo && !localVideo && !autoAcceptCameraPolicy && !LinphoneManager.getLc().isInConference()) { - showAcceptCallUpdateDialog(); + showAcceptCallUpdateDialog(); + timer = new CountDownTimer(SECONDS_BEFORE_DENYING_CALL_UPDATE, 1000) { + public void onTick(long millisUntilFinished) { } + public void onFinish() { + //TODO dismiss dialog + acceptCallUpdate(false); + } + }.start(); + + /*showAcceptCallUpdateDialog(); + + timer = new CountDownTimer(SECONDS_BEFORE_DENYING_CALL_UPDATE, 1000) { + public void onTick(long millisUntilFinished) { } + public void onFinish() { + //TODO dismiss dialog + + } + }.start();*/ - timer = new CountDownTimer(SECONDS_BEFORE_DENYING_CALL_UPDATE, 1000) { - public void onTick(long millisUntilFinished) { } - public void onFinish() { - //TODO dismiss dialog - acceptCallUpdate(false); - } - }.start(); } // else if (remoteVideo && !LinphoneManager.getLc().isInConference() && autoAcceptCameraPolicy) { // mHandler.post(new Runnable() { @@ -426,6 +439,37 @@ public class CallActivity extends Activity implements OnClickListener, SensorEve LinphoneManager.getInstance().changeStatusToOnThePhone(); } + public void checkAndRequestPermission(String permission, int result) { + if (getPackageManager().checkPermission(permission, getPackageName()) != PackageManager.PERMISSION_GRANTED) { + if (!ActivityCompat.shouldShowRequestPermissionRationale(this,permission)){ + ActivityCompat.requestPermissions(this, new String[]{permission}, result); + } + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + switch (requestCode) { + case PERMISSIONS_REQUEST_CAMERA: + UIThreadDispatcher.dispatch(new Runnable() { + @Override + public void run() { + acceptCallUpdate(true); + } + }); + break; + case PERMISSIONS_ENABLED_CAMERA: + UIThreadDispatcher.dispatch(new Runnable() { + @Override + public void run() { + enabledOrDisabledVideo(false); + } + }); + break; + } + LinphonePreferences.instance().neverAskCameraPerm(); + } + public void createInCallStats() { sideMenu = (DrawerLayout) findViewById(R.id.side_menu); menu = (ImageView) findViewById(R.id.call_quality); @@ -554,7 +598,11 @@ public class CallActivity extends Activity implements OnClickListener, SensorEve } if (id == R.id.video) { - enabledOrDisabledVideo(isVideoEnabled(LinphoneManager.getLc().getCurrentCall())); + if (getPackageManager().checkPermission(Manifest.permission.CAMERA, getPackageName()) == PackageManager.PERMISSION_GRANTED) { + enabledOrDisabledVideo(isVideoEnabled(LinphoneManager.getLc().getCurrentCall())); + } else { + checkAndRequestPermission(Manifest.permission.CAMERA, PERMISSIONS_ENABLED_CAMERA); + } } else if (id == R.id.micro) { toggleMicro(); @@ -1324,19 +1372,22 @@ public class CallActivity extends Activity implements OnClickListener, SensorEve delete.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { - if (CallActivity.isInstanciated()) { - Log.d("Call Update Accepted"); + if (getPackageManager().checkPermission(Manifest.permission.CAMERA, getPackageName()) == PackageManager.PERMISSION_GRANTED || LinphonePreferences.instance().cameraPermAsked()) { CallActivity.instance().acceptCallUpdate(true); + } else { + checkAndRequestPermission(Manifest.permission.CAMERA, PERMISSIONS_REQUEST_CAMERA); } + dialog.dismiss(); } }); - cancel.setOnClickListener(new OnClickListener() { + cancel.setOnClickListener(new + + OnClickListener() { @Override - public void onClick(View view) { + public void onClick (View view){ if (CallActivity.isInstanciated()) { - Log.d("Call Update Denied"); CallActivity.instance().acceptCallUpdate(false); } dialog.dismiss(); diff --git a/src/org/linphone/LinphoneActivity.java b/src/org/linphone/LinphoneActivity.java index 64a47a28f..54c1a93c0 100644 --- a/src/org/linphone/LinphoneActivity.java +++ b/src/org/linphone/LinphoneActivity.java @@ -63,6 +63,7 @@ import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; +import android.support.v4.app.ActivityCompat; import android.support.v4.widget.DrawerLayout; import android.view.Gravity; import android.view.KeyEvent; @@ -90,12 +91,16 @@ import android.widget.Toast; /** * @author Sylvain Berfini */ -public class LinphoneActivity extends Activity implements OnClickListener, ContactPicked { +public class LinphoneActivity extends Activity implements OnClickListener, ContactPicked, ActivityCompat.OnRequestPermissionsResultCallback { public static final String PREF_FIRST_LAUNCH = "pref_first_launch"; private static final int SETTINGS_ACTIVITY = 123; private static final int FIRST_LOGIN_ACTIVITY = 101; private static final int REMOTE_PROVISIONING_LOGIN_ACTIVITY = 102; private static final int CALL_ACTIVITY = 19; + private static final int PERMISSIONS_REQUEST_READ_CONTACTS = 200; + private static final int PERMISSIONS_REQUEST_RECORD_AUDIO = 201; + private static final int PERMISSIONS_REQUEST_CAMERA = 202; + private static final int PERMISSIONS_REQUEST_RECORD_AUDIO_INCOMING_CALL = 203; private static LinphoneActivity instance; @@ -111,7 +116,7 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta private ChatFragment chatFragment; private Fragment.SavedState dialerSavedState; private boolean newProxyConfig; - private boolean isAnimationDisabled = true, preferLinphoneContacts = false, emptyFragment = false; + private boolean isAnimationDisabled = true, preferLinphoneContacts = false, emptyFragment = false, permissionAsked = false; private OrientationEventListener mOrientationHelper; private LinphoneCoreListenerBase mListener; private LinearLayout mTabBar; @@ -234,9 +239,17 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta @Override public void callState(LinphoneCore lc, LinphoneCall call, LinphoneCall.State state, String message) { if (state == State.IncomingReceived) { - startActivity(new Intent(LinphoneActivity.instance(), CallIncomingActivity.class)); + if (getPackageManager().checkPermission(Manifest.permission.RECORD_AUDIO, getPackageName()) == PackageManager.PERMISSION_GRANTED || LinphonePreferences.instance().audioPermAsked()) { + startActivity(new Intent(LinphoneActivity.instance(), CallIncomingActivity.class)); + } else { + checkAndRequestPermission(Manifest.permission.RECORD_AUDIO, PERMISSIONS_REQUEST_RECORD_AUDIO_INCOMING_CALL); + } } else if (state == State.OutgoingInit || state == State.OutgoingProgress) { - startActivity(new Intent(LinphoneActivity.instance(), CallOutgoingActivity.class)); + if (getPackageManager().checkPermission(Manifest.permission.RECORD_AUDIO, getPackageName()) == PackageManager.PERMISSION_GRANTED || LinphonePreferences.instance().audioPermAsked()) { + startActivity(new Intent(LinphoneActivity.instance(), CallOutgoingActivity.class)); + } else { + checkAndRequestPermission(Manifest.permission.RECORD_AUDIO, PERMISSIONS_REQUEST_RECORD_AUDIO); + } } else if (state == State.CallEnd || state == State.Error || state == State.CallReleased) { // Convert LinphoneCore message for internalization if (message != null && call.getErrorInfo().getReason() == Reason.Declined) { @@ -1190,6 +1203,35 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta super.onPause(); } + public void checkAndRequestPermission(String permission, int result) { + if (getPackageManager().checkPermission(permission, getPackageName()) != PackageManager.PERMISSION_GRANTED) { + if (!ActivityCompat.shouldShowRequestPermissionRationale(this,permission) && !permissionAsked) { + permissionAsked = true; + if(LinphonePreferences.instance().shouldInitiateVideoCall() || + LinphonePreferences.instance().shouldAutomaticallyAcceptVideoRequests()) { + ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, permission}, result); + } else { + ActivityCompat.requestPermissions(this, new String[]{permission}, result); + } + } + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + switch (requestCode) { + case PERMISSIONS_REQUEST_RECORD_AUDIO: + startActivity(new Intent(this, CallOutgoingActivity.class)); + LinphonePreferences.instance().neverAskAudioPerm(); + break; + case PERMISSIONS_REQUEST_RECORD_AUDIO_INCOMING_CALL: + startActivity(new Intent(this, CallIncomingActivity.class)); + LinphonePreferences.instance().neverAskAudioPerm(); + break; + } + permissionAsked = false; + } + @Override protected void onResume() { super.onResume(); @@ -1201,6 +1243,8 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta if (getPackageManager().checkPermission(Manifest.permission.READ_CONTACTS, getPackageName()) == PackageManager.PERMISSION_GRANTED){ ContactsManager.getInstance().enabledContactsAccess(); ContactsManager.getInstance().prepareContactsInBackground(); + } else { + checkAndRequestPermission(Manifest.permission.READ_CONTACTS, PERMISSIONS_REQUEST_READ_CONTACTS); } updateMissedChatCount(); @@ -1209,14 +1253,22 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta LinphoneManager.getInstance().changeStatusToOnline(); - if(getIntent().getIntExtra("PreviousActivity", 0) != CALL_ACTIVITY){ + if (getIntent().getIntExtra("PreviousActivity", 0) != CALL_ACTIVITY){ if (LinphoneManager.getLc().getCalls().length > 0) { LinphoneCall call = LinphoneManager.getLc().getCalls()[0]; LinphoneCall.State callState = call.getState(); if (callState == State.IncomingReceived) { - startActivity(new Intent(this, CallIncomingActivity.class)); + if (getPackageManager().checkPermission(Manifest.permission.RECORD_AUDIO, getPackageName()) == PackageManager.PERMISSION_GRANTED || LinphonePreferences.instance().audioPermAsked()) { + startActivity(new Intent(this, CallIncomingActivity.class)); + } else { + checkAndRequestPermission(Manifest.permission.RECORD_AUDIO, PERMISSIONS_REQUEST_RECORD_AUDIO_INCOMING_CALL); + } } else if (callState == State.OutgoingInit || callState == State.OutgoingProgress || callState == State.OutgoingRinging) { - startActivity(new Intent(this, CallOutgoingActivity.class)); + if (getPackageManager().checkPermission(Manifest.permission.RECORD_AUDIO, getPackageName()) == PackageManager.PERMISSION_GRANTED || LinphonePreferences.instance().audioPermAsked()) { + startActivity(new Intent(this, CallOutgoingActivity.class)); + } else { + checkAndRequestPermission(Manifest.permission.RECORD_AUDIO, PERMISSIONS_REQUEST_RECORD_AUDIO); + } } else { if (call.getCurrentParamsCopy().getVideoEnabled()) { startVideoActivity(call); @@ -1310,7 +1362,11 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta if (CallActivity.isInstanciated()) { CallActivity.instance().startIncomingCallActivity(); } else { - startActivity(new Intent(this, CallIncomingActivity.class)); + if (getPackageManager().checkPermission(Manifest.permission.RECORD_AUDIO, getPackageName()) == PackageManager.PERMISSION_GRANTED || LinphonePreferences.instance().audioPermAsked()) { + startActivity(new Intent(this, CallIncomingActivity.class)); + } else { + checkAndRequestPermission(Manifest.permission.RECORD_AUDIO, PERMISSIONS_REQUEST_RECORD_AUDIO_INCOMING_CALL); + } } } } diff --git a/src/org/linphone/LinphonePreferences.java b/src/org/linphone/LinphonePreferences.java index 9b92f122e..041e43078 100644 --- a/src/org/linphone/LinphonePreferences.java +++ b/src/org/linphone/LinphonePreferences.java @@ -1204,4 +1204,20 @@ public class LinphonePreferences { public Boolean isDebugLogsEnabled(){ return getConfig().getBool("app", "debug_logs_enabled", false); } + + public Boolean audioPermAsked(){ + return getConfig().getBool("app", "audio_perm", false); + } + + public void neverAskAudioPerm(){ + getConfig().setBool("app", "audio_perm", true); + } + + public Boolean cameraPermAsked(){ + return getConfig().getBool("app", "camera_perm", false); + } + + public void neverAskCameraPerm(){ + getConfig().setBool("app", "camera_perm", true); + } } diff --git a/src/org/linphone/assistant/AssistantActivity.java b/src/org/linphone/assistant/AssistantActivity.java index df15e62ff..68213147f 100644 --- a/src/org/linphone/assistant/AssistantActivity.java +++ b/src/org/linphone/assistant/AssistantActivity.java @@ -46,6 +46,7 @@ import android.content.pm.PackageManager; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Bundle; +import android.support.v4.app.ActivityCompat; import android.text.TextUtils; import android.view.View; @@ -57,8 +58,8 @@ import android.widget.Toast; /** * @author Sylvain Berfini */ -public class AssistantActivity extends Activity implements OnClickListener { - private static AssistantActivity instance; +public class AssistantActivity extends Activity implements OnClickListener, ActivityCompat.OnRequestPermissionsResultCallback { +private static AssistantActivity instance; private ImageView back, cancel; private AssistantFragmentsEnum currentFragment; private AssistantFragmentsEnum firstFragment; @@ -70,6 +71,7 @@ public class AssistantActivity extends Activity implements OnClickListener { private StatusFragment status; private ProgressDialog progress; private Dialog dialog; + private static final int PERMISSIONS_REQUEST_RECORD_AUDIO = 201; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -221,6 +223,27 @@ public class AssistantActivity extends Activity implements OnClickListener { } } + public void checkAndRequestAudioPermission() { + if (getPackageManager().checkPermission(Manifest.permission.RECORD_AUDIO, getPackageName()) != PackageManager.PERMISSION_GRANTED) { + if (!ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.RECORD_AUDIO)) { + ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO}, PERMISSIONS_REQUEST_RECORD_AUDIO); + } + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + if (requestCode == PERMISSIONS_REQUEST_RECORD_AUDIO) { + if (getPackageManager().checkPermission(Manifest.permission.RECORD_AUDIO, getPackageName()) == PackageManager.PERMISSION_GRANTED) { + launchEchoCancellerCalibration(true); + } else { + success(); + } + } else { + success(); + } + } + private void launchEchoCancellerCalibration(boolean sendEcCalibrationResult) { if (getPackageManager().checkPermission(Manifest.permission.RECORD_AUDIO, getPackageName()) == PackageManager.PERMISSION_GRANTED) { boolean needsEchoCalibration = LinphoneManager.getLc().needsEchoCalibration(); @@ -235,7 +258,7 @@ public class AssistantActivity extends Activity implements OnClickListener { success(); } } else { - success(); + checkAndRequestAudioPermission(); } } @@ -472,8 +495,10 @@ public class AssistantActivity extends Activity implements OnClickListener { public void success() { mPrefs.firstLaunchSuccessful(); - LinphoneActivity.instance().isNewProxyConfig(); - setResult(Activity.RESULT_OK); + if(LinphoneActivity.instance() != null) { + LinphoneActivity.instance().isNewProxyConfig(); + setResult(Activity.RESULT_OK); + } finish(); } }