diff --git a/app/src/main/java/org/linphone/LinphoneManager.java b/app/src/main/java/org/linphone/LinphoneManager.java index 34671ad88..88ece552d 100644 --- a/app/src/main/java/org/linphone/LinphoneManager.java +++ b/app/src/main/java/org/linphone/LinphoneManager.java @@ -1450,6 +1450,9 @@ public class LinphoneManager implements CoreListener, SensorEventListener, Accou @Override public void onChatRoomStateChanged(Core lc, ChatRoom cr, ChatRoom.State state) {} + @Override + public void onQrcodeFound(Core lc, String result) {} + public void onCallEncryptionChanged( Core lc, Call call, boolean encrypted, String authenticationToken) {} @@ -2017,8 +2020,6 @@ public class LinphoneManager implements CoreListener, SensorEventListener, Accou } } - public void onQrcodeFound(Core lc, String something) {} - public interface AddressType { CharSequence getText(); diff --git a/app/src/main/java/org/linphone/assistant/AssistantActivity.java b/app/src/main/java/org/linphone/assistant/AssistantActivity.java index e70bbe92e..3a5abd26b 100644 --- a/app/src/main/java/org/linphone/assistant/AssistantActivity.java +++ b/app/src/main/java/org/linphone/assistant/AssistantActivity.java @@ -33,6 +33,7 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; +import android.content.res.Configuration; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Bundle; @@ -85,6 +86,7 @@ public class AssistantActivity extends Activity ActivityCompat.OnRequestPermissionsResultCallback, AccountCreatorListener { private static final int PERMISSIONS_REQUEST_RECORD_AUDIO = 201; + private static final int PERMISSIONS_REQUEST_CAMERA = 202; private static AssistantActivity instance; public DialPlan country; public String phone_number; @@ -334,6 +336,8 @@ public class AssistantActivity extends Activity } else { displayCreateAccount(); } + } else if (currentFragment == AssistantFragmentsEnum.QRCODE_READER) { + displayRemoteProvisioning(""); } } @@ -347,7 +351,12 @@ public class AssistantActivity extends Activity } public void checkAndRequestAudioPermission() { - checkAndRequestPermission(Manifest.permission.RECORD_AUDIO, 0); + checkAndRequestPermission( + Manifest.permission.RECORD_AUDIO, PERMISSIONS_REQUEST_RECORD_AUDIO); + } + + public void checkAndRequestVideoPermission() { + checkAndRequestPermission(Manifest.permission.CAMERA, PERMISSIONS_REQUEST_CAMERA); } public void checkAndRequestPermission(String permission, int result) { @@ -371,7 +380,7 @@ public class AssistantActivity extends Activity @Override public void onRequestPermissionsResult( - int requestCode, String[] permissions, int[] grantResults) { + int requestCode, String[] permissions, final int[] grantResults) { for (int i = 0; i < permissions.length; i++) { Log.i( "[Permission] " @@ -382,12 +391,19 @@ public class AssistantActivity extends Activity : "denied")); } - if (requestCode == PERMISSIONS_REQUEST_RECORD_AUDIO) { - if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { - launchEchoCancellerCalibration(true); - } else { - isEchoCalibrationFinished(); - } + switch (requestCode) { + case PERMISSIONS_REQUEST_CAMERA: + if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { + displayQRCodeReader(); + } + break; + case PERMISSIONS_REQUEST_RECORD_AUDIO: + if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { + launchEchoCancellerCalibration(true); + } else { + isEchoCalibrationFinished(); + } + break; } } @@ -543,13 +559,28 @@ public class AssistantActivity extends Activity back.setVisibility(View.VISIBLE); } - public void displayRemoteProvisioning() { + public void displayRemoteProvisioning(String url) { fragment = new RemoteProvisioningFragment(); + Bundle extra = new Bundle(); + extra.putString("RemoteUrl", url); + fragment.setArguments(extra); changeFragment(fragment); currentFragment = AssistantFragmentsEnum.REMOTE_PROVISIONING; back.setVisibility(View.VISIBLE); } + public void displayQRCodeReader() { + if (getPackageManager().checkPermission(Manifest.permission.CAMERA, getPackageName()) + != PackageManager.PERMISSION_GRANTED) { + checkAndRequestVideoPermission(); + } else { + fragment = new QrCodeFragment(); + changeFragment(fragment); + currentFragment = AssistantFragmentsEnum.QRCODE_READER; + back.setVisibility(View.VISIBLE); + } + } + public void displayCountryChooser() { fragment = new CountryListFragment(); changeFragment(fragment); @@ -849,6 +880,14 @@ public class AssistantActivity extends Activity return countryListAdapter; } + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + if (currentFragment == AssistantFragmentsEnum.QRCODE_READER) { + this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + } + } + /** * This class reads a JSON file containing Country-specific phone number description, and allows * to present them into a ListView diff --git a/app/src/main/java/org/linphone/assistant/AssistantFragmentsEnum.java b/app/src/main/java/org/linphone/assistant/AssistantFragmentsEnum.java index 4b8cf250a..699555cd6 100644 --- a/app/src/main/java/org/linphone/assistant/AssistantFragmentsEnum.java +++ b/app/src/main/java/org/linphone/assistant/AssistantFragmentsEnum.java @@ -28,5 +28,6 @@ public enum AssistantFragmentsEnum { LOGIN, REMOTE_PROVISIONING, ECHO_CANCELLER_CALIBRATION, - DOWNLOAD_CODEC; + DOWNLOAD_CODEC, + QRCODE_READER } diff --git a/app/src/main/java/org/linphone/assistant/QrCodeFragment.java b/app/src/main/java/org/linphone/assistant/QrCodeFragment.java new file mode 100644 index 000000000..0862d5e6a --- /dev/null +++ b/app/src/main/java/org/linphone/assistant/QrCodeFragment.java @@ -0,0 +1,99 @@ +package org.linphone.assistant; + +/* +QrCodeFragment.java +Copyright (C) 2018 Belledonne Communications, Grenoble, France + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import android.app.Fragment; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.TextureView; +import android.view.View; +import android.view.ViewGroup; +import org.linphone.LinphoneManager; +import org.linphone.R; +import org.linphone.core.Core; +import org.linphone.core.CoreListenerStub; +import org.linphone.mediastream.video.capture.hwconf.AndroidCameraConfiguration; + +public class QrCodeFragment extends Fragment { + private TextureView mQrcodeView; + private CoreListenerStub mListener; + + @Override + public View onCreateView( + LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.qrcode, container, false); + + mQrcodeView = view.findViewById(R.id.qrcodeCaptureSurface); + + LinphoneManager.getLc().setNativePreviewWindowId(mQrcodeView); + + mListener = + new CoreListenerStub() { + @Override + public void onQrcodeFound(Core lc, String result) { + enableQrcodeReader(false); + AssistantActivity.instance().displayRemoteProvisioning(result); + } + }; + + return view; + } + + private void enableQrcodeReader(boolean enable) { + LinphoneManager.getLc().enableQrcodeVideoPreview(enable); + LinphoneManager.getLc().enableVideoPreview(enable); + if (enable) { + LinphoneManager.getLc().addListener(mListener); + } else { + LinphoneManager.getLc().removeListener(mListener); + } + } + + private void setBackCamera(boolean useBackCamera) { + int camId = 0; + AndroidCameraConfiguration.AndroidCamera[] cameras = + AndroidCameraConfiguration.retrieveCameras(); + for (AndroidCameraConfiguration.AndroidCamera androidCamera : cameras) { + if (androidCamera.frontFacing == !useBackCamera) camId = androidCamera.id; + } + String[] devices = LinphoneManager.getLc().getVideoDevicesList(); + String newDevice = devices[camId]; + LinphoneManager.getLc().setVideoDevice(newDevice); + } + + private void launchQrcodeReader() { + setBackCamera(true); + + enableQrcodeReader(true); + } + + @Override + public void onResume() { + launchQrcodeReader(); + super.onResume(); + } + + @Override + public void onPause() { + enableQrcodeReader(false); + // setBackCamera(false); + super.onPause(); + } +} diff --git a/app/src/main/java/org/linphone/assistant/RemoteProvisioningActivity.java b/app/src/main/java/org/linphone/assistant/RemoteProvisioningActivity.java index c9814fe0e..e46307f7e 100644 --- a/app/src/main/java/org/linphone/assistant/RemoteProvisioningActivity.java +++ b/app/src/main/java/org/linphone/assistant/RemoteProvisioningActivity.java @@ -204,14 +204,8 @@ public class RemoteProvisioningActivity extends Activity { LinphonePreferences.instance().setContext(this); // Needed, else the next call will crash LinphonePreferences.instance().setRemoteProvisioningUrl(configUri); - mHandler.postDelayed( - new Runnable() { - @Override - public void run() { - LinphoneManager.getInstance().restartCore(); - } - }, - 1000); + LinphoneManager.getLc().getConfig().sync(); + LinphoneManager.getInstance().restartCore(); } private void goToLinphoneActivity() { diff --git a/app/src/main/java/org/linphone/assistant/RemoteProvisioningFragment.java b/app/src/main/java/org/linphone/assistant/RemoteProvisioningFragment.java index 352e1ccb5..e710ac213 100644 --- a/app/src/main/java/org/linphone/assistant/RemoteProvisioningFragment.java +++ b/app/src/main/java/org/linphone/assistant/RemoteProvisioningFragment.java @@ -33,19 +33,25 @@ import org.linphone.R; import org.linphone.settings.LinphonePreferences; public class RemoteProvisioningFragment extends Fragment implements OnClickListener, TextWatcher { - private EditText remoteProvisioningUrl; - private Button apply; + private EditText mRemoteProvisioningUrl; + private Button mApply, mQrcode; @Override public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.assistant_remote_provisioning, container, false); - remoteProvisioningUrl = view.findViewById(R.id.assistant_remote_provisioning_url); - remoteProvisioningUrl.addTextChangedListener(this); - apply = view.findViewById(R.id.assistant_apply); - apply.setEnabled(false); - apply.setOnClickListener(this); + mRemoteProvisioningUrl = view.findViewById(R.id.assistant_remote_provisioning_url); + mRemoteProvisioningUrl.addTextChangedListener(this); + mQrcode = view.findViewById(R.id.assistant_qrcode); + mQrcode.setOnClickListener(this); + mApply = view.findViewById(R.id.assistant_apply); + mApply.setEnabled(false); + mApply.setOnClickListener(this); + + if (getArguments() != null && !getArguments().getString("RemoteUrl").isEmpty()) { + mRemoteProvisioningUrl.setText(getArguments().getString("RemoteUrl")); + } return view; } @@ -55,12 +61,14 @@ public class RemoteProvisioningFragment extends Fragment implements OnClickListe int id = v.getId(); if (id == R.id.assistant_apply) { - String url = remoteProvisioningUrl.getText().toString(); + String url = mRemoteProvisioningUrl.getText().toString(); AssistantActivity.instance().displayRemoteProvisioningInProgressDialog(); LinphonePreferences.instance().setRemoteProvisioningUrl(url); LinphoneManager.getLc().getConfig().sync(); LinphoneManager.getInstance().restartCore(); AssistantActivity.instance().setCoreListener(); + } else if (id == R.id.assistant_qrcode) { + AssistantActivity.instance().displayQRCodeReader(); } } @@ -69,7 +77,7 @@ public class RemoteProvisioningFragment extends Fragment implements OnClickListe @Override public void onTextChanged(CharSequence s, int start, int before, int count) { - apply.setEnabled(!remoteProvisioningUrl.getText().toString().isEmpty()); + mApply.setEnabled(!mRemoteProvisioningUrl.getText().toString().isEmpty()); } @Override diff --git a/app/src/main/java/org/linphone/assistant/WelcomeFragment.java b/app/src/main/java/org/linphone/assistant/WelcomeFragment.java index 08fbf265a..b7123e02a 100644 --- a/app/src/main/java/org/linphone/assistant/WelcomeFragment.java +++ b/app/src/main/java/org/linphone/assistant/WelcomeFragment.java @@ -72,7 +72,7 @@ public class WelcomeFragment extends Fragment implements OnClickListener { } else if (id == R.id.create_account) { AssistantActivity.instance().displayCreateAccount(); } else if (id == R.id.remote_provisioning) { - AssistantActivity.instance().displayRemoteProvisioning(); + AssistantActivity.instance().displayRemoteProvisioning(""); } } } diff --git a/app/src/main/res/layout/assistant_remote_provisioning.xml b/app/src/main/res/layout/assistant_remote_provisioning.xml index c81a66f15..000bd4f53 100644 --- a/app/src/main/res/layout/assistant_remote_provisioning.xml +++ b/app/src/main/res/layout/assistant_remote_provisioning.xml @@ -59,5 +59,18 @@ android:paddingRight="10dp" android:layout_marginTop="20dp"/> +