...
 
Commits (24)
......@@ -10,13 +10,23 @@ Group changes to describe their impact on the project, as follows:
Fixed for any bug fixes.
Security to invite users to upgrade in case of vulnerabilities.
## [Unreleased]
## [4.2.3] - 2020-03-03
### Added
-
### Changed
- Fixed various crashes
- Updated SDK to 4.3.3
## [4.2.2] - 2020-02-24
### Changed
- Fixed various issues
- Updated SDK to 4.3.1
- Removed AAudio plugin for now (we have observed quality issues on some popular devices with their latest updates)
## [4.2.1] - 2020-01-13
### Changed
-
- Fixed various issues
## [4.2.0] - 2019-12-09
......
......@@ -24,7 +24,7 @@ static def isLocalAarAvailable() {
}
task getGitVersion() {
def gitVersion = "4.2"
def gitVersion = "4.2.3"
def gitVersionStream = new ByteArrayOutputStream()
def gitCommitsCount = new ByteArrayOutputStream()
def gitCommitHash = new ByteArrayOutputStream()
......@@ -43,7 +43,11 @@ task getGitVersion() {
standardOutput = gitCommitHash
}
gitVersion = gitVersionStream.toString().trim() + "." + gitCommitsCount.toString().trim() + "+" + gitCommitHash.toString().trim()
if (gitCommitsCount.toString().toInteger() == 0) {
gitVersion = gitVersionStream.toString().trim()
} else {
gitVersion = gitVersionStream.toString().trim() + "." + gitCommitsCount.toString().trim() + "+" + gitCommitHash.toString().trim()
}
println("Git version: " + gitVersion)
} catch (Exception e) {
println("Git not found")
......@@ -88,7 +92,7 @@ android {
defaultConfig {
minSdkVersion 21
targetSdkVersion 29
versionCode 4213
versionCode 4230
versionName "${project.version}"
applicationId getPackageName()
multiDexEnabled true
......
......@@ -209,6 +209,7 @@
<activity
android:name=".assistant.OpenH264DownloadAssistantActivity"/>
<!-- Services -->
<service
......@@ -263,6 +264,13 @@
android:enabled="true"
android:exported="false" />
<receiver
android:name=".receivers.AccountEnableReceiver">
<intent-filter>
<action android:name="org.linphone.intent.ACCOUNTACTIVATE" />
</intent-filter>
</receiver>
<!-- Providers -->
<provider
......
......@@ -90,6 +90,9 @@ public class LinphoneContext {
}
public static LinphoneContext instance() {
if (sInstance == null) {
throw new RuntimeException("[Context] Linphone Context not available!");
}
return sInstance;
}
......
......@@ -332,6 +332,8 @@ public class LinphoneManager implements SensorEventListener {
}
public static synchronized Core getCore() {
if (!LinphoneContext.isReady()) return null;
if (getInstance().mExited) {
// Can occur if the UI thread play a posted event but in the meantime the
// LinphoneManager was destroyed
......
......@@ -23,6 +23,7 @@ import android.app.Activity;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.util.Log;
import org.linphone.LinphoneManager;
import org.linphone.R;
import org.linphone.assistant.MenuAssistantActivity;
......@@ -57,9 +58,14 @@ public class LinphoneLauncherActivity extends Activity implements ServiceWaitThr
if (LinphoneService.isReady()) {
onServiceReady();
} else {
startService(
new Intent().setClass(LinphoneLauncherActivity.this, LinphoneService.class));
new ServiceWaitThread(this).start();
try {
startService(
new Intent()
.setClass(LinphoneLauncherActivity.this, LinphoneService.class));
new ServiceWaitThread(this).start();
} catch (IllegalStateException ise) {
Log.e("Linphone", "Exception raised while starting service: " + ise);
}
}
}
......
......@@ -25,6 +25,7 @@ import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.app.KeyguardManager;
import android.content.ActivityNotFoundException;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
......@@ -69,6 +70,7 @@ import org.linphone.fragments.EmptyFragment;
import org.linphone.fragments.StatusBarFragment;
import org.linphone.history.HistoryActivity;
import org.linphone.menu.SideMenuFragment;
import org.linphone.service.LinphoneService;
import org.linphone.settings.LinphonePreferences;
import org.linphone.settings.SettingsActivity;
import org.linphone.utils.DeviceUtils;
......@@ -419,11 +421,19 @@ public abstract class MainActivity extends LinphoneGenericActivity
Intent intent = new Intent();
intent.setAction(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
try {
startActivity(intent);
} catch (IllegalStateException ise) {
Log.e("[Main Activity] Can't start home activity: ", ise);
}
}
private void quit() {
goHomeAndClearStack();
if (LinphoneService.isReady()
&& LinphonePreferences.instance().getServiceNotificationVisibility()) {
LinphoneService.instance().stopSelf();
}
}
// Tab, Top and Status bars
......@@ -546,8 +556,10 @@ public abstract class MainActivity extends LinphoneGenericActivity
if (permissions[i].equals(Manifest.permission.READ_CONTACTS)
|| permissions[i].equals(Manifest.permission.WRITE_CONTACTS)) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
ContactsManager.getInstance().enableContactsAccess();
ContactsManager.getInstance().initializeContactManager();
if (LinphoneContext.isReady()) {
ContactsManager.getInstance().enableContactsAccess();
ContactsManager.getInstance().initializeContactManager();
}
}
} else if (permissions[i].equals(Manifest.permission.READ_EXTERNAL_STORAGE)) {
boolean enableRingtone = grantResults[i] == PackageManager.PERMISSION_GRANTED;
......@@ -626,6 +638,18 @@ public abstract class MainActivity extends LinphoneGenericActivity
}
}
public void newOutgoingCall(String to) {
if (LinphoneManager.getCore().getCallsNb() > 0) {
Intent intent = new Intent(this, DialerActivity.class);
intent.addFlags(
Intent.FLAG_ACTIVITY_NO_ANIMATION | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
intent.putExtra("SipUri", to);
this.startActivity(intent);
} else {
LinphoneManager.getCallManager().newOutgoingCall(to, null);
}
}
private void addFlagsToIntent(Intent intent) {
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
}
......@@ -774,8 +798,13 @@ public abstract class MainActivity extends LinphoneGenericActivity
new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(
new Intent("android.settings.NOTIFICATION_POLICY_ACCESS_SETTINGS"));
try {
startActivity(
new Intent(
"android.settings.NOTIFICATION_POLICY_ACCESS_SETTINGS"));
} catch (ActivityNotFoundException anfe) {
Log.e("[Main Activity] Activity not found exception: ", anfe);
}
dialog.dismiss();
}
});
......
......@@ -237,9 +237,18 @@ public class PhoneAccountLinkingAssistantActivity extends AssistantActivity {
super.onResume();
Core core = LinphoneManager.getCore();
// Save & restore username & password informations, reload will reset
String username = getAccountCreator().getUsername();
String ha1 = getAccountCreator().getHa1();
String algo = getAccountCreator().getAlgorithm();
if (core != null) {
reloadLinphoneAccountCreatorConfig();
}
AccountCreator creator = getAccountCreator();
creator.setUsername(username);
creator.setHa1(ha1);
creator.setAlgorithm(algo);
getAccountCreator().addListener(mListener);
......
......@@ -162,9 +162,12 @@ public class PhoneAccountValidationAssistantActivity extends AssistantActivity {
public void onPrimaryClipChanged() {
ClipData data = mClipboard.getPrimaryClip();
if (data != null && data.getItemCount() > 0) {
String clip = data.getItemAt(0).getText().toString();
if (clip.length() == mActivationCodeLength) {
mSmsCode.setText(clip);
ClipData.Item item = data.getItemAt(0);
if (item != null && item.getText() != null) {
String clip = item.getText().toString();
if (clip.length() == mActivationCodeLength) {
mSmsCode.setText(clip);
}
}
}
}
......
......@@ -40,6 +40,7 @@ import android.view.KeyEvent;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
import org.linphone.LinphoneContext;
import org.linphone.LinphoneManager;
import org.linphone.R;
import org.linphone.compatibility.Compatibility;
......@@ -438,7 +439,7 @@ public class AndroidAudioManager {
public synchronized void bluetoothHeadetConnectionChanged(boolean connected) {
mIsBluetoothHeadsetConnected = connected;
mAudioManager.setBluetoothScoOn(connected);
LinphoneManager.getCallManager().refreshInCallActions();
if (LinphoneContext.isReady()) LinphoneManager.getCallManager().refreshInCallActions();
}
public synchronized void bluetoothHeadetAudioConnectionChanged(boolean connected) {
......@@ -452,7 +453,7 @@ public class AndroidAudioManager {
public synchronized void bluetoothHeadetScoConnectionChanged(boolean connected) {
mIsBluetoothHeadsetScoConnected = connected;
LinphoneManager.getCallManager().refreshInCallActions();
if (LinphoneContext.isReady()) LinphoneManager.getCallManager().refreshInCallActions();
}
public synchronized boolean isUsingBluetoothAudioRoute() {
......
......@@ -49,6 +49,7 @@ import androidx.core.content.ContextCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import org.linphone.LinphoneContext;
import org.linphone.LinphoneManager;
import org.linphone.R;
import org.linphone.activities.LinphoneGenericActivity;
......@@ -94,6 +95,8 @@ public class CallActivity extends LinphoneGenericActivity
@Override
public void run() {
// Make sure that at the time this is executed this is still required
if (!LinphoneContext.isReady()) return;
Call call = LinphoneManager.getCore().getCurrentCall();
if (call != null && call.getCurrentParams().videoEnabled()) {
CallActivity activity = mWeakCallActivity.get();
......@@ -487,7 +490,7 @@ public class CallActivity extends LinphoneGenericActivity
finish();
}
LinphoneService.instance().destroyOverlay();
if (LinphoneService.isReady()) LinphoneService.instance().destroyOverlay();
}
@Override
......@@ -502,7 +505,7 @@ public class CallActivity extends LinphoneGenericActivity
Call call = core.getCurrentCall();
if (call.getState() == Call.State.StreamsRunning) {
// Prevent overlay creation if video call is paused by remote
LinphoneService.instance().createOverlay();
if (LinphoneService.isReady()) LinphoneService.instance().createOverlay();
}
}
......@@ -924,7 +927,7 @@ public class CallActivity extends LinphoneGenericActivity
private void goBackToDialer() {
Intent intent = new Intent();
intent.setClass(this, DialerActivity.class);
intent.putExtra("Transfer", false);
intent.putExtra("isTransfer", false);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);
}
......@@ -932,7 +935,7 @@ public class CallActivity extends LinphoneGenericActivity
private void goBackToDialerAndDisplayTransferButton() {
Intent intent = new Intent();
intent.setClass(this, DialerActivity.class);
intent.putExtra("Transfer", true);
intent.putExtra("isTransfer", true);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);
}
......
......@@ -122,15 +122,8 @@ public class CallIncomingActivity extends LinphoneGenericActivity {
@Override
public void onCallStateChanged(
Core core, Call call, State state, String message) {
if (call == mCall) {
if (state == State.Connected) {
// This is done by the LinphoneContext listener now
// startActivity(new Intent(CallOutgoingActivity.this,
// CallActivity.class));
}
}
if (state == State.End || state == State.Released) {
mCall = null;
finish();
}
}
......@@ -176,7 +169,7 @@ public class CallIncomingActivity extends LinphoneGenericActivity {
mNumber.setText(address.asStringUriOnly());
if (LinphonePreferences.instance().acceptIncomingEarlyMedia()) {
if (mCall.getCurrentParams().videoEnabled()) {
if (mCall.getCurrentParams() != null && mCall.getCurrentParams().videoEnabled()) {
findViewById(R.id.avatar_layout).setVisibility(View.GONE);
mCall.getCore().setNativeVideoWindowId(mVideoDisplay);
}
......@@ -206,7 +199,8 @@ public class CallIncomingActivity extends LinphoneGenericActivity {
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (LinphoneContext.isReady()
&& (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_HOME)) {
&& (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_HOME)
&& mCall != null) {
mCall.terminate();
finish();
}
......@@ -231,7 +225,7 @@ public class CallIncomingActivity extends LinphoneGenericActivity {
}
mAlreadyAcceptedOrDeniedCall = true;
mCall.terminate();
if (mCall != null) mCall.terminate();
finish();
}
......@@ -281,6 +275,7 @@ public class CallIncomingActivity extends LinphoneGenericActivity {
}
if (LinphonePreferences.instance().shouldAutomaticallyAcceptVideoRequests()
&& mCall != null
&& mCall.getRemoteParams() != null
&& mCall.getRemoteParams().videoEnabled()) {
if (camera != PackageManager.PERMISSION_GRANTED) {
Log.i("[Permission] Asking for camera");
......
......@@ -89,7 +89,11 @@ public class CallStatsFragment extends Fragment {
@Override
public void onPause() {
super.onPause();
LinphoneManager.getCore().removeListener(mListener);
Core core = LinphoneManager.getCore();
if (core != null) {
core.removeListener(mListener);
}
}
public void setDrawer(DrawerLayout drawer, RelativeLayout content) {
......
......@@ -35,6 +35,7 @@ import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.core.content.ContextCompat;
import org.linphone.LinphoneContext;
import org.linphone.LinphoneManager;
import org.linphone.R;
import org.linphone.core.Call;
......@@ -184,9 +185,11 @@ public class CallStatusBarFragment extends Fragment {
public void onPause() {
super.onPause();
Core core = LinphoneManager.getCore();
if (core != null) {
core.removeListener(mListener);
if (LinphoneContext.isReady()) {
Core core = LinphoneManager.getCore();
if (core != null) {
core.removeListener(mListener);
}
}
if (mCallQualityUpdater != null) {
......
......@@ -250,7 +250,7 @@ public class ChatMessageViewHolder extends RecyclerView.ViewHolder implements Vi
final TextView fileName = content.findViewById(R.id.file);
fileName.setVisibility(View.GONE);
if (c.isFile() || (c.isFileTransfer() && message.isOutgoing())) {
if (c.isFile() || (c.isFileTransfer() && !c.getFilePath().isEmpty())) {
// If message is outgoing, even if content
// is file transfer we have the file available
final String filePath = c.getFilePath();
......
......@@ -66,10 +66,13 @@ class ApiTwentyFivePlus {
Address participantAddress =
room.hasCapability(ChatRoomCapabilities.Basic.toInt())
? room.getPeerAddress()
: room.getParticipants()[0].getAddress();
: room.getParticipants().length == 0
? null
: room.getParticipants()[0].getAddress();
if (participantAddress == null) continue;
LinphoneContact contact =
ContactsManager.getInstance().findContactFromAddress(participantAddress);
if (contact != null && !contacts.contains(contact)) {
if (context.getResources().getBoolean(R.bool.shortcut_to_contact)) {
ShortcutInfo shortcut = manager.createContactShortcutInfo(contact);
......
......@@ -48,7 +48,10 @@ class ApiTwentySixPlus {
Settings.Global.getString(
context.getContentResolver(), Settings.Global.DEVICE_NAME);
if (name == null) {
name = BluetoothAdapter.getDefaultAdapter().getName();
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if (adapter != null) {
name = adapter.getName();
}
}
if (name == null) {
name = Settings.Secure.getString(context.getContentResolver(), "bluetooth_name");
......
......@@ -51,7 +51,12 @@ public class Compatibility {
return ApiTwentySixPlus.getDeviceName(context);
}
String name = BluetoothAdapter.getDefaultAdapter().getName();
String name = null;
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if (adapter != null) {
name = adapter.getName();
}
if (name == null) {
name = Settings.Secure.getString(context.getContentResolver(), "bluetooth_name");
}
......
......@@ -43,7 +43,7 @@ class AndroidContact implements Serializable {
String mAndroidId;
private String mAndroidRawId;
private boolean isAndroidRawIdLinphone;
private final transient ArrayList<ContentProviderOperation> mChangesToCommit;
private transient ArrayList<ContentProviderOperation> mChangesToCommit;
private byte[] mTempPicture;
AndroidContact() {
......@@ -66,6 +66,9 @@ class AndroidContact implements Serializable {
private void addChangesToCommit(ContentProviderOperation operation) {
Log.i("[Contact] Added operation " + operation);
if (mChangesToCommit == null) {
mChangesToCommit = new ArrayList<>();
}
mChangesToCommit.add(operation);
}
......
......@@ -35,8 +35,6 @@ import org.linphone.compatibility.Compatibility;
import org.linphone.core.Core;
import org.linphone.core.Friend;
import org.linphone.core.FriendList;
import org.linphone.core.PresenceBasicStatus;
import org.linphone.core.PresenceModel;
import org.linphone.core.tools.Log;
import org.linphone.settings.LinphonePreferences;
import org.linphone.utils.LinphoneUtils;
......@@ -226,7 +224,7 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsLoader.Asyn
}
}
if (contact.getFriend() != null) {
/*if (contact.getFriend() != null) {
for (LinphoneNumberOrAddress noa : contact.getNumbersOrAddresses()) {
PresenceModel pm =
contact.getFriend().getPresenceModelForUriOrTel(noa.getValue());
......@@ -235,7 +233,7 @@ class AsyncContactsLoader extends AsyncTask<Void, Void, AsyncContactsLoader.Asyn
break;
}
}
}
}*/
if (!mContext.getResources().getBoolean(R.bool.hide_sip_contacts_without_presence)) {
if (contact.hasAddress() && !data.sipContacts.contains(contact)) {
......
......@@ -36,6 +36,7 @@ import android.widget.TableLayout;
import android.widget.TextView;
import org.linphone.LinphoneManager;
import org.linphone.R;
import org.linphone.activities.MainActivity;
import org.linphone.contacts.views.ContactAvatar;
import org.linphone.core.Address;
import org.linphone.core.ChatRoom;
......@@ -304,7 +305,7 @@ public class ContactDetailsFragment extends Fragment implements ContactsUpdatedL
@Override
public void onClick(View v) {
String tag = (String) v.getTag();
LinphoneManager.getCallManager().newOutgoingCall(tag, null);
((MainActivity) getActivity()).newOutgoingCall(tag);
}
});
if (contactAddress != null) {
......@@ -367,12 +368,16 @@ public class ContactDetailsFragment extends Fragment implements ContactsUpdatedL
if (core == null) return;
Address participant = Factory.instance().createAddress(tag);
if (participant == null) {
Log.e("[Contact Detail] Couldn't parse ", tag);
return;
}
ProxyConfig defaultProxyConfig = core.getDefaultProxyConfig();
if (defaultProxyConfig != null) {
ChatRoom room =
core.findOneToOneChatRoom(
defaultProxyConfig.getContact(), participant, isSecured);
defaultProxyConfig.getIdentityAddress(), participant, isSecured);
if (room != null) {
((ContactsActivity) getActivity())
.showChatRoom(room.getLocalAddress(), room.getPeerAddress());
......
......@@ -222,7 +222,7 @@ public class ContactsManager extends ContentObserver
}
public boolean hasReadContactsAccess() {
if (mContext == null) {
if (mContext == null || mContext.getPackageManager() == null) {
return false;
}
......@@ -286,6 +286,12 @@ public class ContactsManager extends ContentObserver
ContentProviderClient client =
mContext.getContentResolver()
.acquireContentProviderClient(ContactsContract.AUTHORITY_URI);
if (client == null) {
Log.e(
"[Contacts Manager] Failed to get content provider client for contacts authority!");
return;
}
ContentValues values = new ContentValues();
values.put(
ContactsContract.Settings.ACCOUNT_NAME,
......@@ -294,6 +300,7 @@ public class ContactsManager extends ContentObserver
ContactsContract.Settings.ACCOUNT_TYPE,
mContext.getString(R.string.sync_account_type));
values.put(ContactsContract.Settings.UNGROUPED_VISIBLE, true);
try {
client.insert(
ContactsContract.Settings.CONTENT_URI
......
......@@ -90,26 +90,29 @@ public class LinphoneContact extends AndroidContact
String contactFullName = contact.getFullName() != null ? contact.getFullName() : "";
if (fullName.equals(contactFullName)) {
if (getAndroidId() != null) {
if (contact.getAndroidId() != null) {
int idComp = getAndroidId().compareTo(contact.getAndroidId());
if (idComp == 0) return 0;
List<LinphoneNumberOrAddress> noas1 = getNumbersOrAddresses();
List<LinphoneNumberOrAddress> noas2 = contact.getNumbersOrAddresses();
if (noas1.size() == noas2.size()) {
if (noas1.containsAll(noas2) && noas2.containsAll(noas1)) {
return 0;
String id = getAndroidId() != null ? getAndroidId() : "";
String contactId = contact.getAndroidId() != null ? contact.getAndroidId() : "";
if (id.equals(contactId)) {
List<LinphoneNumberOrAddress> noas1 = getNumbersOrAddresses();
List<LinphoneNumberOrAddress> noas2 = contact.getNumbersOrAddresses();
if (noas1.size() == noas2.size() && noas1.size() > 0) {
if (!noas1.containsAll(noas2) || !noas2.containsAll(noas1)) {
for (int i = 0; i < noas1.size(); i++) {
int compare = noas1.get(i).compareTo(noas2.get(i));
if (compare != 0) return compare;
}
return -1;
}
} else {
return Integer.compare(noas1.size(), noas2.size());
}
return -1;
String org = getOrganization() != null ? getOrganization() : "";
String contactOrg =
contact.getOrganization() != null ? contact.getOrganization() : "";
return org.compareTo(contactOrg);
}
if (contact.getAndroidId() != null) return 1;
return 0;
return id.compareTo(contactId);
}
return fullName.compareTo(contactFullName);
}
......@@ -531,18 +534,24 @@ public class LinphoneContact extends AndroidContact
}
private synchronized void syncValuesFromAndroidContact(Context context) {
Cursor c =
context.getContentResolver()
.query(
ContactsContract.Data.CONTENT_URI,
AsyncContactsLoader.PROJECTION,
ContactsContract.Data.IN_DEFAULT_DIRECTORY
+ " == 1 AND "
+ ContactsContract.Data.CONTACT_ID
+ " == "
+ mAndroidId,
null,
null);
Cursor c = null;
try {
c =
context.getContentResolver()
.query(
ContactsContract.Data.CONTENT_URI,
AsyncContactsLoader.PROJECTION,
ContactsContract.Data.IN_DEFAULT_DIRECTORY
+ " == 1 AND "
+ ContactsContract.Data.CONTACT_ID
+ " == "
+ mAndroidId,
null,
null);
} catch (SecurityException se) {
Log.e("[Contact] Security exception: ", se);
}
if (c != null) {
mAddresses = new ArrayList<>();
while (c.moveToNext()) {
......
......@@ -124,7 +124,7 @@ public class SearchContactsAdapter extends RecyclerView.Adapter<SearchContactVie
if (mSecurityEnabled || !mIsOnlyOnePersonSelection) {
Core core = LinphoneManager.getCore();
ProxyConfig defaultProxyConfig = core.getDefaultProxyConfig();
if (defaultProxyConfig != null) {
if (defaultProxyConfig != null && searchResult.getAddress() != null) {
// SDK won't accept ourselves in the list of participants
if (defaultProxyConfig.getIdentityAddress().weakEqual(searchResult.getAddress())) {
// Disable row, we can't use our own address in a group chat room
......
......@@ -116,13 +116,26 @@ public class DialerActivity extends MainActivity implements AddressText.AddressC
Manifest.permission.READ_CONTACTS
};
mIsTransfer = false;
if (getIntent() != null) {
mIsTransfer = getIntent().getBooleanExtra("isTransfer", false);
}
handleIntentParams(getIntent());
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
handleIntentParams(intent);
if (intent != null) {
mIsTransfer = intent.getBooleanExtra("isTransfer", mIsTransfer);
if (mAddress != null && intent.getStringExtra("SipUri") != null) {
mAddress.setText(intent.getStringExtra("SipUri"));
}
}
}
@Override
......@@ -207,9 +220,7 @@ public class DialerActivity extends MainActivity implements AddressText.AddressC
}
});
mIsTransfer = false;
if (getIntent() != null) {
mIsTransfer = getIntent().getBooleanExtra("Transfer", false);
mAddress.setText(getIntent().getStringExtra("SipUri"));
}
......
......@@ -28,6 +28,7 @@ import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import org.linphone.LinphoneContext;
import org.linphone.LinphoneManager;
import org.linphone.R;
import org.linphone.core.Content;
......@@ -162,9 +163,11 @@ public class StatusBarFragment extends Fragment {
public void onPause() {
super.onPause();
Core core = LinphoneManager.getCore();
if (core != null) {
core.removeListener(mListener);
if (LinphoneContext.isReady()) {
Core core = LinphoneManager.getCore();
if (core != null) {
core.removeListener(mListener);
}
}
}
......
......@@ -33,6 +33,7 @@ import java.util.Arrays;
import java.util.List;
import org.linphone.LinphoneManager;
import org.linphone.R;
import org.linphone.activities.MainActivity;
import org.linphone.contacts.ContactsManager;
import org.linphone.contacts.LinphoneContact;
import org.linphone.contacts.views.ContactAvatar;
......@@ -80,7 +81,7 @@ public class HistoryDetailFragment extends Fragment {
new OnClickListener() {
@Override
public void onClick(View v) {
LinphoneManager.getCallManager().newOutgoingCall(mSipUri, mDisplayName);
((MainActivity) getActivity()).newOutgoingCall(mSipUri);
}
});
......@@ -260,12 +261,16 @@ public class HistoryDetailFragment extends Fragment {
if (core == null) return;
Address participant = Factory.instance().createAddress(mSipUri);
if (participant == null) {
Log.e("[History Detail] Couldn't parse ", mSipUri);
return;
}
ProxyConfig defaultProxyConfig = core.getDefaultProxyConfig();
if (defaultProxyConfig != null) {
ChatRoom room =
core.findOneToOneChatRoom(
defaultProxyConfig.getContact(), participant, isSecured);
defaultProxyConfig.getIdentityAddress(), participant, isSecured);
if (room != null) {
((HistoryActivity) getActivity())
.showChatRoom(room.getLocalAddress(), room.getPeerAddress());
......
......@@ -38,6 +38,7 @@ import java.util.List;
import org.linphone.LinphoneContext;
import org.linphone.LinphoneManager;
import org.linphone.R;
import org.linphone.activities.MainActivity;
import org.linphone.call.views.LinphoneLinearLayoutManager;
import org.linphone.contacts.ContactsManager;
import org.linphone.contacts.ContactsUpdatedListener;
......@@ -206,8 +207,7 @@ public class HistoryFragment extends Fragment
address = log.getToAddress();
}
if (address != null) {
LinphoneManager.getCallManager()
.newOutgoingCall(address.asStringUriOnly(), null);
((MainActivity) getActivity()).newOutgoingCall(address.asStringUriOnly());
}
}
}
......
......@@ -36,6 +36,7 @@ import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.Fragment;
import java.util.ArrayList;
import java.util.List;
import org.linphone.LinphoneContext;
import org.linphone.LinphoneManager;
import org.linphone.R;
import org.linphone.activities.AboutActivity;
......@@ -182,6 +183,8 @@ public class SideMenuFragment extends Fragment {
TextView address = mDefaultAccount.findViewById(R.id.main_account_address);
TextView displayName = mDefaultAccount.findViewById(R.id.main_account_display_name);
if (!LinphoneContext.isReady() || LinphoneManager.getCore() == null) return;
ProxyConfig proxy = LinphoneManager.getCore().getDefaultProxyConfig();
if (proxy == null) {
displayName.setText(getString(R.string.no_account));
......
......@@ -42,6 +42,11 @@ public class NotificationBroadcastReceiver extends BroadcastReceiver {
final int notifId = intent.getIntExtra(Compatibility.INTENT_NOTIF_ID, 0);
final String localyIdentity = intent.getStringExtra(Compatibility.INTENT_LOCAL_IDENTITY);
if (!LinphoneContext.isReady()) {
Log.e("[Notification Broadcast Receiver] Context not ready, aborting...");
return;
}
if (intent.getAction().equals(Compatibility.INTENT_REPLY_NOTIF_ACTION)
|| intent.getAction().equals(Compatibility.INTENT_MARK_AS_READ_ACTION)) {
String remoteSipAddr =
......@@ -125,7 +130,7 @@ public class NotificationBroadcastReceiver extends BroadcastReceiver {
}
if (intent.getAction().equals(Compatibility.INTENT_ANSWER_CALL_NOTIF_ACTION)) {
call.accept();
LinphoneManager.getCallManager().acceptCall(call);
} else {
call.terminate();
}
......
/*
* Copyright (c) 2010-2019 Belledonne Communications SARL.
*
* This file is part of linphone-android
* (see https://www.linphone.org).
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
package org.linphone.receivers;
/*
See Linphone (Tasker Plugin)
https://github.com/GrahamJB1/linphone-plugin
*/
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import org.linphone.settings.LinphonePreferences;
public class AccountEnableReceiver extends BroadcastReceiver {
private static final String TAG = "AccountEnableReceiver";
private static final String FIELD_ID = "id";
private static final String FIELD_ACTIVE = "active";
@Override
public void onReceive(Context context, Intent intent) {
int prefsAccountIndex = (int) (long) intent.getLongExtra(FIELD_ID, -1);
boolean enable = intent.getBooleanExtra(FIELD_ACTIVE, true);
Log.i(TAG, "Received broadcast for index=" + prefsAccountIndex + ",enable=" + enable);
if (prefsAccountIndex < 0
|| prefsAccountIndex >= LinphonePreferences.instance().getAccountCount()) return;
LinphonePreferences.instance().setAccountEnabled(prefsAccountIndex, enable);
}
}
......@@ -44,7 +44,6 @@ public final class LinphoneService extends Service {
private Application.ActivityLifecycleCallbacks mActivityCallbacks;
private boolean misLinphoneContextOwned;
@SuppressWarnings("unchecked")
@Override
public void onCreate() {
super.onCreate();
......
......@@ -36,6 +36,7 @@ import org.linphone.core.Core;
import org.linphone.core.CoreListenerStub;
import org.linphone.core.EcCalibratorStatus;
import org.linphone.core.PayloadType;
import org.linphone.core.tools.Log;
import org.linphone.settings.widget.BasicSetting;
import org.linphone.settings.widget.ListSetting;
import org.linphone.settings.widget.SettingListenerBase;
......@@ -113,7 +114,11 @@ public class AudioSettingsFragment extends SettingsFragment {
new SettingListenerBase() {
@Override
public void onTextValueChanged(String newValue) {
mPrefs.setMicGainDb(Float.valueOf(newValue));
try {
mPrefs.setMicGainDb(Float.valueOf(newValue));
} catch (NumberFormatException nfe) {
Log.e("Can't set mic gain, number format exception: " + nfe);
}
}
});
......@@ -121,7 +126,11 @@ public class AudioSettingsFragment extends SettingsFragment {
new SettingListenerBase() {
@Override
public void onTextValueChanged(String newValue) {
mPrefs.setPlaybackGainDb(Float.valueOf(newValue));
try {
mPrefs.setPlaybackGainDb(Float.valueOf(newValue));
} catch (NumberFormatException nfe) {
Log.e("Can't set speaker gain, number format exception: " + nfe);
}
}
});
......@@ -129,14 +138,18 @@ public class AudioSettingsFragment extends SettingsFragment {
new SettingListenerBase() {
@Override
public void onListValueChanged(int position, String newLabel, String newValue) {
int bitrate = Integer.valueOf(newValue);
mPrefs.setCodecBitrateLimit(bitrate);
Core core = LinphoneManager.getCore();
for (final PayloadType pt : core.getAudioPayloadTypes()) {
if (pt.isVbr()) {
pt.setNormalBitrate(bitrate);
try {
int bitrate = Integer.valueOf(newValue);
mPrefs.setCodecBitrateLimit(bitrate);
Core core = LinphoneManager.getCore();
for (final PayloadType pt : core.getAudioPayloadTypes()) {
if (pt.isVbr()) {
pt.setNormalBitrate(bitrate);
}
}
} catch (NumberFormatException nfe) {
Log.e("Can't set codec bitrate limit, number format exception: " + nfe);
}
}
});
......
......@@ -20,6 +20,7 @@
package org.linphone.settings;
import android.Manifest;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
......@@ -223,8 +224,13 @@ public class CallSettingsFragment extends SettingsFragment {
new SettingListenerBase() {
@Override
public void onClicked() {
startActivity(
new Intent("android.settings.NOTIFICATION_POLICY_ACCESS_SETTINGS"));
try {
startActivity(
new Intent(
"android.settings.NOTIFICATION_POLICY_ACCESS_SETTINGS"));
} catch (ActivityNotFoundException anfe) {
Log.e("[Call Settings] Activity not found: ", anfe);
}
}
});
......
......@@ -189,6 +189,7 @@ public class LinphonePreferences {
// App settings
public boolean isFirstLaunch() {
if (getConfig() == null) return true;
return getConfig().getBool("app", "first_launch", true);
}
......@@ -599,12 +600,14 @@ public class LinphonePreferences {
public String getStunServer() {
NatPolicy nat = getOrCreateNatPolicy();
if (nat == null) return null;
return nat.getStunServer();
}
public void setStunServer(String stun) {
if (getLc() == null) return;
NatPolicy nat = getOrCreateNatPolicy();
if (nat == null) return;
nat.setStunServer(stun);
getLc().setNatPolicy(nat);
......@@ -612,12 +615,14 @@ public class LinphonePreferences {
public boolean isIceEnabled() {
NatPolicy nat = getOrCreateNatPolicy();
if (nat == null) return false;
return nat.iceEnabled();
}
public void setIceEnabled(boolean enabled) {
if (getLc() == null) return;
NatPolicy nat = getOrCreateNatPolicy();
if (nat == null) return;
nat.enableIce(enabled);
if (enabled) nat.enableStun(true);
getLc().setNatPolicy(nat);
......@@ -625,24 +630,28 @@ public class LinphonePreferences {
public boolean isTurnEnabled() {
NatPolicy nat = getOrCreateNatPolicy();
if (nat == null) return false;
return nat.turnEnabled();
}
public void setTurnEnabled(boolean enabled) {
if (getLc() == null) return;
NatPolicy nat = getOrCreateNatPolicy();
if (nat == null) return;
nat.enableTurn(enabled);
getLc().setNatPolicy(nat);
}
public String getTurnUsername() {
NatPolicy nat = getOrCreateNatPolicy();
if (nat == null) return null;
return nat.getStunServerUsername();
}
public void setTurnUsername(String username) {
if (getLc() == null) return;
NatPolicy nat = getOrCreateNatPolicy();
if (nat == null) return;
AuthInfo authInfo = getLc().findAuthInfo(null, nat.getStunServerUsername(), null);
if (authInfo != null) {
......@@ -663,6 +672,7 @@ public class LinphonePreferences {
public void setTurnPassword(String password) {
if (getLc() == null) return;
NatPolicy nat = getOrCreateNatPolicy();
if (nat == null) return;
AuthInfo authInfo = getLc().findAuthInfo(null, nat.getStunServerUsername(), null);
if (authInfo != null) {
......
......@@ -198,7 +198,11 @@ public class NetworkSettingsFragment extends SettingsFragment {
mPrefs.powerSaverDialogPrompted(true);
Intent intent = DeviceUtils.getDevicePowerManagerIntent(getActivity());
if (intent != null) {
startActivity(intent);
try {
startActivity(intent);
} catch (SecurityException se) {
Log.e("[Network Settings] Security exception: ", se);
}
}
}
});
......
......@@ -180,12 +180,16 @@ public class FileUtils {
public static String getRealPathFromURI(Context context, Uri contentUri) {
String[] proj = {MediaStore.Images.Media.DATA};
Cursor cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
String result = cursor.getString(column_index);
cursor.close();
return result;
try {
Cursor cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
String result = cursor.getString(column_index);
cursor.close();
return result;
}
} catch (IllegalArgumentException iae) {
Log.e("[File Utils] Failed to get real path from uri: ", iae);
}
return null;
}
......
......@@ -242,20 +242,24 @@ public final class LinphoneUtils {
}
if (username.contains("@")) {
String domain = username.split("@")[1];
ProxyConfig lpc = core.getDefaultProxyConfig();
if (lpc != null) {
if (domain.equals(lpc.getDomain())) {
return username.split("@")[0];
}
} else {
if (domain.equals(
LinphoneContext.instance()
.getApplicationContext()
.getString(R.string.default_domain))) {
return username.split("@")[0];
String[] split = username.split("@");
if (split.length > 1) {
String domain = split[1];
ProxyConfig lpc = core.getDefaultProxyConfig();
if (lpc != null) {
if (domain.equals(lpc.getDomain())) {
return split[0];
}
} else {
if (domain.equals(
LinphoneContext.instance()
.getApplicationContext()
.getString(R.string.default_domain))) {
return split[0];
}
}
}
return split[0];
}
return username;
}
......
......@@ -117,7 +117,6 @@
<SeekBar
android:id="@+id/record_progression_bar"
style="@style/Widget.AppCompat.SeekBar.Discrete"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
......