mirror of
https://github.com/nextcloud/talk-android
synced 2025-03-06 06:15:12 +00:00
More work on joining
Signed-off-by: Mario Danic <mario@lovelyhq.com>
This commit is contained in:
parent
902a1c1885
commit
b46c2362b7
@ -201,6 +201,8 @@ public class CallActivity extends AppCompatActivity {
|
||||
private PulseAnimation pulseAnimation;
|
||||
private View.OnClickListener videoOnClickListener;
|
||||
|
||||
private String baseUrl;
|
||||
|
||||
private static int getSystemUiVisibility() {
|
||||
int flags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN;
|
||||
flags |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
|
||||
@ -236,6 +238,13 @@ public class CallActivity extends AppCompatActivity {
|
||||
callSession = getIntent().getExtras().getString(BundleKeys.KEY_CALL_SESSION, "0");
|
||||
credentials = ApiUtils.getCredentials(userEntity.getUsername(), userEntity.getToken());
|
||||
|
||||
if (getIntent().getExtras().containsKey(BundleKeys.KEY_MODIFIED_BASE_URL)) {
|
||||
credentials = null;
|
||||
baseUrl = getIntent().getExtras().getString(BundleKeys.KEY_MODIFIED_BASE_URL);
|
||||
} else {
|
||||
baseUrl = userEntity.getBaseUrl();
|
||||
}
|
||||
|
||||
callControls.setZ(100.0f);
|
||||
basicInitialization();
|
||||
|
||||
@ -281,7 +290,7 @@ public class CallActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
private void handleFromNotification() {
|
||||
ncApi.getRooms(credentials, ApiUtils.getUrlForGetRooms(userEntity.getBaseUrl()))
|
||||
ncApi.getRooms(credentials, ApiUtils.getUrlForGetRooms(baseUrl))
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Observer<RoomsOverall>() {
|
||||
@ -676,8 +685,7 @@ public class CallActivity extends AppCompatActivity {
|
||||
public void startPullingSignalingMessages() {
|
||||
leavingCall = false;
|
||||
|
||||
ncApi.getSignalingSettings(ApiUtils.getCredentials(userEntity.getUsername(), userEntity.getToken()),
|
||||
ApiUtils.getUrlForSignalingSettings(userEntity.getBaseUrl()))
|
||||
ncApi.getSignalingSettings(credentials, ApiUtils.getUrlForSignalingSettings(baseUrl))
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Observer<SignalingSettingsOverall>() {
|
||||
@ -737,7 +745,7 @@ public class CallActivity extends AppCompatActivity {
|
||||
|
||||
private void joinRoomAndCall() {
|
||||
if (callSession.equals("0")) {
|
||||
ncApi.joinRoom(credentials, ApiUtils.getUrlForRoomParticipants(userEntity.getBaseUrl(), roomToken), null)
|
||||
ncApi.joinRoom(credentials, ApiUtils.getUrlForRoomParticipants(baseUrl, roomToken), null)
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.retry(3)
|
||||
@ -769,7 +777,7 @@ public class CallActivity extends AppCompatActivity {
|
||||
|
||||
private void performCall(@Nullable String callSessionId) {
|
||||
ncApi.joinCall(credentials,
|
||||
ApiUtils.getUrlForCall(userEntity.getBaseUrl(), roomToken))
|
||||
ApiUtils.getUrlForCall(baseUrl, roomToken))
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.retry(3)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
@ -787,8 +795,7 @@ public class CallActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
// start pinging the call
|
||||
ncApi.pingCall(ApiUtils.getCredentials(userEntity.getUsername(), userEntity.getToken()),
|
||||
ApiUtils.getUrlForCallPing(userEntity.getBaseUrl(), roomToken))
|
||||
ncApi.pingCall(credentials, ApiUtils.getUrlForCallPing(baseUrl, roomToken))
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.repeatWhen(observable -> observable.delay(5000, TimeUnit.MILLISECONDS))
|
||||
@ -817,8 +824,7 @@ public class CallActivity extends AppCompatActivity {
|
||||
});
|
||||
|
||||
// Start pulling signaling messages
|
||||
ncApi.pullSignalingMessages(ApiUtils.getCredentials(userEntity.getUsername(),
|
||||
userEntity.getToken()), ApiUtils.getUrlForSignaling(userEntity.getBaseUrl()))
|
||||
ncApi.pullSignalingMessages(credentials, ApiUtils.getUrlForSignaling(baseUrl))
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.repeatWhen(observable -> observable)
|
||||
@ -945,8 +951,7 @@ public class CallActivity extends AppCompatActivity {
|
||||
Set<String> oldSesssions = new HashSet<>();
|
||||
|
||||
for (HashMap<String, String> participant : users) {
|
||||
if (!participant.get("sessionId").equals(callSession) && !participant.get("userId").equals(userEntity
|
||||
.getUserId())) {
|
||||
if (!participant.get("sessionId").equals(callSession)) {
|
||||
Object inCallObject = participant.get("inCall");
|
||||
if ((boolean) inCallObject) {
|
||||
newSessions.add(participant.get("sessionId"));
|
||||
@ -1050,7 +1055,7 @@ public class CallActivity extends AppCompatActivity {
|
||||
localAudioTrack = null;
|
||||
localVideoTrack = null;
|
||||
|
||||
if (!dueToNetworkChange) {
|
||||
if (!dueToNetworkChange && credentials != null) {
|
||||
hangupNetworkCalls();
|
||||
} else {
|
||||
finish();
|
||||
@ -1058,8 +1063,7 @@ public class CallActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
private void hangupNetworkCalls() {
|
||||
String credentials = ApiUtils.getCredentials(userEntity.getUsername(), userEntity.getToken());
|
||||
ncApi.leaveCall(credentials, ApiUtils.getUrlForCall(userEntity.getBaseUrl(), roomToken))
|
||||
ncApi.leaveCall(credentials, ApiUtils.getUrlForCall(baseUrl, roomToken))
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Observer<GenericOverall>() {
|
||||
@ -1070,7 +1074,7 @@ public class CallActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
public void onNext(GenericOverall genericOverall) {
|
||||
ncApi.leaveRoom(credentials, ApiUtils.getUrlForRoomParticipants(userEntity.getBaseUrl(), roomToken))
|
||||
ncApi.leaveRoom(credentials, ApiUtils.getUrlForRoomParticipants(baseUrl, roomToken))
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Observer<GenericOverall>() {
|
||||
@ -1277,7 +1281,6 @@ public class CallActivity extends AppCompatActivity {
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.BACKGROUND)
|
||||
public void onMessageEvent(SessionDescriptionSendEvent sessionDescriptionSend) throws IOException {
|
||||
String credentials = ApiUtils.getCredentials(userEntity.getUsername(), userEntity.getToken());
|
||||
NCMessageWrapper ncMessageWrapper = new NCMessageWrapper();
|
||||
ncMessageWrapper.setEv("message");
|
||||
ncMessageWrapper.setSessionId(callSession);
|
||||
@ -1317,7 +1320,7 @@ public class CallActivity extends AppCompatActivity {
|
||||
String stringToSend = stringBuilder.toString();
|
||||
strings.add(stringToSend);
|
||||
|
||||
ncApi.sendSignalingMessages(credentials, ApiUtils.getUrlForSignaling(userEntity.getBaseUrl()),
|
||||
ncApi.sendSignalingMessages(credentials, ApiUtils.getUrlForSignaling(baseUrl),
|
||||
strings.toString())
|
||||
.retry(3)
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
@ -1427,7 +1430,7 @@ public class CallActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
hangup(false);
|
||||
onHangupClick();
|
||||
}
|
||||
|
||||
private class microphoneButtonTouchListener implements View.OnTouchListener {
|
||||
|
@ -143,34 +143,34 @@ public interface NcApi {
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST
|
||||
Observable<CallOverall> joinRoom(@Header("Authorization") String authorization, @Url String url,
|
||||
Observable<CallOverall> joinRoom(@Nullable @Header("Authorization") String authorization, @Url String url,
|
||||
@Nullable @Field("password") String password);
|
||||
|
||||
@DELETE
|
||||
Observable<GenericOverall> leaveRoom(@Header("Authorization") String authorization, @Url String url);
|
||||
Observable<GenericOverall> leaveRoom(@Nullable @Header("Authorization") String authorization, @Url String url);
|
||||
|
||||
/*
|
||||
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /call/callToken
|
||||
*/
|
||||
|
||||
@POST
|
||||
Observable<GenericOverall> joinCall(@Header("Authorization") String authorization, @Url String url);
|
||||
Observable<GenericOverall> joinCall(@Nullable @Header("Authorization") String authorization, @Url String url);
|
||||
|
||||
/*
|
||||
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /call/callToken
|
||||
*/
|
||||
@DELETE
|
||||
Observable<GenericOverall> leaveCall(@Header("Authorization") String authorization, @Url String url);
|
||||
Observable<GenericOverall> leaveCall(@Nullable @Header("Authorization") String authorization, @Url String url);
|
||||
|
||||
/*
|
||||
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /call/callToken/ping
|
||||
*/
|
||||
@POST
|
||||
Observable<GenericOverall> pingCall(@Header("Authorization") String authorization, @Url String url);
|
||||
Observable<GenericOverall> pingCall(@Nullable @Header("Authorization") String authorization, @Url String url);
|
||||
|
||||
@GET
|
||||
Observable<SignalingSettingsOverall> getSignalingSettings(@Header("Authorization") String authorization, @Url
|
||||
String url);
|
||||
Observable<SignalingSettingsOverall> getSignalingSettings(@Nullable @Header("Authorization") String authorization,
|
||||
@Url String url);
|
||||
|
||||
/*
|
||||
QueryMap items are as follows:
|
||||
@ -180,14 +180,16 @@ public interface NcApi {
|
||||
*/
|
||||
@FormUrlEncoded
|
||||
@POST
|
||||
Observable<SignalingOverall> sendSignalingMessages(@Header("Authorization") String authorization, @Url String url,
|
||||
Observable<SignalingOverall> sendSignalingMessages(@Nullable@Header("Authorization") String authorization, @Url String url,
|
||||
@Field("messages") String messages);
|
||||
|
||||
/*
|
||||
Server URL is: baseUrl + ocsApiVersion + spreedApiVersion + /signaling
|
||||
*/
|
||||
@GET
|
||||
Observable<SignalingOverall> pullSignalingMessages(@Header("Authorization") String authorization, @Url String url);
|
||||
Observable<SignalingOverall> pullSignalingMessages(@Nullable @Header("Authorization") String authorization, @Url
|
||||
String
|
||||
url);
|
||||
|
||||
/*
|
||||
QueryMap items are as follows:
|
||||
|
@ -113,6 +113,31 @@ public class NextcloudTalkApplication extends MultiDexApplication implements Pro
|
||||
super.onCreate();
|
||||
ProviderInstaller.installIfNeededAsync(this, this);
|
||||
|
||||
/*if (Build.MANUFACTURER.equalsIgnoreCase("huawei")) {
|
||||
try {
|
||||
Class<?> enclosingClass = Class.forName("com.huawei.systemmanager.startupmgr.db.StartupDataMgrHelper");
|
||||
Method method = enclosingClass.getMethod("modifyNormalStartupInfoStatus", Context.class, String.class, boolean.class);
|
||||
method.invoke(null, getApplicationContext(), getPackageName(), true);
|
||||
|
||||
Class<?> secondaryEnclosingClass = Class.forName("com.huawei.systemmanager.optimize.process" +
|
||||
".ProtectAppControl");
|
||||
Method secondaryMethod = secondaryEnclosingClass.getMethod("getInstance", Context.class);
|
||||
Object object = secondaryMethod.invoke(null, getApplicationContext());
|
||||
Method thirdMethod = secondaryEnclosingClass.getMethod("setNoProtect", List.class);
|
||||
List<String> packageNames = new ArrayList<>();
|
||||
packageNames.add(getPackageName());
|
||||
thirdMethod.invoke(object, packageNames);
|
||||
} catch (ClassNotFoundException e) {
|
||||
Log.e(TAG, "Failed to find the required class on Huawei");
|
||||
} catch (NoSuchMethodException e) {
|
||||
Log.e(TAG, "Failed to find the appropriate method");
|
||||
} catch (IllegalAccessException e) {
|
||||
Log.e(TAG, "Illegal access exception");
|
||||
} catch (InvocationTargetException e) {
|
||||
Log.e(TAG, "Invocation target exception");
|
||||
}
|
||||
}*/
|
||||
|
||||
JobManager.create(this).addJobCreator(new MagicJobCreator());
|
||||
FirebaseAnalytics.getInstance(this).setAnalyticsCollectionEnabled(false);
|
||||
|
||||
@ -138,6 +163,8 @@ public class NextcloudTalkApplication extends MultiDexApplication implements Pro
|
||||
}
|
||||
|
||||
|
||||
private void prepareThingsForStrangePhones() {
|
||||
}
|
||||
@Override
|
||||
public void onTerminate() {
|
||||
super.onTerminate();
|
||||
|
@ -231,16 +231,9 @@ public class CallsListController extends BaseController implements SearchView.On
|
||||
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_new_conversation:
|
||||
searchItem.setVisible(false);
|
||||
menuVariable.findItem(R.id.action_new_conversation).setVisible(false);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putBoolean(BundleKeys.KEY_NEW_CONVERSATION, true);
|
||||
if (getParentController() != null) {
|
||||
getParentController().getRouter().pushController(
|
||||
(RouterTransaction.with(new ContactsController(bundle))
|
||||
.pushChangeHandler(new VerticalChangeHandler())
|
||||
.popChangeHandler(new VerticalChangeHandler())));
|
||||
}
|
||||
bundle.putParcelable(BundleKeys.KEY_MENU_TYPE, Parcels.wrap(CallMenuController.MenuType.NEW_CONVERSATION));
|
||||
prepareAndShowBottomSheetWithBundle(bundle, true);
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
@ -445,6 +438,7 @@ public class CallsListController extends BaseController implements SearchView.On
|
||||
Bundle bundle = new Bundle();
|
||||
Room room = moreMenuClickEvent.getRoom();
|
||||
bundle.putParcelable(BundleKeys.KEY_ROOM, Parcels.wrap(room));
|
||||
bundle.putParcelable(BundleKeys.KEY_MENU_TYPE, Parcels.wrap(CallMenuController.MenuType.REGULAR));
|
||||
|
||||
prepareAndShowBottomSheetWithBundle(bundle, true);
|
||||
}
|
||||
@ -455,13 +449,13 @@ public class CallsListController extends BaseController implements SearchView.On
|
||||
if (shouldShowCallMenuController) {
|
||||
getChildRouter((ViewGroup) view).setRoot(
|
||||
RouterTransaction.with(new CallMenuController(bundle))
|
||||
.popChangeHandler(new HorizontalChangeHandler())
|
||||
.pushChangeHandler(new HorizontalChangeHandler()));
|
||||
.popChangeHandler(new VerticalChangeHandler())
|
||||
.pushChangeHandler(new VerticalChangeHandler()));
|
||||
} else {
|
||||
getChildRouter((ViewGroup) view).setRoot(
|
||||
RouterTransaction.with(new EntryMenuController(bundle))
|
||||
.popChangeHandler(new HorizontalChangeHandler())
|
||||
.pushChangeHandler(new HorizontalChangeHandler()));
|
||||
.popChangeHandler(new VerticalChangeHandler())
|
||||
.pushChangeHandler(new VerticalChangeHandler()));
|
||||
}
|
||||
|
||||
boolean isNew = false;
|
||||
|
@ -32,11 +32,14 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.bluelinelabs.conductor.RouterTransaction;
|
||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
|
||||
import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler;
|
||||
import com.kennyc.bottomsheet.adapters.AppAdapter;
|
||||
import com.nextcloud.talk.R;
|
||||
import com.nextcloud.talk.adapters.items.AppItem;
|
||||
import com.nextcloud.talk.adapters.items.MenuItem;
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
||||
import com.nextcloud.talk.controllers.ContactsController;
|
||||
import com.nextcloud.talk.controllers.base.BaseController;
|
||||
import com.nextcloud.talk.events.BottomSheetLockEvent;
|
||||
import com.nextcloud.talk.models.json.rooms.Room;
|
||||
@ -45,6 +48,7 @@ import com.nextcloud.talk.utils.bundle.BundleKeys;
|
||||
import com.nextcloud.talk.utils.database.user.UserUtils;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.parceler.Parcel;
|
||||
import org.parceler.Parcels;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -73,14 +77,19 @@ public class CallMenuController extends BaseController implements FlexibleAdapte
|
||||
private List<AbstractFlexibleItem> menuItems;
|
||||
private FlexibleAdapter<AbstractFlexibleItem> adapter;
|
||||
|
||||
private boolean isShare;
|
||||
@Parcel
|
||||
public enum MenuType {
|
||||
REGULAR, SHARE, NEW_CONVERSATION
|
||||
}
|
||||
|
||||
private MenuType menuType;
|
||||
private Intent shareIntent;
|
||||
|
||||
public CallMenuController(Bundle args) {
|
||||
super(args);
|
||||
this.room = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_ROOM));
|
||||
if (args.containsKey(BundleKeys.KEY_IS_SHARE)) {
|
||||
this.isShare = true;
|
||||
if (args.containsKey(BundleKeys.KEY_MENU_TYPE)) {
|
||||
this.menuType = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_MENU_TYPE));
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,7 +133,7 @@ public class CallMenuController extends BaseController implements FlexibleAdapte
|
||||
private void prepareMenu() {
|
||||
menuItems = new ArrayList<>();
|
||||
|
||||
if (!isShare) {
|
||||
if (menuType.equals(MenuType.REGULAR)) {
|
||||
menuItems.add(new MenuItem(getResources().getString(R.string.nc_what), 0));
|
||||
|
||||
menuItems.add(new MenuItem(getResources().getString(R.string.nc_leave), 1));
|
||||
@ -156,7 +165,7 @@ public class CallMenuController extends BaseController implements FlexibleAdapte
|
||||
if (room.isDeletable()) {
|
||||
menuItems.add(new MenuItem(getResources().getString(R.string.nc_delete_call), 9));
|
||||
}
|
||||
} else {
|
||||
} else if (menuType.equals(MenuType.SHARE)) {
|
||||
prepareIntent();
|
||||
List<AppAdapter.AppInfo> appInfoList = ShareUtils.getShareApps(getActivity(), shareIntent, null,
|
||||
null);
|
||||
@ -167,6 +176,10 @@ public class CallMenuController extends BaseController implements FlexibleAdapte
|
||||
menuItems.add(new AppItem(appInfo.title, appInfo.packageName, appInfo.name, appInfo.drawable));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
menuItems.add(new MenuItem(getResources().getString(R.string.nc_what), 0));
|
||||
menuItems.add(new MenuItem(getResources().getString(R.string.nc_new_conversation), 1));
|
||||
menuItems.add(new MenuItem(getResources().getString(R.string.nc_join_via_link), 2));
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,7 +188,7 @@ public class CallMenuController extends BaseController implements FlexibleAdapte
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putParcelable(BundleKeys.KEY_ROOM, Parcels.wrap(room));
|
||||
|
||||
if (!isShare) {
|
||||
if (menuType.equals(MenuType.REGULAR)) {
|
||||
MenuItem menuItem = (MenuItem) adapter.getItem(position);
|
||||
if (menuItem != null) {
|
||||
|
||||
@ -188,16 +201,22 @@ public class CallMenuController extends BaseController implements FlexibleAdapte
|
||||
bundle.putInt(BundleKeys.KEY_OPERATION_CODE, tag);
|
||||
if (tag != 2 && tag != 4 && tag != 6 && tag != 7) {
|
||||
eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
|
||||
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle)));
|
||||
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle))
|
||||
.pushChangeHandler(new HorizontalChangeHandler())
|
||||
.popChangeHandler(new HorizontalChangeHandler()));
|
||||
} else if (tag != 7) {
|
||||
getRouter().pushController(RouterTransaction.with(new EntryMenuController(bundle)));
|
||||
getRouter().pushController(RouterTransaction.with(new EntryMenuController(bundle))
|
||||
.pushChangeHandler(new VerticalChangeHandler())
|
||||
.popChangeHandler(new VerticalChangeHandler()));
|
||||
} else {
|
||||
bundle.putBoolean(BundleKeys.KEY_IS_SHARE, true);
|
||||
getRouter().pushController(RouterTransaction.with(new CallMenuController(bundle)));
|
||||
bundle.putParcelable(BundleKeys.KEY_MENU_TYPE, Parcels.wrap(MenuType.SHARE));
|
||||
getRouter().pushController(RouterTransaction.with(new CallMenuController(bundle))
|
||||
.pushChangeHandler(new VerticalChangeHandler())
|
||||
.popChangeHandler(new VerticalChangeHandler()));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (position != 0) {
|
||||
} else if (menuType.equals(MenuType.SHARE) && position != 0) {
|
||||
AppItem appItem = (AppItem) adapter.getItem(position);
|
||||
if (appItem != null && getActivity() != null) {
|
||||
if (!room.hasPassword) {
|
||||
@ -213,7 +232,30 @@ public class CallMenuController extends BaseController implements FlexibleAdapte
|
||||
bundle.putParcelable(BundleKeys.KEY_SHARE_INTENT, Parcels.wrap(shareIntent));
|
||||
bundle.putString(BundleKeys.KEY_APP_ITEM_PACKAGE_NAME, appItem.getPackageName());
|
||||
bundle.putString(BundleKeys.KEY_APP_ITEM_NAME, appItem.getName());
|
||||
getRouter().pushController(RouterTransaction.with(new EntryMenuController(bundle)));
|
||||
getRouter().pushController(RouterTransaction.with(new EntryMenuController(bundle))
|
||||
.pushChangeHandler(new VerticalChangeHandler())
|
||||
.popChangeHandler(new VerticalChangeHandler()));
|
||||
}
|
||||
}
|
||||
} else if (menuType.equals(MenuType.NEW_CONVERSATION) && position != 0) {
|
||||
MenuItem menuItem = (MenuItem) adapter.getItem(position);
|
||||
if (menuItem != null) {
|
||||
if (menuItem.getTag() == 1) {
|
||||
eventBus.post(new BottomSheetLockEvent(true, 0, false, true));
|
||||
bundle = new Bundle();
|
||||
bundle.putBoolean(BundleKeys.KEY_NEW_CONVERSATION, true);
|
||||
if (getParentController() != null && getParentController().getParentController() != null) {
|
||||
getParentController().getParentController().getRouter().pushController(
|
||||
(RouterTransaction.with(new ContactsController(bundle))
|
||||
.pushChangeHandler(new VerticalChangeHandler())
|
||||
.popChangeHandler(new VerticalChangeHandler())));
|
||||
}
|
||||
} else {
|
||||
bundle = new Bundle();
|
||||
bundle.putInt(BundleKeys.KEY_OPERATION_CODE, 10);
|
||||
getRouter().pushController(RouterTransaction.with(new EntryMenuController(bundle))
|
||||
.pushChangeHandler(new HorizontalChangeHandler())
|
||||
.popChangeHandler(new HorizontalChangeHandler()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.Button;
|
||||
|
||||
import com.bluelinelabs.conductor.RouterTransaction;
|
||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
|
||||
import com.nextcloud.talk.R;
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
||||
import com.nextcloud.talk.controllers.base.BaseController;
|
||||
@ -84,7 +85,9 @@ public class EntryMenuController extends BaseController {
|
||||
public EntryMenuController(Bundle args) {
|
||||
super(args);
|
||||
this.operationCode = args.getInt(BundleKeys.KEY_OPERATION_CODE);
|
||||
this.room = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_ROOM));
|
||||
if (args.containsKey(BundleKeys.KEY_ROOM)) {
|
||||
this.room = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_ROOM));
|
||||
}
|
||||
|
||||
if (args.containsKey(BundleKeys.KEY_SHARE_INTENT)) {
|
||||
this.shareIntent = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_SHARE_INTENT));
|
||||
@ -123,12 +126,13 @@ public class EntryMenuController extends BaseController {
|
||||
eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
|
||||
bundle = new Bundle();
|
||||
bundle.putParcelable(BundleKeys.KEY_ROOM, Parcels.wrap(room));
|
||||
bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, Parcels.wrap(userEntity));
|
||||
bundle.putString(BundleKeys.KEY_CALL_PASSWORD, editText.getText().toString());
|
||||
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle)));
|
||||
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle))
|
||||
.pushChangeHandler(new HorizontalChangeHandler())
|
||||
.popChangeHandler(new HorizontalChangeHandler()));
|
||||
}
|
||||
|
||||
} else if (operationCode != 7) {
|
||||
} else if (operationCode != 7 && operationCode != 10) {
|
||||
eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
|
||||
bundle = new Bundle();
|
||||
if (operationCode == 4 || operationCode == 6) {
|
||||
@ -138,8 +142,10 @@ public class EntryMenuController extends BaseController {
|
||||
}
|
||||
bundle.putParcelable(BundleKeys.KEY_ROOM, Parcels.wrap(room));
|
||||
bundle.putInt(BundleKeys.KEY_OPERATION_CODE, operationCode);
|
||||
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle)));
|
||||
} else {
|
||||
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle))
|
||||
.pushChangeHandler(new HorizontalChangeHandler())
|
||||
.popChangeHandler(new HorizontalChangeHandler()));
|
||||
} else if (operationCode == 7) {
|
||||
if (getActivity() != null) {
|
||||
shareIntent.putExtra(Intent.EXTRA_TEXT, ShareUtils.getStringForIntent(getActivity(),
|
||||
editText.getText().toString(), userUtils, room));
|
||||
@ -149,6 +155,15 @@ public class EntryMenuController extends BaseController {
|
||||
getActivity().startActivity(intent);
|
||||
eventBus.post(new BottomSheetLockEvent(true, 0, false, true));
|
||||
}
|
||||
} else {
|
||||
eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
|
||||
bundle = new Bundle();
|
||||
bundle.putInt(BundleKeys.KEY_OPERATION_CODE, operationCode);
|
||||
bundle.putString(BundleKeys.KEY_CALL_URL, editText.getText().toString());
|
||||
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle))
|
||||
.pushChangeHandler(new HorizontalChangeHandler())
|
||||
.popChangeHandler(new HorizontalChangeHandler()));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -193,11 +208,27 @@ public class EntryMenuController extends BaseController {
|
||||
textFieldBoxes.setError(getResources().getString(R.string.nc_call_name_is_same),
|
||||
true);
|
||||
}
|
||||
} else {
|
||||
} else if (operationCode != 10) {
|
||||
if (!proceedButton.isEnabled()) {
|
||||
proceedButton.setEnabled(true);
|
||||
proceedButton.setAlpha(1.0f);
|
||||
}
|
||||
} else if (editText.getText().toString().startsWith("http://") ||
|
||||
editText.getText().toString().startsWith("https://") &&
|
||||
editText.getText().toString().contains("/call/")) {
|
||||
// operation code 10
|
||||
if (!proceedButton.isEnabled()) {
|
||||
proceedButton.setEnabled(true);
|
||||
proceedButton.setAlpha(1.0f);
|
||||
|
||||
}
|
||||
} else {
|
||||
if (proceedButton.isEnabled()) {
|
||||
proceedButton.setEnabled(false);
|
||||
proceedButton.setAlpha(0.7f);
|
||||
}
|
||||
textFieldBoxes.setError(getResources().getString(R.string.nc_wrong_link),
|
||||
true);
|
||||
}
|
||||
} else {
|
||||
if (proceedButton.isEnabled()) {
|
||||
@ -219,8 +250,12 @@ public class EntryMenuController extends BaseController {
|
||||
case 6:
|
||||
case 7:
|
||||
case 99:
|
||||
// 99 is joining a room via password
|
||||
labelText = getResources().getString(R.string.nc_password);
|
||||
break;
|
||||
case 10:
|
||||
labelText = getResources().getString(R.string.nc_conversation_link);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -39,8 +39,8 @@ import com.nextcloud.talk.application.NextcloudTalkApplication;
|
||||
import com.nextcloud.talk.controllers.base.BaseController;
|
||||
import com.nextcloud.talk.events.BottomSheetLockEvent;
|
||||
import com.nextcloud.talk.models.database.UserEntity;
|
||||
import com.nextcloud.talk.models.json.call.CallOverall;
|
||||
import com.nextcloud.talk.models.json.rooms.Room;
|
||||
import com.nextcloud.talk.models.json.rooms.RoomOverall;
|
||||
import com.nextcloud.talk.utils.ApiUtils;
|
||||
import com.nextcloud.talk.utils.ApplicationWideMessageHolder;
|
||||
import com.nextcloud.talk.utils.DisplayUtils;
|
||||
@ -90,21 +90,21 @@ public class OperationsMenuController extends BaseController {
|
||||
|
||||
private UserEntity userEntity;
|
||||
private String callPassword;
|
||||
private String callUrl;
|
||||
|
||||
private String baseUrl;
|
||||
|
||||
private Disposable disposable;
|
||||
private Disposable secondaryDisposable;
|
||||
|
||||
private int retryCount = 0;
|
||||
|
||||
public OperationsMenuController(Bundle args) {
|
||||
super(args);
|
||||
this.operationCode = args.getInt(BundleKeys.KEY_OPERATION_CODE);
|
||||
this.room = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_ROOM));
|
||||
if (args.containsKey(BundleKeys.KEY_ROOM)) {
|
||||
this.room = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_ROOM));
|
||||
}
|
||||
|
||||
this.callPassword = args.getString(BundleKeys.KEY_CALL_PASSWORD, "");
|
||||
if (args.containsKey(BundleKeys.KEY_USER_ENTITY)) {
|
||||
this.userEntity = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_USER_ENTITY));
|
||||
}
|
||||
this.callUrl = args.getString(BundleKeys.KEY_CALL_URL, "");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -121,7 +121,7 @@ public class OperationsMenuController extends BaseController {
|
||||
}
|
||||
|
||||
private void processOperation() {
|
||||
UserEntity userEntity = userUtils.getCurrentUser();
|
||||
userEntity = userUtils.getCurrentUser();
|
||||
OperationsObserver operationsObserver = new OperationsObserver();
|
||||
if (userEntity != null) {
|
||||
String credentials = ApiUtils.getCredentials(userEntity.getUsername(), userEntity.getToken());
|
||||
@ -181,6 +181,46 @@ public class OperationsMenuController extends BaseController {
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.retry(1)
|
||||
.subscribe(operationsObserver);
|
||||
case 10:
|
||||
String conversationToken = callUrl.substring(callUrl.lastIndexOf("/") + 1, callUrl.length());
|
||||
if (callUrl.contains("/index.php")) {
|
||||
baseUrl = callUrl.substring(0, callUrl.indexOf("/index.php"));
|
||||
} else {
|
||||
baseUrl = callUrl.substring(0, callUrl.indexOf("/call"));
|
||||
}
|
||||
|
||||
ncApi.getRoom(credentials, ApiUtils.getRoom(baseUrl, conversationToken))
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.retry(1)
|
||||
.subscribe(new Observer<RoomOverall>() {
|
||||
@Override
|
||||
public void onSubscribe(Disposable d) {
|
||||
disposable = d;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(RoomOverall roomOverall) {
|
||||
room = roomOverall.getOcs().getData();
|
||||
if (room.isHasPassword() && room.isGuest()) {
|
||||
|
||||
} else {
|
||||
initiateCall();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable e) {
|
||||
showResultImage(false, false);
|
||||
dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete() {
|
||||
dispose();
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 99:
|
||||
ncApi.joinRoom(credentials, ApiUtils.getUrlForRoomParticipants(userEntity.getBaseUrl(), room.getToken()),
|
||||
callPassword)
|
||||
@ -195,7 +235,7 @@ public class OperationsMenuController extends BaseController {
|
||||
}
|
||||
}
|
||||
|
||||
private void showResultImage(boolean everythingOK) {
|
||||
private void showResultImage(boolean everythingOK, boolean isSignalingSettingsError) {
|
||||
progressBar.setVisibility(View.GONE);
|
||||
|
||||
if (everythingOK) {
|
||||
@ -212,7 +252,11 @@ public class OperationsMenuController extends BaseController {
|
||||
resultsTextView.setText(R.string.nc_all_ok_operation);
|
||||
} else {
|
||||
resultsTextView.setTextColor(getResources().getColor(R.color.nc_darkRed));
|
||||
resultsTextView.setText(R.string.nc_failed_to_perform_operation);
|
||||
if (!isSignalingSettingsError) {
|
||||
resultsTextView.setText(R.string.nc_failed_to_perform_operation);
|
||||
} else {
|
||||
resultsTextView.setText(R.string.nc_failed_signaling_settings);
|
||||
}
|
||||
}
|
||||
|
||||
resultsTextView.setVisibility(View.VISIBLE);
|
||||
@ -221,8 +265,8 @@ public class OperationsMenuController extends BaseController {
|
||||
} else {
|
||||
resultImageView.setImageDrawable(DisplayUtils.getTintedDrawable(getResources(), R.drawable
|
||||
.ic_cancel_black_24dp, R.color.nc_darkRed));
|
||||
okButton.setOnClickListener(v -> eventBus.post(new BottomSheetLockEvent(true, 0, operationCode != 99,
|
||||
true)));
|
||||
okButton.setOnClickListener(v -> eventBus.post(new BottomSheetLockEvent(true, 0, operationCode != 99
|
||||
&& operationCode != 10, true)));
|
||||
okButton.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
@ -241,35 +285,41 @@ public class OperationsMenuController extends BaseController {
|
||||
dispose();
|
||||
}
|
||||
|
||||
private void initiateCall() {
|
||||
eventBus.post(new BottomSheetLockEvent(true, 0, false, true));
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(BundleKeys.KEY_ROOM_TOKEN, room.getToken());
|
||||
bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, Parcels.wrap(userEntity));
|
||||
if (!baseUrl.equals(userEntity.getBaseUrl())) {
|
||||
bundle.putString(BundleKeys.KEY_MODIFIED_BASE_URL, baseUrl);
|
||||
}
|
||||
overridePushHandler(new NoOpControllerChangeHandler());
|
||||
overridePopHandler(new NoOpControllerChangeHandler());
|
||||
Intent callIntent = new Intent(getActivity(), CallActivity.class);
|
||||
callIntent.putExtras(bundle);
|
||||
startActivity(callIntent);
|
||||
}
|
||||
|
||||
private class OperationsObserver implements Observer {
|
||||
|
||||
@Override
|
||||
public void onSubscribe(Disposable d) {
|
||||
disposable = d;
|
||||
retryCount++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(Object o) {
|
||||
if (operationCode != 99) {
|
||||
showResultImage(true);
|
||||
showResultImage(true, false);
|
||||
} else {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(BundleKeys.KEY_ROOM_TOKEN, room.getToken());
|
||||
bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, Parcels.wrap(userEntity));
|
||||
bundle.putString(BundleKeys.KEY_CALL_SESSION, ((CallOverall) o).getOcs().getData().getSessionId());
|
||||
overridePushHandler(new NoOpControllerChangeHandler());
|
||||
overridePopHandler(new NoOpControllerChangeHandler());
|
||||
Intent callIntent = new Intent(getActivity(), CallActivity.class);
|
||||
callIntent.putExtras(bundle);
|
||||
startActivity(callIntent);
|
||||
initiateCall();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable e) {
|
||||
if (operationCode != 99 || !(e instanceof HttpException)) {
|
||||
showResultImage(false);
|
||||
showResultImage(false, false);
|
||||
} else {
|
||||
if (((HttpException) e).response().code() == 403) {
|
||||
eventBus.post(new BottomSheetLockEvent(true, 0, false,
|
||||
@ -277,7 +327,7 @@ public class OperationsMenuController extends BaseController {
|
||||
ApplicationWideMessageHolder.getInstance().setMessageType(ApplicationWideMessageHolder.MessageType.CALL_PASSWORD_WRONG);
|
||||
getRouter().popCurrentController();
|
||||
} else {
|
||||
showResultImage(false);
|
||||
showResultImage(false, false);
|
||||
}
|
||||
}
|
||||
dispose();
|
||||
|
222
app/src/main/java/com/nextcloud/talk/jobs/NotificationJob.java
Normal file
222
app/src/main/java/com/nextcloud/talk/jobs/NotificationJob.java
Normal file
@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Mario Danic
|
||||
* Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
||||
*
|
||||
* 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 com.nextcloud.talk.jobs;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.media.RingtoneManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
|
||||
import com.bluelinelabs.logansquare.LoganSquare;
|
||||
import com.evernote.android.job.Job;
|
||||
import com.evernote.android.job.util.support.PersistableBundleCompat;
|
||||
import com.nextcloud.talk.R;
|
||||
import com.nextcloud.talk.activities.CallActivity;
|
||||
import com.nextcloud.talk.models.SignatureVerification;
|
||||
import com.nextcloud.talk.models.json.push.DecryptedPushMessage;
|
||||
import com.nextcloud.talk.models.json.push.PushMessage;
|
||||
import com.nextcloud.talk.utils.NotificationUtils;
|
||||
import com.nextcloud.talk.utils.PushUtils;
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys;
|
||||
|
||||
import org.parceler.Parcels;
|
||||
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.util.Calendar;
|
||||
import java.util.zip.CRC32;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
|
||||
public class NotificationJob extends Job {
|
||||
public static final String TAG = "NotificationJob";
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected Result onRunJob(Params params) {
|
||||
Context context = getContext();
|
||||
PersistableBundleCompat persistableBundleCompat = getParams().getExtras();
|
||||
String subject = persistableBundleCompat.getString(BundleKeys.KEY_NOTIFICATION_SUBJECT, "");
|
||||
String signature = persistableBundleCompat.getString(BundleKeys.KEY_NOTIFICATION_SIGNATURE, "");
|
||||
|
||||
if (!TextUtils.isEmpty(subject) && !TextUtils.isEmpty(signature)) {
|
||||
|
||||
try {
|
||||
PushMessage pushMessage = new PushMessage();
|
||||
pushMessage.setSubject(subject);
|
||||
pushMessage.setSignature(signature);
|
||||
|
||||
byte[] base64DecodedSubject = Base64.decode(pushMessage.getSubject(), Base64.DEFAULT);
|
||||
byte[] base64DecodedSignature = Base64.decode(pushMessage.getSignature(), Base64.DEFAULT);
|
||||
PushUtils pushUtils = new PushUtils();
|
||||
PrivateKey privateKey = (PrivateKey) pushUtils.readKeyFromFile(false);
|
||||
|
||||
try {
|
||||
SignatureVerification signatureVerification = pushUtils.verifySignature(base64DecodedSignature,
|
||||
base64DecodedSubject);
|
||||
|
||||
if (signatureVerification.isSignatureValid()) {
|
||||
Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding");
|
||||
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||
byte[] decryptedSubject = cipher.doFinal(base64DecodedSubject);
|
||||
DecryptedPushMessage decryptedPushMessage = LoganSquare.parse(new String(decryptedSubject),
|
||||
DecryptedPushMessage.class);
|
||||
|
||||
if (decryptedPushMessage.getApp().equals("spreed")) {
|
||||
int smallIcon;
|
||||
Bitmap largeIcon;
|
||||
String category = "";
|
||||
int priority = Notification.PRIORITY_DEFAULT;
|
||||
Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
|
||||
|
||||
Intent intent = new Intent(context, CallActivity.class);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(BundleKeys.KEY_ROOM_TOKEN, decryptedPushMessage.getId());
|
||||
bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, Parcels.wrap(signatureVerification
|
||||
.getUserEntity()));
|
||||
bundle.putBoolean("fromNotification", true);
|
||||
intent.putExtras(bundle);
|
||||
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(context,
|
||||
0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
|
||||
|
||||
NotificationManager notificationManager =
|
||||
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
|
||||
switch (decryptedPushMessage.getType()) {
|
||||
case "call":
|
||||
smallIcon = R.drawable.ic_call_black_24dp;
|
||||
category = Notification.CATEGORY_CALL;
|
||||
priority = Notification.PRIORITY_HIGH;
|
||||
soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
|
||||
break;
|
||||
case "room":
|
||||
smallIcon = R.drawable.ic_notifications_black_24dp;
|
||||
category = Notification.CATEGORY_CALL;
|
||||
priority = Notification.PRIORITY_HIGH;
|
||||
break;
|
||||
case "chat":
|
||||
smallIcon = R.drawable.ic_chat_black_24dp;
|
||||
category = Notification.CATEGORY_MESSAGE;
|
||||
break;
|
||||
default:
|
||||
smallIcon = R.drawable.ic_logo;
|
||||
}
|
||||
|
||||
largeIcon = BitmapFactory.decodeResource(context.getResources(), smallIcon);
|
||||
CRC32 crc32 = new CRC32();
|
||||
|
||||
Notification.Builder notificationBuilder = new Notification.Builder(context)
|
||||
.setLargeIcon(largeIcon)
|
||||
.setSmallIcon(smallIcon)
|
||||
.setCategory(category)
|
||||
.setPriority(priority)
|
||||
.setWhen(Calendar.getInstance().getTimeInMillis())
|
||||
.setShowWhen(true)
|
||||
.setSubText(signatureVerification.getUserEntity().getDisplayName())
|
||||
.setContentTitle(decryptedPushMessage.getSubject())
|
||||
.setSound(soundUri)
|
||||
.setAutoCancel(true);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
// This method should exist since API 21, but some phones don't have it
|
||||
// So as a safeguard, we don't use it until 23
|
||||
notificationBuilder.setColor(context.getResources().getColor(R.color.colorPrimary));
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
|
||||
String groupName = String.format(context.getResources().getString(R.string
|
||||
.nc_notification_channel), signatureVerification.getUserEntity()
|
||||
.getDisplayName(), signatureVerification.getUserEntity().getBaseUrl());
|
||||
crc32.update(groupName.getBytes());
|
||||
|
||||
NotificationUtils.createNotificationChannelGroup(notificationManager,
|
||||
Long.toString(crc32.getValue()),
|
||||
groupName);
|
||||
|
||||
if (category.equals(Notification.CATEGORY_CALL)) {
|
||||
NotificationUtils.createNotificationChannel(notificationManager,
|
||||
NotificationUtils.NOTIFICATION_CHANNEL_CALLS, context.getResources()
|
||||
.getString(R
|
||||
.string.nc_notification_channel_calls), context.getResources()
|
||||
.getString
|
||||
(R.string.nc_notification_channel_calls_description), true,
|
||||
NotificationManager.IMPORTANCE_HIGH, soundUri);
|
||||
|
||||
notificationBuilder.setChannelId(NotificationUtils.NOTIFICATION_CHANNEL_CALLS);
|
||||
} else {
|
||||
NotificationUtils.createNotificationChannel(notificationManager,
|
||||
NotificationUtils.NOTIFICATION_CHANNEL_MESSAGES, context.getResources()
|
||||
.getString(R
|
||||
.string.nc_notification_channel_messages), context.getResources()
|
||||
.getString
|
||||
(R.string.nc_notification_channel_messages_description), true,
|
||||
NotificationManager.IMPORTANCE_DEFAULT, soundUri);
|
||||
|
||||
notificationBuilder.setChannelId(NotificationUtils.NOTIFICATION_CHANNEL_MESSAGES);
|
||||
}
|
||||
|
||||
notificationBuilder.setGroup(Long.toString(crc32.getValue()));
|
||||
}
|
||||
|
||||
notificationBuilder.setContentIntent(pendingIntent);
|
||||
|
||||
String stringForCrc = decryptedPushMessage.getSubject() + " " + signatureVerification
|
||||
.getUserEntity().getDisplayName() + " " + signatureVerification.getUserEntity
|
||||
().getBaseUrl();
|
||||
|
||||
crc32 = new CRC32();
|
||||
crc32.update(stringForCrc.getBytes());
|
||||
|
||||
if (notificationManager != null) {
|
||||
notificationManager.notify((int) crc32.getValue(), notificationBuilder.build());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} catch (NoSuchAlgorithmException e1) {
|
||||
Log.d(TAG, "No proper algorithm to decrypt the message " + e1.getLocalizedMessage());
|
||||
} catch (NoSuchPaddingException e1) {
|
||||
Log.d(TAG, "No proper padding to decrypt the message " + e1.getLocalizedMessage());
|
||||
} catch (InvalidKeyException e1) {
|
||||
Log.d(TAG, "Invalid private key " + e1.getLocalizedMessage());
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
Log.d(TAG, "Something went very wrong" + exception.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
return Result.SUCCESS;
|
||||
}
|
||||
}
|
@ -26,6 +26,7 @@ import android.support.annotation.Nullable;
|
||||
import com.evernote.android.job.Job;
|
||||
import com.evernote.android.job.JobCreator;
|
||||
import com.nextcloud.talk.jobs.AccountRemovalJob;
|
||||
import com.nextcloud.talk.jobs.NotificationJob;
|
||||
import com.nextcloud.talk.jobs.PushRegistrationJob;
|
||||
|
||||
public class MagicJobCreator implements JobCreator {
|
||||
@ -39,6 +40,8 @@ public class MagicJobCreator implements JobCreator {
|
||||
return new PushRegistrationJob();
|
||||
case AccountRemovalJob.TAG:
|
||||
return new AccountRemovalJob();
|
||||
case NotificationJob.TAG:
|
||||
return new NotificationJob();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
@ -68,6 +68,11 @@ public class Room {
|
||||
return (RoomType.ROOM_PUBLIC_CALL.equals(type));
|
||||
}
|
||||
|
||||
public boolean isGuest() {
|
||||
return (Participant.ParticipantType.GUEST.equals(participantType) ||
|
||||
Participant.ParticipantType.USER_FOLLOWING_LINK.equals(participantType));
|
||||
}
|
||||
|
||||
public boolean canModerate() {
|
||||
return (Participant.ParticipantType.OWNER.equals(participantType)
|
||||
|| Participant.ParticipantType.MODERATOR.equals(participantType));
|
||||
|
@ -21,43 +21,14 @@
|
||||
package com.nextcloud.talk.services.firebase;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.media.RingtoneManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
|
||||
import com.bluelinelabs.logansquare.LoganSquare;
|
||||
import com.evernote.android.job.JobRequest;
|
||||
import com.evernote.android.job.util.support.PersistableBundleCompat;
|
||||
import com.google.firebase.messaging.FirebaseMessagingService;
|
||||
import com.google.firebase.messaging.RemoteMessage;
|
||||
import com.nextcloud.talk.R;
|
||||
import com.nextcloud.talk.activities.CallActivity;
|
||||
import com.nextcloud.talk.models.SignatureVerification;
|
||||
import com.nextcloud.talk.models.json.push.DecryptedPushMessage;
|
||||
import com.nextcloud.talk.models.json.push.PushMessage;
|
||||
import com.nextcloud.talk.utils.NotificationUtils;
|
||||
import com.nextcloud.talk.utils.PushUtils;
|
||||
import com.nextcloud.talk.jobs.NotificationJob;
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys;
|
||||
|
||||
import org.parceler.Parcels;
|
||||
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.util.Calendar;
|
||||
import java.util.zip.CRC32;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
|
||||
public class MagicFirebaseMessagingService extends FirebaseMessagingService {
|
||||
private static final String TAG = "MagicFirebaseMessagingService";
|
||||
|
||||
@ -65,149 +36,17 @@ public class MagicFirebaseMessagingService extends FirebaseMessagingService {
|
||||
@Override
|
||||
public void onMessageReceived(RemoteMessage remoteMessage) {
|
||||
if (remoteMessage.getData() != null) {
|
||||
try {
|
||||
PushMessage pushMessage = new PushMessage();
|
||||
pushMessage.setSubject(remoteMessage.getData().get("subject"));
|
||||
pushMessage.setSignature(remoteMessage.getData().get("signature"));
|
||||
|
||||
byte[] base64DecodedSubject = android.util.Base64.decode(pushMessage.getSubject(), Base64.DEFAULT);
|
||||
byte[] base64DecodedSignature = android.util.Base64.decode(pushMessage.getSignature(), Base64.DEFAULT);
|
||||
PushUtils pushUtils = new PushUtils();
|
||||
PrivateKey privateKey = (PrivateKey) pushUtils.readKeyFromFile(false);
|
||||
|
||||
try {
|
||||
SignatureVerification signatureVerification = pushUtils.verifySignature(base64DecodedSignature,
|
||||
base64DecodedSubject);
|
||||
|
||||
if (signatureVerification.isSignatureValid()) {
|
||||
Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding");
|
||||
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||
byte[] decryptedSubject = cipher.doFinal(base64DecodedSubject);
|
||||
DecryptedPushMessage decryptedPushMessage = LoganSquare.parse(new String(decryptedSubject),
|
||||
DecryptedPushMessage.class);
|
||||
|
||||
if (decryptedPushMessage.getApp().equals("spreed")) {
|
||||
int smallIcon;
|
||||
Bitmap largeIcon;
|
||||
String category = "";
|
||||
int priority = Notification.PRIORITY_DEFAULT;
|
||||
Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
|
||||
|
||||
Intent intent = new Intent(this, CallActivity.class);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(BundleKeys.KEY_ROOM_TOKEN, decryptedPushMessage.getId());
|
||||
bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, Parcels.wrap(signatureVerification
|
||||
.getUserEntity()));
|
||||
bundle.putBoolean("fromNotification", true);
|
||||
intent.putExtras(bundle);
|
||||
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(this,
|
||||
0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
|
||||
|
||||
NotificationManager notificationManager =
|
||||
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
|
||||
switch (decryptedPushMessage.getType()) {
|
||||
case "call":
|
||||
smallIcon = R.drawable.ic_call_black_24dp;
|
||||
category = Notification.CATEGORY_CALL;
|
||||
priority = Notification.PRIORITY_HIGH;
|
||||
soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
|
||||
break;
|
||||
case "room":
|
||||
smallIcon = R.drawable.ic_notifications_black_24dp;
|
||||
category = Notification.CATEGORY_CALL;
|
||||
priority = Notification.PRIORITY_HIGH;
|
||||
break;
|
||||
case "chat":
|
||||
smallIcon = R.drawable.ic_chat_black_24dp;
|
||||
category = Notification.CATEGORY_MESSAGE;
|
||||
break;
|
||||
default:
|
||||
smallIcon = R.drawable.ic_logo;
|
||||
}
|
||||
|
||||
largeIcon = BitmapFactory.decodeResource(getResources(), smallIcon);
|
||||
CRC32 crc32 = new CRC32();
|
||||
|
||||
Notification.Builder notificationBuilder = new Notification.Builder(this)
|
||||
.setLargeIcon(largeIcon)
|
||||
.setSmallIcon(smallIcon)
|
||||
.setCategory(category)
|
||||
.setPriority(priority)
|
||||
.setWhen(Calendar.getInstance().getTimeInMillis())
|
||||
.setShowWhen(true)
|
||||
.setSubText(signatureVerification.getUserEntity().getDisplayName())
|
||||
.setContentTitle(decryptedPushMessage.getSubject())
|
||||
.setSound(soundUri)
|
||||
.setAutoCancel(true);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
// This method should exist since API 21, but some phones don't have it
|
||||
// So as a safeguard, we don't use it until 23
|
||||
notificationBuilder.setColor(getResources().getColor(R.color.colorPrimary));
|
||||
}
|
||||
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
|
||||
|
||||
String groupName = String.format(getResources().getString(R.string
|
||||
.nc_notification_channel), signatureVerification.getUserEntity()
|
||||
.getDisplayName(), signatureVerification.getUserEntity().getBaseUrl());
|
||||
crc32.update(groupName.getBytes());
|
||||
|
||||
NotificationUtils.createNotificationChannelGroup(notificationManager,
|
||||
Long.toString(crc32.getValue()),
|
||||
groupName);
|
||||
|
||||
if (category.equals(Notification.CATEGORY_CALL)) {
|
||||
NotificationUtils.createNotificationChannel(notificationManager,
|
||||
NotificationUtils.NOTIFICATION_CHANNEL_CALLS, getResources().getString(R
|
||||
.string.nc_notification_channel_calls), getResources().getString
|
||||
(R.string.nc_notification_channel_calls_description), true,
|
||||
NotificationManager.IMPORTANCE_HIGH, soundUri);
|
||||
|
||||
notificationBuilder.setChannelId(NotificationUtils.NOTIFICATION_CHANNEL_CALLS);
|
||||
} else {
|
||||
NotificationUtils.createNotificationChannel(notificationManager,
|
||||
NotificationUtils.NOTIFICATION_CHANNEL_MESSAGES, getResources().getString(R
|
||||
.string.nc_notification_channel_messages), getResources().getString
|
||||
(R.string.nc_notification_channel_messages_description), true,
|
||||
NotificationManager.IMPORTANCE_DEFAULT, soundUri);
|
||||
|
||||
notificationBuilder.setChannelId(NotificationUtils.NOTIFICATION_CHANNEL_MESSAGES);
|
||||
}
|
||||
|
||||
notificationBuilder.setGroup(Long.toString(crc32.getValue()));
|
||||
}
|
||||
|
||||
notificationBuilder.setContentIntent(pendingIntent);
|
||||
|
||||
String stringForCrc = decryptedPushMessage.getSubject() + " " + signatureVerification
|
||||
.getUserEntity().getDisplayName() + " " + signatureVerification.getUserEntity
|
||||
().getBaseUrl();
|
||||
|
||||
crc32 = new CRC32();
|
||||
crc32.update(stringForCrc.getBytes());
|
||||
|
||||
if (notificationManager != null) {
|
||||
notificationManager.notify((int) crc32.getValue(), notificationBuilder.build());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} catch (NoSuchAlgorithmException e1) {
|
||||
Log.d(TAG, "No proper algorithm to decrypt the message " + e1.getLocalizedMessage());
|
||||
} catch (NoSuchPaddingException e1) {
|
||||
Log.d(TAG, "No proper padding to decrypt the message " + e1.getLocalizedMessage());
|
||||
} catch (InvalidKeyException e1) {
|
||||
Log.d(TAG, "Invalid private key " + e1.getLocalizedMessage());
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
Log.d(TAG, "Something went very wrong" + exception.getLocalizedMessage());
|
||||
}
|
||||
} else {
|
||||
Log.d(TAG, "The data we received was empty");
|
||||
|
||||
PersistableBundleCompat persistableBundleCompat = new PersistableBundleCompat();
|
||||
persistableBundleCompat.putString(BundleKeys.KEY_NOTIFICATION_SUBJECT, remoteMessage.getData().get
|
||||
("subject"));
|
||||
persistableBundleCompat.putString(BundleKeys.KEY_NOTIFICATION_SIGNATURE, remoteMessage.getData().get
|
||||
("signature"));
|
||||
new JobRequest.Builder(NotificationJob.TAG)
|
||||
.addExtras(persistableBundleCompat)
|
||||
.setUpdateCurrent(false)
|
||||
.startNow()
|
||||
.build()
|
||||
.schedule();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ public class BundleKeys {
|
||||
public static final String KEY_ORIGINAL_PROTOCOL = "KEY_ORIGINAL_PROTOCOL";
|
||||
public static final String KEY_ROOM = "KEY_ROOM";
|
||||
public static final String KEY_OPERATION_CODE = "KEY_OPERATION_CODE";
|
||||
public static final String KEY_IS_SHARE = "KEY_IS_SHARE";
|
||||
public static final String KEY_MENU_TYPE = "KEY_MENU_TYPE";
|
||||
public static final String KEY_SHARE_INTENT = "KEY_SHARE_INTENT";
|
||||
public static final String KEY_APP_ITEM_PACKAGE_NAME = "KEY_APP_ITEM_PACKAGE_NAME";
|
||||
public static final String KEY_APP_ITEM_NAME = "KEY_APP_ITEM_NAME";
|
||||
@ -38,4 +38,8 @@ public class BundleKeys {
|
||||
public static final String KEY_USER_ENTITY = "KEY_USER_ENTITY";
|
||||
public static final String KEY_NEW_CONVERSATION = "KEY_NEW_CONVERSATION";
|
||||
public static final String KEY_IS_PUBLIC_CALL = "KEY_IS_PUBLIC_CALL";
|
||||
public static final String KEY_CALL_URL = "KEY_CALL_URL";
|
||||
public static final String KEY_MODIFIED_BASE_URL = "KEY_MODIFIED_BASE_URL";
|
||||
public static final String KEY_NOTIFICATION_SUBJECT = "KEY_NOTIFICATION_SUBJECT";
|
||||
public static final String KEY_NOTIFICATION_SIGNATURE = "KEY_NOTIFICATION_SIGNATURE";
|
||||
}
|
||||
|
@ -28,7 +28,6 @@
|
||||
|
||||
<string name="nc_never">Never joined</string>
|
||||
<string name="nc_search">Search</string>
|
||||
<string name="nc_new_conversation">Create a new conversation</string>
|
||||
|
||||
<string name="nc_certificate_dialog_title">Check out the certificate</string>
|
||||
<string name="nc_certificate_dialog_text">Do you trust the until now unknown SSL certificate, issued by %1$s for %2$s, valid from %3$s to %4$s?</string>
|
||||
@ -61,6 +60,7 @@
|
||||
<string name="nc_no_proxy">No proxy</string>
|
||||
<string name="nc_username">Username</string>
|
||||
<string name="nc_password">Password</string>
|
||||
<string name="nc_conversation_link">Conversation link</string>
|
||||
<string name="nc_new_password">New password</string>
|
||||
<string name="nc_wrong_password">Wrong password</string>
|
||||
<string name="nc_about">About</string>
|
||||
@ -83,6 +83,9 @@
|
||||
<string name="nc_make_call_public">Make call public</string>
|
||||
<string name="nc_make_call_private">Make call private</string>
|
||||
<string name="nc_delete_call">Delete call</string>
|
||||
<string name="nc_new_conversation">Start a new conversation</string>
|
||||
<string name="nc_join_via_link">Join via link</string>
|
||||
<string name="nc_join_via_web">Join via web</string>
|
||||
|
||||
<!-- Contacts -->
|
||||
<string name="nc_select_contacts">Select contacts</string>
|
||||
@ -115,11 +118,14 @@
|
||||
|
||||
<!-- Bottom sheet menu -->
|
||||
<string name="nc_failed_to_perform_operation">Sorry, something went wrong!</string>
|
||||
<string name="nc_failed_signaling_settings">Target server does not support joining public rooms via mobile phones.
|
||||
You may attempt to join the call via web browser.</string>
|
||||
<string name="nc_all_ok_operation">OK, all done!</string>
|
||||
<string name="nc_ok">OK</string>
|
||||
<string name="nc_call_name">Call name</string>
|
||||
<string name="nc_proceed">Proceed</string>
|
||||
<string name="nc_call_name_is_same">The name you entered is the same as the existing one</string>
|
||||
<string name="nc_wrong_link">Conversation link is not valid</string>
|
||||
<string name="nc_share_text">Hello,\n\nI would like you to join a call with me.\n\nYou can join this call via
|
||||
%1$s/index.php/call/%2$s</string>
|
||||
<string name="nc_talk_soon">\n\nTalk soon,\n %1$s</string>
|
||||
|
Loading…
Reference in New Issue
Block a user