diff options
author | Andrew Comminos <andrew@comminos.com> | 2017-03-02 08:21:12 +0300 |
---|---|---|
committer | Andrew Comminos <andrew@comminos.com> | 2017-03-02 08:21:12 +0300 |
commit | 3fbbef140168f6bb8bb609c7976ef572083969d4 (patch) | |
tree | 6230fa488d291aa143e1a6711552ea63217f1b0b | |
parent | 4684fadb58112368e1651dbb65847e86fb4d97d8 (diff) |
Update usage of connection-oriented calls to match new Jumble getSession API, improving stability.
21 files changed, 312 insertions, 200 deletions
diff --git a/app/src/main/java/com/morlunk/mumbleclient/app/PlumbleActivity.java b/app/src/main/java/com/morlunk/mumbleclient/app/PlumbleActivity.java index 0794ffd..b0cb4f2 100644 --- a/app/src/main/java/com/morlunk/mumbleclient/app/PlumbleActivity.java +++ b/app/src/main/java/com/morlunk/mumbleclient/app/PlumbleActivity.java @@ -31,7 +31,6 @@ import android.media.AudioManager; import android.os.Build; import android.os.Bundle; import android.os.IBinder; -import android.os.RemoteException; import android.preference.PreferenceManager; import android.support.v4.app.DialogFragment; import android.support.v4.app.Fragment; @@ -51,9 +50,10 @@ import android.widget.ListView; import android.widget.Toast; import com.morlunk.jumble.IJumbleService; -import com.morlunk.jumble.JumbleService; +import com.morlunk.jumble.IJumbleSession; import com.morlunk.jumble.model.Server; import com.morlunk.jumble.protobuf.Mumble; +import com.morlunk.jumble.util.JumbleDisconnectedException; import com.morlunk.jumble.util.JumbleException; import com.morlunk.jumble.util.JumbleObserver; import com.morlunk.jumble.util.MumbleURLParser; @@ -73,6 +73,7 @@ import com.morlunk.mumbleclient.preference.Preferences; import com.morlunk.mumbleclient.servers.FavouriteServerListFragment; import com.morlunk.mumbleclient.servers.PublicServerListFragment; import com.morlunk.mumbleclient.servers.ServerEditFragment; +import com.morlunk.mumbleclient.service.IPlumbleService; import com.morlunk.mumbleclient.service.PlumbleService; import com.morlunk.mumbleclient.util.JumbleServiceFragment; import com.morlunk.mumbleclient.util.JumbleServiceProvider; @@ -80,14 +81,11 @@ import com.morlunk.mumbleclient.util.PlumbleTrustStore; import org.spongycastle.util.encoders.Hex; -import java.io.ByteArrayInputStream; -import java.io.File; import java.net.MalformedURLException; import java.security.KeyStore; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; @@ -103,7 +101,7 @@ public class PlumbleActivity extends ActionBarActivity implements ListView.OnIte */ public static final String EXTRA_DRAWER_FRAGMENT = "drawer_fragment"; - private PlumbleService mService; + private IPlumbleService mService; private PlumbleDatabase mDatabase; private Settings mSettings; @@ -122,7 +120,7 @@ public class PlumbleActivity extends ActionBarActivity implements ListView.OnIte private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { - mService = (PlumbleService)((JumbleService.JumbleBinder) service).getService(); + mService = ((PlumbleService.PlumbleBinder) service).getService(); mService.setSuppressNotifications(true); mService.registerObserver(mObserver); mService.clearChatNotifications(); // Clear chat notifications on resume. @@ -133,7 +131,7 @@ public class PlumbleActivity extends ActionBarActivity implements ListView.OnIte // Re-show server list if we're showing a fragment that depends on the service. if(getSupportFragmentManager().findFragmentById(R.id.content_frame) instanceof JumbleServiceFragment && - !mService.isSynchronized()) { + !mService.isConnected()) { loadDrawerFragment(DrawerAdapter.ITEM_FAVOURITES); } updateConnectionState(getService()); @@ -174,7 +172,7 @@ public class PlumbleActivity extends ActionBarActivity implements ListView.OnIte @Override public void onTLSHandshakeFailed(X509Certificate[] chain) { - final Server lastServer = getService().getConnectedServer(); + final Server lastServer = getService().getTargetServer(); if (chain.length == 0) return; @@ -262,10 +260,11 @@ public class PlumbleActivity extends ActionBarActivity implements ListView.OnIte public void onDrawerStateChanged(int newState) { super.onDrawerStateChanged(newState); // Prevent push to talk from getting stuck on when the drawer is opened. - if (getService() != null - && getService().isSynchronized() - && getService().isTalking() && !mSettings.isPushToTalkToggle()) { - getService().setTalkingState(false); + if (getService() != null && getService().isConnected()) { + IJumbleSession session = getService().getSession(); + if (session.isTalking() && !mSettings.isPushToTalkToggle()) { + session.setTalkingState(false); + } } } @@ -290,8 +289,7 @@ public class PlumbleActivity extends ActionBarActivity implements ListView.OnIte dadb.setPositiveButton(R.string.confirm, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - if(mService != null && mService.isConnectionEstablished()) - mService.disconnect(); + if(mService != null) mService.disconnect(); loadDrawerFragment(DrawerAdapter.ITEM_FAVOURITES); } }); @@ -372,7 +370,7 @@ public class PlumbleActivity extends ActionBarActivity implements ListView.OnIte @Override public boolean onPrepareOptionsMenu(Menu menu) { MenuItem disconnectButton = menu.findItem(R.id.action_disconnect); - disconnectButton.setVisible(mService != null && mService.isSynchronized()); + disconnectButton.setVisible(mService != null && mService.isConnected()); // Color the action bar icons to the primary text color of the theme. int foregroundColor = getSupportActionBar().getThemedContext() @@ -436,7 +434,7 @@ public class PlumbleActivity extends ActionBarActivity implements ListView.OnIte @Override public void onBackPressed() { - if(mService != null && mService.isSynchronized()) { + if(mService != null && mService.isConnected()) { mDisconnectPromptBuilder.show(); return; } @@ -495,8 +493,9 @@ public class PlumbleActivity extends ActionBarActivity implements ListView.OnIte break; case DrawerAdapter.ITEM_ACCESS_TOKENS: fragmentClass = AccessTokenFragment.class; - args.putLong("server", mService.getConnectedServer().getId()); - args.putStringArrayList("access_tokens", (ArrayList<String>) mDatabase.getAccessTokens(mService.getConnectedServer().getId())); + Server connectedServer = getService().getTargetServer(); + args.putLong("server", connectedServer.getId()); + args.putStringArrayList("access_tokens", (ArrayList<String>) mDatabase.getAccessTokens(connectedServer.getId())); break; case DrawerAdapter.ITEM_PINNED_CHANNELS: fragmentClass = ChannelFragment.class; @@ -525,7 +524,7 @@ public class PlumbleActivity extends ActionBarActivity implements ListView.OnIte public void connectToServer(final Server server) { // Check if we're already connected to a server; if so, inform user. - if(mService != null && mService.isConnectionEstablished()) { + if(mService != null && mService.isConnected()) { AlertDialog.Builder adb = new AlertDialog.Builder(this); adb.setMessage(R.string.reconnect_dialog_message); adb.setPositiveButton(R.string.connect, new DialogInterface.OnClickListener() { @@ -610,7 +609,7 @@ public class PlumbleActivity extends ActionBarActivity implements ListView.OnIte switch (mService.getConnectionState()) { case CONNECTING: - Server server = service.getConnectedServer(); + Server server = service.getTargetServer(); mConnectingDialog = new ProgressDialog(this); mConnectingDialog.setIndeterminate(true); mConnectingDialog.setCancelable(true); @@ -657,7 +656,7 @@ public class PlumbleActivity extends ActionBarActivity implements ListView.OnIte ab.setPositiveButton(R.string.reconnect, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - Server server = getService().getConnectedServer(); + Server server = getService().getTargetServer(); if (server == null) return; String password = passwordField.getText().toString(); @@ -698,7 +697,7 @@ public class PlumbleActivity extends ActionBarActivity implements ListView.OnIte */ @Override - public PlumbleService getService() { + public IPlumbleService getService() { return mService; } @@ -738,13 +737,13 @@ public class PlumbleActivity extends ActionBarActivity implements ListView.OnIte @Override public boolean isConnected() { - return mService != null && mService.isSynchronized(); + return mService != null && mService.isConnected(); } @Override public String getConnectedServerName() { - if(mService != null && mService.isSynchronized()) { - Server server = mService.getConnectedServer(); + if(mService != null && mService.isConnected()) { + Server server = mService.getTargetServer(); return server.getName().equals("") ? server.getHost() : server.getName(); } if (BuildConfig.DEBUG) diff --git a/app/src/main/java/com/morlunk/mumbleclient/channel/AccessTokenFragment.java b/app/src/main/java/com/morlunk/mumbleclient/channel/AccessTokenFragment.java index bb6efe5..80fd0bf 100644 --- a/app/src/main/java/com/morlunk/mumbleclient/channel/AccessTokenFragment.java +++ b/app/src/main/java/com/morlunk/mumbleclient/channel/AccessTokenFragment.java @@ -120,7 +120,9 @@ public class AccessTokenFragment extends JumbleServiceFragment { mTokenList.smoothScrollToPosition(mTokens.size() - 1); mProvider.getDatabase().addAccessToken(getServerId(), tokenText); - getService().sendAccessTokens(mTokens); + if (getService().isConnected()) { + getService().getSession().sendAccessTokens(mTokens); + } } private long getServerId() { @@ -158,7 +160,9 @@ public class AccessTokenFragment extends JumbleServiceFragment { mTokens.remove(position); notifyDataSetChanged(); mProvider.getDatabase().removeAccessToken(getServerId(), token); - getService().sendAccessTokens(mTokens); + if (getService().isConnected()) { + getService().getSession().sendAccessTokens(mTokens); + } } }); diff --git a/app/src/main/java/com/morlunk/mumbleclient/channel/ChannelChatFragment.java b/app/src/main/java/com/morlunk/mumbleclient/channel/ChannelChatFragment.java index 0a0d613..0d99897 100644 --- a/app/src/main/java/com/morlunk/mumbleclient/channel/ChannelChatFragment.java +++ b/app/src/main/java/com/morlunk/mumbleclient/channel/ChannelChatFragment.java @@ -43,18 +43,16 @@ import android.widget.TextView; import android.widget.TextView.OnEditorActionListener; import com.morlunk.jumble.IJumbleService; -import com.morlunk.jumble.JumbleService; -import com.morlunk.jumble.model.Channel; +import com.morlunk.jumble.IJumbleSession; import com.morlunk.jumble.model.IChannel; import com.morlunk.jumble.model.IMessage; import com.morlunk.jumble.model.IUser; -import com.morlunk.jumble.model.Message; import com.morlunk.jumble.model.User; import com.morlunk.jumble.util.IJumbleObserver; +import com.morlunk.jumble.util.JumbleDisconnectedException; import com.morlunk.jumble.util.JumbleObserver; import com.morlunk.mumbleclient.R; import com.morlunk.mumbleclient.service.IChatMessage; -import com.morlunk.mumbleclient.service.PlumbleService; import com.morlunk.mumbleclient.util.JumbleServiceFragment; import com.morlunk.mumbleclient.util.MumbleImageGetter; @@ -63,7 +61,6 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; -import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -94,11 +91,15 @@ public class ChannelChatFragment extends JumbleServiceFragment implements ChatTa @Override public void onUserJoinedChannel(IUser user, IChannel newChannel, IChannel oldChannel) { - if (user != null && getService().getSessionUser() != null && - user.equals(getService().getSessionUser()) && - mTargetProvider.getChatTarget() == null) { - // Update chat target when user changes channels without a target. - updateChatTargetText(null); + IJumbleService service = getService(); + if (service.isConnected()) { + IJumbleSession session = service.getSession(); + if (user != null && session.getSessionUser() != null && + user.equals(session.getSessionUser()) && + mTargetProvider.getChatTarget() == null) { + // Update chat target when user changes channels without a target. + updateChatTargetText(null); + } } } }; @@ -148,22 +149,14 @@ public class ChannelChatFragment extends JumbleServiceFragment implements ChatTa mSendButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - try { - sendMessage(); - } catch (RemoteException e) { - e.printStackTrace(); - } + sendMessage(); } }); mChatTextEdit.setOnEditorActionListener(new OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { - try { - sendMessage(); - } catch (RemoteException e) { - e.printStackTrace(); - } + sendMessage(); return true; } }); @@ -228,20 +221,21 @@ public class ChannelChatFragment extends JumbleServiceFragment implements ChatTa /** * Sends the message currently in {@link com.morlunk.mumbleclient.channel.ChannelChatFragment#mChatTextEdit} * to the remote server. Clears the message box if the message was sent successfully. - * @throws RemoteException If the service failed to send the message. + * @throws JumbleDisconnectedException If the service is disconnected. */ - private void sendMessage() throws RemoteException { + private void sendMessage() throws JumbleDisconnectedException { if(mChatTextEdit.length() == 0) return; String message = mChatTextEdit.getText().toString(); String formattedMessage = markupOutgoingMessage(message); ChatTargetProvider.ChatTarget target = mTargetProvider.getChatTarget(); IMessage responseMessage = null; + IJumbleSession session = getService().getSession(); if(target == null) - responseMessage = getService().sendChannelTextMessage(getService().getSessionChannel().getId(), formattedMessage, false); + responseMessage = session.sendChannelTextMessage(session.getSessionChannel().getId(), formattedMessage, false); else if(target.getUser() != null) - responseMessage = getService().sendUserTextMessage(target.getUser().getSession(), formattedMessage); + responseMessage = session.sendUserTextMessage(target.getUser().getSession(), formattedMessage); else if(target.getChannel() != null) - responseMessage = getService().sendChannelTextMessage(target.getChannel().getId(), formattedMessage, false); + responseMessage = session.sendChannelTextMessage(target.getChannel().getId(), formattedMessage, false); addChatMessage(new IChatMessage.TextMessage(responseMessage), true); mChatTextEdit.setText(""); } @@ -267,12 +261,13 @@ public class ChannelChatFragment extends JumbleServiceFragment implements ChatTa /** * Updates hint displaying chat target. */ - public void updateChatTargetText(ChatTargetProvider.ChatTarget target) { - if(getService() == null) return; + public void updateChatTargetText(final ChatTargetProvider.ChatTarget target) { + if(getService() == null || !getService().isConnected()) return; + IJumbleSession session = getService().getSession(); String hint = null; - if(target == null && getService().getSessionChannel() != null) { - hint = getString(R.string.messageToChannel, getService().getSessionChannel().getName()); + if(target == null && session.getSessionChannel() != null) { + hint = getString(R.string.messageToChannel, session.getSessionChannel().getName()); } else if(target != null && target.getUser() != null) { hint = getString(R.string.messageToUser, target.getUser().getName()); } else if(target != null && target.getChannel() != null) { @@ -335,8 +330,12 @@ public class ChannelChatFragment extends JumbleServiceFragment implements ChatTa public void visit(IChatMessage.TextMessage message) { IMessage textMessage = message.getMessage(); String targetMessage = getContext().getString(R.string.unknown); - boolean selfAuthored = mService.getConnectionState() == JumbleService.ConnectionState.CONNECTED && - textMessage.getActor() == mService.getSession(); + boolean selfAuthored; + try { + selfAuthored = textMessage.getActor() == mService.getSession().getSessionId(); + } catch (JumbleDisconnectedException e) { + selfAuthored = false; + } if (textMessage.getTargetChannels() != null && !textMessage.getTargetChannels().isEmpty()) { IChannel currentChannel = (IChannel) textMessage.getTargetChannels().get(0); diff --git a/app/src/main/java/com/morlunk/mumbleclient/channel/ChannelEditFragment.java b/app/src/main/java/com/morlunk/mumbleclient/channel/ChannelEditFragment.java index 6004c24..548a593 100644 --- a/app/src/main/java/com/morlunk/mumbleclient/channel/ChannelEditFragment.java +++ b/app/src/main/java/com/morlunk/mumbleclient/channel/ChannelEditFragment.java @@ -29,6 +29,7 @@ import android.view.View; import android.widget.CheckBox; import android.widget.TextView; +import com.morlunk.jumble.IJumbleSession; import com.morlunk.jumble.model.Channel; import com.morlunk.jumble.model.IChannel; import com.morlunk.jumble.net.Permissions; @@ -67,13 +68,17 @@ public class ChannelEditFragment extends DialogFragment { mTemporaryBox = (CheckBox) view.findViewById(R.id.channel_edit_temporary); // If we can only make temporary channels, remove the option. - IChannel parentChannel = mServiceProvider.getService().getChannel(getParent()); - int combinedPermissions = mServiceProvider.getService().getPermissions() | parentChannel.getPermissions(); - boolean canMakeChannel = (combinedPermissions & Permissions.MakeChannel) > 0; - boolean canMakeTempChannel = (combinedPermissions & Permissions.MakeTempChannel) > 0; - boolean onlyTemp = canMakeTempChannel && !canMakeChannel; - mTemporaryBox.setChecked(onlyTemp); - mTemporaryBox.setEnabled(!onlyTemp); + if (mServiceProvider.getService().isConnected()) { + // TODO: we probably should just stop this dialog in its tracks if we're disconnected. + IJumbleSession session = mServiceProvider.getService().getSession(); + IChannel parentChannel = session.getChannel(getParent()); + int combinedPermissions = session.getPermissions() | parentChannel.getPermissions(); + boolean canMakeChannel = (combinedPermissions & Permissions.MakeChannel) > 0; + boolean canMakeTempChannel = (combinedPermissions & Permissions.MakeTempChannel) > 0; + boolean onlyTemp = canMakeTempChannel && !canMakeChannel; + mTemporaryBox.setChecked(onlyTemp); + mTemporaryBox.setEnabled(!onlyTemp); + } return new AlertDialog.Builder(getActivity()) .setTitle(isAdding() ? R.string.channel_add : R.string.channel_edit) @@ -81,8 +86,8 @@ public class ChannelEditFragment extends DialogFragment { .setPositiveButton(isAdding() ? R.string.add : R.string.save, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - if(isAdding()) { - mServiceProvider.getService().createChannel(getParent(), + if(isAdding() && mServiceProvider.getService().isConnected()) { + mServiceProvider.getService().getSession().createChannel(getParent(), mNameField.getText().toString(), mDescriptionField.getText().toString(), Integer.parseInt(mPositionField.getText().toString()), // We can guarantee this to be an int. InputType is numberSigned. diff --git a/app/src/main/java/com/morlunk/mumbleclient/channel/ChannelFragment.java b/app/src/main/java/com/morlunk/mumbleclient/channel/ChannelFragment.java index 3c8e56d..bc2932c 100644 --- a/app/src/main/java/com/morlunk/mumbleclient/channel/ChannelFragment.java +++ b/app/src/main/java/com/morlunk/mumbleclient/channel/ChannelFragment.java @@ -21,7 +21,6 @@ import android.animation.Animator; import android.content.SharedPreferences; import android.content.res.TypedArray; import android.os.Bundle; -import android.os.RemoteException; import android.preference.PreferenceManager; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; @@ -36,19 +35,14 @@ import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; -import android.view.animation.Animation; -import android.view.animation.AnimationSet; -import android.view.animation.AnimationUtils; import android.widget.Button; -import android.widget.CheckBox; import android.widget.ImageView; -import android.widget.LinearLayout; import android.widget.TextView; import com.morlunk.jumble.IJumbleService; +import com.morlunk.jumble.IJumbleSession; import com.morlunk.jumble.JumbleService; import com.morlunk.jumble.model.IUser; -import com.morlunk.jumble.model.User; import com.morlunk.jumble.model.WhisperTarget; import com.morlunk.jumble.util.IJumbleObserver; import com.morlunk.jumble.util.JumbleObserver; @@ -85,26 +79,32 @@ public class ChannelFragment extends JumbleServiceFragment implements SharedPref private JumbleObserver mObserver = new JumbleObserver() { @Override public void onUserTalkStateUpdated(IUser user) { - if (user != null && user.getSession() == getService().getSession()) { - // Manually set button selection colour when we receive a talk state update. - // This allows representation of talk state when using hot corners and PTT toggle. - switch (user.getTalkState()) { - case TALKING: - case SHOUTING: - case WHISPERING: - mTalkButton.setPressed(true); - break; - case PASSIVE: - mTalkButton.setPressed(false); - break; + if (getService().isConnected()) { + IJumbleSession session = getService().getSession(); + if (user != null && user.getSession() == session.getSessionId()) { + // Manually set button selection colour when we receive a talk state update. + // This allows representation of talk state when using hot corners and PTT toggle. + switch (user.getTalkState()) { + case TALKING: + case SHOUTING: + case WHISPERING: + mTalkButton.setPressed(true); + break; + case PASSIVE: + mTalkButton.setPressed(false); + break; + } } } } @Override public void onUserStateUpdated(IUser user) { - if (user != null && user.getSession() == getService().getSession()) { - configureInput(); + if (getService().isConnected()) { + IJumbleSession session = getService().getSession(); + if (user != null && user.getSession() == session.getSessionId()) { + configureInput(); + } } } @@ -160,12 +160,14 @@ public class ChannelFragment extends JumbleServiceFragment implements SharedPref mTargetPanelCancel.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - if (getService() != null && - getService().getConnectionState() == JumbleService.ConnectionState.CONNECTED && - getService().getVoiceTargetMode() == VoiceTargetMode.WHISPER) { - byte target = getService().getVoiceTargetId(); - getService().setVoiceTargetId((byte) 0); - getService().unregisterWhisperTarget(target); + if (getService() == null || !getService().isConnected()) + return; + + IJumbleSession session = getService().getSession(); + if (session.getVoiceTargetMode() == VoiceTargetMode.WHISPER) { + byte target = session.getVoiceTargetId(); + session.setVoiceTargetId((byte) 0); + session.unregisterWhisperTarget(target); } } }); @@ -224,10 +226,11 @@ public class ChannelFragment extends JumbleServiceFragment implements SharedPref @Override public void onPause() { super.onPause(); - if (getService() != null && !Settings.getInstance(getActivity()).isPushToTalkToggle()) { + if (getService() != null && getService().isConnected() && + !Settings.getInstance(getActivity()).isPushToTalkToggle()) { // XXX: This ensures that push to talk is disabled when we pause. // We don't want to leave the talk state active if the fragment is paused while pressed. - getService().setTalkingState(false); + getService().getSession().setTalkingState(false); } } @@ -253,9 +256,13 @@ public class ChannelFragment extends JumbleServiceFragment implements SharedPref } private void configureTargetPanel() { - VoiceTargetMode mode = getService().getVoiceTargetMode(); + if (!getService().isConnected()) + return; + + IJumbleSession session = getService().getSession(); + VoiceTargetMode mode = session.getVoiceTargetMode(); if (mode == VoiceTargetMode.WHISPER) { - WhisperTarget target = getService().getWhisperTarget(); + WhisperTarget target = session.getWhisperTarget(); mTargetPanel.setVisibility(View.VISIBLE); mTargetPanelText.setText(getString(R.string.shout_target, target.getName())); } else { @@ -282,8 +289,8 @@ public class ChannelFragment extends JumbleServiceFragment implements SharedPref mTalkButton.setLayoutParams(params); boolean muted = false; - if (getService().getConnectionState() == JumbleService.ConnectionState.CONNECTED) { - IUser user = getService().getSessionUser(); + if (getService().isConnected()) { + IUser user = getService().getSession().getSessionUser(); muted = user.isMuted() || user.isSuppressed() || user.isSelfMuted(); } boolean showPttButton = diff --git a/app/src/main/java/com/morlunk/mumbleclient/channel/ChannelListAdapter.java b/app/src/main/java/com/morlunk/mumbleclient/channel/ChannelListAdapter.java index 2b3f233..bf649af 100644 --- a/app/src/main/java/com/morlunk/mumbleclient/channel/ChannelListAdapter.java +++ b/app/src/main/java/com/morlunk/mumbleclient/channel/ChannelListAdapter.java @@ -17,39 +17,31 @@ package com.morlunk.mumbleclient.channel; -import android.animation.AnimatorInflater; -import android.animation.AnimatorSet; -import android.animation.ObjectAnimator; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Typeface; import android.graphics.drawable.Drawable; -import android.os.Build; import android.os.RemoteException; import android.support.v4.app.FragmentManager; import android.support.v7.widget.RecyclerView; import android.util.DisplayMetrics; -import android.util.Log; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.view.animation.Animation; -import android.view.animation.AnimationUtils; import android.widget.ImageView; import android.widget.LinearLayout; -import android.widget.ProgressBar; import android.widget.TextView; import com.morlunk.jumble.IJumbleService; +import com.morlunk.jumble.IJumbleSession; import com.morlunk.jumble.JumbleService; import com.morlunk.jumble.model.IChannel; import com.morlunk.jumble.model.IUser; import com.morlunk.jumble.model.Server; import com.morlunk.jumble.model.TalkState; -import com.morlunk.mumbleclient.Constants; import com.morlunk.mumbleclient.R; import com.morlunk.mumbleclient.db.PlumbleDatabase; import com.morlunk.mumbleclient.drawable.CircleDrawable; @@ -102,7 +94,7 @@ public class ChannelListAdapter extends RecyclerView.Adapter implements UserMenu mRootChannels = new ArrayList<Integer>(); if(showPinnedOnly) { - mRootChannels = mDatabase.getPinnedChannels(mService.getConnectedServer().getId()); + mRootChannels = mDatabase.getPinnedChannels(mService.getTargetServer().getId()); } else { mRootChannels.add(0); } @@ -161,9 +153,9 @@ public class ChannelListAdapter extends RecyclerView.Adapter implements UserMenu cvh.mChannelName.setText(channel.getName()); int nameTypeface = Typeface.NORMAL; - if (mService != null && - mService.getConnectionState() == JumbleService.ConnectionState.CONNECTED) { - if (channel.equals(mService.getSessionChannel())) { + if (mService != null && mService.isConnected()) { + IJumbleSession session = mService.getSession(); + if (channel.equals(session.getSessionChannel())) { nameTypeface |= Typeface.BOLD; // Always italicize our current channel if it has a link. if (channel.getLinks().size() > 0) { @@ -171,7 +163,7 @@ public class ChannelListAdapter extends RecyclerView.Adapter implements UserMenu } } // Italicize channels in a link with our current channel. - if (channel.getLinks().contains(mService.getSessionChannel())) { + if (channel.getLinks().contains(session.getSessionChannel())) { nameTypeface |= Typeface.ITALIC; } } @@ -196,7 +188,8 @@ public class ChannelListAdapter extends RecyclerView.Adapter implements UserMenu cvh.mJoinButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - mService.joinChannel(channel.getId()); + if (mService.isConnected()) + mService.getSession().joinChannel(channel.getId()); } }); @@ -228,7 +221,14 @@ public class ChannelListAdapter extends RecyclerView.Adapter implements UserMenu }); uvh.mUserName.setText(user.getName()); - uvh.mUserName.setTypeface(null, user.getSession() == mService.getSession() ? Typeface.BOLD : Typeface.NORMAL); + + final int typefaceStyle; + if (mService.isConnected() && mService.getSession().getSessionId() == user.getSession()) { + typefaceStyle = Typeface.BOLD; + } else { + typefaceStyle = Typeface.NORMAL; + } + uvh.mUserName.setTypeface(null, typefaceStyle); uvh.mUserTalkHighlight.setImageDrawable(getTalkStateDrawable(user)); uvh.mTalkingIndicator.setAlpha( @@ -293,12 +293,15 @@ public class ChannelListAdapter extends RecyclerView.Adapter implements UserMenu /** * Updates the channel tree model. * To be used after any channel tree modifications. - * @throws IllegalStateException if the service is not synchronized when calling this. */ public void updateChannels() { + if (!mService.isConnected()) + return; + + IJumbleSession session = mService.getSession(); mNodes.clear(); for (int cid : mRootChannels) { - IChannel channel = mService.getChannel(cid); + IChannel channel = session.getChannel(cid); if (channel != null) { constructNodes(null, channel, 0, mNodes); } @@ -469,7 +472,7 @@ public class ChannelListAdapter extends RecyclerView.Adapter implements UserMenu notifyDataSetChanged(); // Add or remove registered user from local mute history - final Server server = mService.getConnectedServer(); + final Server server = mService.getTargetServer(); if (user.getUserId() >= 0 && server.isSaved()) { new Thread(new Runnable() { diff --git a/app/src/main/java/com/morlunk/mumbleclient/channel/ChannelListFragment.java b/app/src/main/java/com/morlunk/mumbleclient/channel/ChannelListFragment.java index 3427509..fb234a4 100644 --- a/app/src/main/java/com/morlunk/mumbleclient/channel/ChannelListFragment.java +++ b/app/src/main/java/com/morlunk/mumbleclient/channel/ChannelListFragment.java @@ -44,6 +44,7 @@ import android.view.View; import android.view.ViewGroup; import com.morlunk.jumble.IJumbleService; +import com.morlunk.jumble.IJumbleSession; import com.morlunk.jumble.model.IChannel; import com.morlunk.jumble.model.IUser; import com.morlunk.jumble.util.IJumbleObserver; @@ -66,7 +67,8 @@ public class ChannelListFragment extends JumbleServiceFragment implements OnChan public void onUserJoinedChannel(IUser user, IChannel newChannel, IChannel oldChannel) { mChannelListAdapter.updateChannels(); mChannelListAdapter.notifyDataSetChanged(); - if(getService().getSession() == user.getSession()) { + if(getService().isConnected() && + getService().getSession().getSessionId() == user.getSession()) { scrollToChannel(newChannel.getId()); } } @@ -99,7 +101,7 @@ public class ChannelListFragment extends JumbleServiceFragment implements OnChan public void onUserRemoved(IUser user, String reason) { // If we are the user being removed, don't update the channel list. // We won't be in a synchronized state. - if (!getService().isSynchronized()) + if (!getService().isConnected()) return; mChannelListAdapter.updateChannels(); @@ -212,19 +214,20 @@ public class ChannelListFragment extends JumbleServiceFragment implements OnChan MenuItem muteItem = menu.findItem(R.id.menu_mute_button); MenuItem deafenItem = menu.findItem(R.id.menu_deafen_button); - if(getService() != null - && getService().isSynchronized()) { + if(getService() != null && getService().isConnected()) { + IJumbleSession session = getService().getSession(); + // Color the action bar icons to the primary text color of the theme, TODO move this elsewhere int foregroundColor = getActivity().getTheme().obtainStyledAttributes(new int[]{android.R.attr.textColorPrimaryInverse}).getColor(0, -1); - IUser self = getService().getSessionUser(); + IUser self = session.getSessionUser(); muteItem.setIcon(self.isSelfMuted() ? R.drawable.ic_action_microphone_muted : R.drawable.ic_action_microphone); deafenItem.setIcon(self.isSelfDeafened() ? R.drawable.ic_action_audio_muted : R.drawable.ic_action_audio); muteItem.getIcon().mutate().setColorFilter(foregroundColor, PorterDuff.Mode.MULTIPLY); deafenItem.getIcon().mutate().setColorFilter(foregroundColor, PorterDuff.Mode.MULTIPLY); MenuItem bluetoothItem = menu.findItem(R.id.menu_bluetooth); - bluetoothItem.setChecked(getService().usingBluetoothSco()); + bluetoothItem.setChecked(session.usingBluetoothSco()); } } @@ -245,14 +248,18 @@ public class ChannelListFragment extends JumbleServiceFragment implements OnChan @Override public boolean onSuggestionClick(int i) { + if (getService() == null || !getService().isConnected()) + return false; CursorWrapper cursor = (CursorWrapper) searchView.getSuggestionsAdapter().getItem(i); int typeColumn = cursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA); int dataIdColumn = cursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_INTENT_DATA); String itemType = cursor.getString(typeColumn); int itemId = cursor.getInt(dataIdColumn); + + IJumbleSession session = getService().getSession(); if(ChannelSearchProvider.INTENT_DATA_CHANNEL.equals(itemType)) { - if(getService().getSessionChannel().getId() != itemId) { - getService().joinChannel(itemId); + if(session.getSessionChannel().getId() != itemId) { + session.joinChannel(itemId); } else { scrollToChannel(itemId); } @@ -268,24 +275,27 @@ public class ChannelListFragment extends JumbleServiceFragment implements OnChan @Override public boolean onOptionsItemSelected(MenuItem item) { + if (getService() == null || !getService().isConnected()) + return super.onOptionsItemSelected(item); + IJumbleSession session = getService().getSession(); switch (item.getItemId()) { case R.id.menu_mute_button: { - IUser self = getService().getSessionUser(); + IUser self = session.getSessionUser(); boolean muted = !self.isSelfMuted(); boolean deafened = self.isSelfDeafened(); deafened &= muted; // Undeafen if mute is off - getService().setSelfMuteDeafState(muted, deafened); + session.setSelfMuteDeafState(muted, deafened); getActivity().supportInvalidateOptionsMenu(); return true; } case R.id.menu_deafen_button: { - IUser self = getService().getSessionUser(); + IUser self = session.getSessionUser(); boolean deafened = !self.isSelfDeafened(); - getService().setSelfMuteDeafState(deafened, deafened); + session.setSelfMuteDeafState(deafened, deafened); getActivity().supportInvalidateOptionsMenu(); return true; @@ -295,9 +305,9 @@ public class ChannelListFragment extends JumbleServiceFragment implements OnChan case R.id.menu_bluetooth: item.setChecked(!item.isChecked()); if (item.isChecked()) { - getService().enableBluetoothSco(); + session.enableBluetoothSco(); } else { - getService().disableBluetoothSco(); + session.disableBluetoothSco(); } return true; } diff --git a/app/src/main/java/com/morlunk/mumbleclient/channel/ChannelMenu.java b/app/src/main/java/com/morlunk/mumbleclient/channel/ChannelMenu.java index 3044a6b..cca5866 100644 --- a/app/src/main/java/com/morlunk/mumbleclient/channel/ChannelMenu.java +++ b/app/src/main/java/com/morlunk/mumbleclient/channel/ChannelMenu.java @@ -35,6 +35,7 @@ import android.widget.LinearLayout; import android.widget.Toast; import com.morlunk.jumble.IJumbleService; +import com.morlunk.jumble.IJumbleSession; import com.morlunk.jumble.JumbleService; import com.morlunk.jumble.model.IChannel; import com.morlunk.jumble.model.Server; @@ -74,21 +75,26 @@ public class ChannelMenu implements PermissionsPopupMenu.IOnMenuPrepareListener, menu.findItem(R.id.context_channel_view_description) .setVisible(mChannel.getDescription() != null || mChannel.getDescriptionHash() != null); - Server server = mService.getConnectedServer(); + Server server = mService.getTargetServer(); if(server != null) { menu.findItem(R.id.context_channel_pin) .setChecked(mDatabase.isChannelPinned(server.getId(), mChannel.getId())); } - menu.findItem(R.id.context_channel_link) - .setChecked(mChannel.getLinks().contains(mService.getSessionChannel())); + if (mService.isConnected()) { + menu.findItem(R.id.context_channel_link) + .setChecked(mChannel.getLinks().contains(mService.getSession().getSessionChannel())); + } } @Override public boolean onMenuItemClick(MenuItem item) { + if (!mService.isConnected()) + return false; + boolean adding = false; switch(item.getItemId()) { case R.id.context_channel_join: - mService.joinChannel(mChannel.getId()); + mService.getSession().joinChannel(mChannel.getId()); break; case R.id.context_channel_add: adding = true; @@ -108,7 +114,9 @@ public class ChannelMenu implements PermissionsPopupMenu.IOnMenuPrepareListener, adb.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - mService.removeChannel(mChannel.getId()); + if (mService.isConnected()) { + mService.getSession().removeChannel(mChannel.getId()); + } } }); adb.setNegativeButton(android.R.string.cancel, null); @@ -124,22 +132,22 @@ public class ChannelMenu implements PermissionsPopupMenu.IOnMenuPrepareListener, commentFragment.show(mFragmentManager, ChannelDescriptionFragment.class.getName()); break; case R.id.context_channel_pin: - long serverId = mService.getConnectedServer().getId(); + long serverId = mService.getTargetServer().getId(); boolean pinned = mDatabase.isChannelPinned(serverId, mChannel.getId()); if(!pinned) mDatabase.addPinnedChannel(serverId, mChannel.getId()); else mDatabase.removePinnedChannel(serverId, mChannel.getId()); break; case R.id.context_channel_link: { - IChannel channel = mService.getSessionChannel(); + IChannel channel = mService.getSession().getSessionChannel(); if (!item.isChecked()) { - mService.linkChannels(channel, mChannel); + mService.getSession().linkChannels(channel, mChannel); } else { - mService.unlinkChannels(channel, mChannel); + mService.getSession().unlinkChannels(channel, mChannel); } break; } case R.id.context_channel_unlink_all: - mService.unlinkAllChannels(mChannel); + mService.getSession().unlinkAllChannels(mChannel); break; case R.id.context_channel_shout: { AlertDialog.Builder builder = new AlertDialog.Builder(mContext); @@ -159,20 +167,21 @@ public class ChannelMenu implements PermissionsPopupMenu.IOnMenuPrepareListener, builder.setPositiveButton(R.string.confirm, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - if (mService == null || - mService.getConnectionState() != JumbleService.ConnectionState.CONNECTED) + if (!mService.isConnected()) return; + IJumbleSession session = mService.getSession(); + // Unregister any existing voice target. - if (mService.getVoiceTargetMode() == VoiceTargetMode.WHISPER) { - mService.unregisterWhisperTarget(mService.getVoiceTargetId()); + if (session.getVoiceTargetMode() == VoiceTargetMode.WHISPER) { + session.unregisterWhisperTarget(session.getVoiceTargetId()); } WhisperTargetChannel channelTarget = new WhisperTargetChannel(mChannel, linkedBox.isChecked(), subchannelBox.isChecked(), null); - byte id = mService.registerWhisperTarget(channelTarget); + byte id = session.registerWhisperTarget(channelTarget); if (id > 0) { - mService.setVoiceTargetId(id); + session.setVoiceTargetId(id); } else { Toast.makeText(mContext, R.string.shout_failed, Toast.LENGTH_LONG).show(); } diff --git a/app/src/main/java/com/morlunk/mumbleclient/channel/ChannelSearchProvider.java b/app/src/main/java/com/morlunk/mumbleclient/channel/ChannelSearchProvider.java index a713f82..30f1740 100644 --- a/app/src/main/java/com/morlunk/mumbleclient/channel/ChannelSearchProvider.java +++ b/app/src/main/java/com/morlunk/mumbleclient/channel/ChannelSearchProvider.java @@ -31,6 +31,7 @@ import android.os.RemoteException; import android.util.Log; import com.morlunk.jumble.IJumbleService; +import com.morlunk.jumble.IJumbleSession; import com.morlunk.jumble.JumbleService; import com.morlunk.jumble.model.Channel; import com.morlunk.jumble.model.IChannel; @@ -55,7 +56,7 @@ public class ChannelSearchProvider extends ContentProvider { private ServiceConnection mConn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { - mService = ((JumbleService.JumbleBinder) service).getService(); + mService = ((PlumbleService.PlumbleBinder) service).getService(); synchronized (mServiceLock) { mServiceLock.notify(); } @@ -113,6 +114,11 @@ public class ChannelSearchProvider extends ContentProvider { } } } + + if (!mService.isConnected()) + return null; + + IJumbleSession session = mService.getSession(); String query = ""; for(int x=0;x<selectionArgs.length;x++) { @@ -125,23 +131,17 @@ public class ChannelSearchProvider extends ContentProvider { MatrixCursor cursor = new MatrixCursor(new String[] { "_ID", SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA, SearchManager.SUGGEST_COLUMN_TEXT_1, SearchManager.SUGGEST_COLUMN_ICON_1, SearchManager.SUGGEST_COLUMN_TEXT_2, SearchManager.SUGGEST_COLUMN_INTENT_DATA }); - List<IChannel> channels; - List<IUser> users; - try { - channels = channelSearch(mService.getRootChannel(), query); - users = userSearch(mService.getRootChannel(), query); + List<IChannel> channels = channelSearch(session.getRootChannel(), query); + List<IUser> users = userSearch(session.getRootChannel(), query); - for(int x=0;x<channels.size();x++) { - IChannel channel = channels.get(x); - cursor.addRow(new Object[] { x, INTENT_DATA_CHANNEL, channel.getName(), R.drawable.ic_action_channels, getContext().getString(R.string.search_channel_users, channel.getSubchannelUserCount()), channel.getId() }); - } + for(int x=0;x<channels.size();x++) { + IChannel channel = channels.get(x); + cursor.addRow(new Object[] { x, INTENT_DATA_CHANNEL, channel.getName(), R.drawable.ic_action_channels, getContext().getString(R.string.search_channel_users, channel.getSubchannelUserCount()), channel.getId() }); + } - for(int x=0;x<users.size();x++) { - IUser user = users.get(x); - cursor.addRow(new Object[] { x, INTENT_DATA_USER, user.getName(), R.drawable.ic_action_user_dark, getContext().getString(R.string.user), user.getSession() }); - } - } catch (RemoteException e) { - e.printStackTrace(); + for(int x=0;x<users.size();x++) { + IUser user = users.get(x); + cursor.addRow(new Object[] { x, INTENT_DATA_USER, user.getName(), R.drawable.ic_action_user_dark, getContext().getString(R.string.user), user.getSession() }); } return cursor; } @@ -153,7 +153,7 @@ public class ChannelSearchProvider extends ContentProvider { * @param str The string to match against the user's name. Case insensitive. * @return A list of users whose names contain str. */ - private List<IUser> userSearch(IChannel root, String str) throws RemoteException { + private List<IUser> userSearch(IChannel root, String str) { List<IUser> list = new LinkedList<IUser>(); userSearch(root, str, list); return list; @@ -162,7 +162,7 @@ public class ChannelSearchProvider extends ContentProvider { /** * @see #userSearch(IChannel,String) */ - private void userSearch(IChannel root, String str, List<IUser> users) throws RemoteException { + private void userSearch(IChannel root, String str, List<IUser> users) { if (root == null) { return; } @@ -185,7 +185,7 @@ public class ChannelSearchProvider extends ContentProvider { * @param str The string to match against the channel's name. Case insensitive. * @return A list of channels whose names contain str. */ - private List<IChannel> channelSearch(IChannel root, String str) throws RemoteException { + private List<IChannel> channelSearch(IChannel root, String str) { List<IChannel> list = new LinkedList<IChannel>(); channelSearch(root, str, list); return list; @@ -194,7 +194,7 @@ public class ChannelSearchProvider extends ContentProvider { /** * @see #channelSearch(IChannel,String) */ - private void channelSearch(IChannel root, String str, List<IChannel> channels) throws RemoteException { + private void channelSearch(IChannel root, String str, List<IChannel> channels) { if (root == null) { return; } diff --git a/app/src/main/java/com/morlunk/mumbleclient/channel/PermissionsPopupMenu.java b/app/src/main/java/com/morlunk/mumbleclient/channel/PermissionsPopupMenu.java index 2f96df3..4d6d80a 100644 --- a/app/src/main/java/com/morlunk/mumbleclient/channel/PermissionsPopupMenu.java +++ b/app/src/main/java/com/morlunk/mumbleclient/channel/PermissionsPopupMenu.java @@ -62,14 +62,20 @@ public class PermissionsPopupMenu implements PopupMenu.OnDismissListener { } private int getPermissions() { - return mChannel.getId() == 0 ? mService.getPermissions() : mChannel.getPermissions(); + if (mService.isConnected()) { + return mChannel.getId() == 0 ? mService.getSession().getPermissions() + : mChannel.getPermissions(); + } + return 0; } public void show() { mService.registerObserver(mPermissionsObserver); if (getPermissions() == 0) { // onMenuPrepare will be called once more once permissions have loaded. - mService.requestPermissions(mChannel.getId()); + if (mService.isConnected()) { + mService.getSession().requestPermissions(mChannel.getId()); + } } else { mPrepareListener.onMenuPrepare(mMenu.getMenu(), getPermissions()); } diff --git a/app/src/main/java/com/morlunk/mumbleclient/channel/ServerInfoFragment.java b/app/src/main/java/com/morlunk/mumbleclient/channel/ServerInfoFragment.java index ff173b0..7f83bb3 100644 --- a/app/src/main/java/com/morlunk/mumbleclient/channel/ServerInfoFragment.java +++ b/app/src/main/java/com/morlunk/mumbleclient/channel/ServerInfoFragment.java @@ -27,6 +27,7 @@ import android.view.ViewGroup; import android.widget.TextView; import com.morlunk.jumble.IJumbleService; +import com.morlunk.jumble.IJumbleSession; import com.morlunk.jumble.JumbleService; import com.morlunk.jumble.net.JumbleConnection; import com.morlunk.jumble.net.JumbleUDPMessageType; @@ -77,18 +78,19 @@ public class ServerInfoFragment extends JumbleServiceFragment { * Updates the info from the service. */ public void updateData() throws RemoteException { - if(getService() == null - || !getService().isSynchronized()) + if(getService() == null || !getService().isConnected()) return; - mProtocolView.setText(getString(R.string.server_info_protocol, getService().getServerRelease())); - mOSVersionView.setText(getString(R.string.server_info_version, getService().getServerOSName(), getService().getServerOSVersion())); - mTCPLatencyView.setText(getString(R.string.server_info_latency, (float)getService().getTCPLatency()*Math.pow(10, -3))); - mUDPLatencyView.setText(getString(R.string.server_info_latency, (float)getService().getUDPLatency()*Math.pow(10, -3))); - mHostView.setText(getString(R.string.server_info_host, getService().getConnectedServer().getHost(), getService().getConnectedServer().getPort())); + IJumbleSession session = getService().getSession(); + + mProtocolView.setText(getString(R.string.server_info_protocol, session.getServerRelease())); + mOSVersionView.setText(getString(R.string.server_info_version, session.getServerOSName(), session.getServerOSVersion())); + mTCPLatencyView.setText(getString(R.string.server_info_latency, (float)session.getTCPLatency()*Math.pow(10, -3))); + mUDPLatencyView.setText(getString(R.string.server_info_latency, (float)session.getUDPLatency()*Math.pow(10, -3))); + mHostView.setText(getString(R.string.server_info_host, getService().getTargetServer().getHost(), getService().getTargetServer().getPort())); String codecName; - JumbleUDPMessageType codecType = getService().getCodec(); + JumbleUDPMessageType codecType = session.getCodec(); switch (codecType) { case UDPVoiceOpus: codecName = "Opus"; @@ -106,8 +108,8 @@ public class ServerInfoFragment extends JumbleServiceFragment { codecName = "???"; } - mMaxBandwidthView.setText(getString(R.string.server_info_max_bandwidth, (float)getService().getMaxBandwidth()/1000f)); - mCurrentBandwidthView.setText(getString(R.string.server_info_current_bandwidth, (float)getService().getCurrentBandwidth()/1000f)); + mMaxBandwidthView.setText(getString(R.string.server_info_max_bandwidth, (float)session.getMaxBandwidth()/1000f)); + mCurrentBandwidthView.setText(getString(R.string.server_info_current_bandwidth, (float)session.getCurrentBandwidth()/1000f)); mCodecView.setText(getString(R.string.server_info_codec, codecName)); } diff --git a/app/src/main/java/com/morlunk/mumbleclient/channel/UserMenu.java b/app/src/main/java/com/morlunk/mumbleclient/channel/UserMenu.java index 8a66859..e67a5f0 100644 --- a/app/src/main/java/com/morlunk/mumbleclient/channel/UserMenu.java +++ b/app/src/main/java/com/morlunk/mumbleclient/channel/UserMenu.java @@ -21,7 +21,6 @@ import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; -import android.os.RemoteException; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v7.widget.PopupMenu; @@ -62,7 +61,7 @@ public class UserMenu implements PermissionsPopupMenu.IOnMenuPrepareListener, Po @Override public void onMenuPrepare(Menu menu, int permissions) { // Use permission data to determine the actions available. - boolean self = mUser.getSession() == mService.getSession(); + boolean self = mUser.getSession() == mService.getSessionId(); int perms = mService.getPermissions(); IChannel channel = mUser.getChannel(); int channelPerms = channel.getId() != 0 ? channel.getPermissions() : perms; @@ -95,7 +94,7 @@ public class UserMenu implements PermissionsPopupMenu.IOnMenuPrepareListener, Po menu.findItem(R.id.context_ignore_messages).setVisible(!self); // TODO info -// informationItem.enabled = (((perms & (Permissions.Write | Permissions.Register))) > 0 || (channelPermissions & (Permissions.Write | Permissions.Enter)) > 0 || (mUser.getSession() == mService.getSession())); +// informationItem.enabled = (((perms & (Permissions.Write | Permissions.Register))) > 0 || (channelPermissions & (Permissions.Write | Permissions.Enter)) > 0 || (mUser.getSessionId() == mService.getSessionId())); // Highlight toggles menu.findItem(R.id.context_mute).setChecked(mUser.isMuted() || mUser.isSuppressed()); diff --git a/app/src/main/java/com/morlunk/mumbleclient/channel/comment/ChannelDescriptionFragment.java b/app/src/main/java/com/morlunk/mumbleclient/channel/comment/ChannelDescriptionFragment.java index f049d66..4b9708b 100644 --- a/app/src/main/java/com/morlunk/mumbleclient/channel/comment/ChannelDescriptionFragment.java +++ b/app/src/main/java/com/morlunk/mumbleclient/channel/comment/ChannelDescriptionFragment.java @@ -31,6 +31,8 @@ public class ChannelDescriptionFragment extends AbstractCommentFragment { @Override public void requestComment(final IJumbleService service) { + if (!service.isConnected()) + return; service.registerObserver(new JumbleObserver() { @Override public void onChannelStateUpdated(IChannel channel) { @@ -41,7 +43,7 @@ public class ChannelDescriptionFragment extends AbstractCommentFragment { } } }); - service.requestChannelDescription(getChannelId()); + service.getSession().requestChannelDescription(getChannelId()); } @Override diff --git a/app/src/main/java/com/morlunk/mumbleclient/channel/comment/UserCommentFragment.java b/app/src/main/java/com/morlunk/mumbleclient/channel/comment/UserCommentFragment.java index adec7e7..d80dc9c 100644 --- a/app/src/main/java/com/morlunk/mumbleclient/channel/comment/UserCommentFragment.java +++ b/app/src/main/java/com/morlunk/mumbleclient/channel/comment/UserCommentFragment.java @@ -31,6 +31,8 @@ public class UserCommentFragment extends AbstractCommentFragment { @Override public void requestComment(final IJumbleService service) { + if (!service.isConnected()) + return; service.registerObserver(new JumbleObserver() { @Override public void onUserStateUpdated(IUser user) { @@ -41,12 +43,14 @@ public class UserCommentFragment extends AbstractCommentFragment { } } }); - service.requestComment(getSession()); + service.getSession().requestComment(getSession()); } @Override public void editComment(IJumbleService service, String comment) { - service.setUserComment(getSession(), comment); + if (!service.isConnected()) + return; + service.getSession().setUserComment(getSession(), comment); } public int getSession() { diff --git a/app/src/main/java/com/morlunk/mumbleclient/service/IPlumbleService.java b/app/src/main/java/com/morlunk/mumbleclient/service/IPlumbleService.java new file mode 100644 index 0000000..cc5f768 --- /dev/null +++ b/app/src/main/java/com/morlunk/mumbleclient/service/IPlumbleService.java @@ -0,0 +1,30 @@ +package com.morlunk.mumbleclient.service; + +import com.morlunk.jumble.IJumbleService; + +import java.util.List; + +/** + * Created by andrew on 28/02/17. + */ +public interface IPlumbleService extends IJumbleService { + void setOverlayShown(boolean showOverlay); + + boolean isOverlayShown(); + + void clearChatNotifications(); + + void markErrorShown(); + + boolean isErrorShown(); + + void onTalkKeyDown(); + + void onTalkKeyUp(); + + List<IChatMessage> getMessageLog(); + + void clearMessageLog(); + + void setSuppressNotifications(boolean suppressNotifications); +} diff --git a/app/src/main/java/com/morlunk/mumbleclient/service/PlumbleOverlay.java b/app/src/main/java/com/morlunk/mumbleclient/service/PlumbleOverlay.java index 934ea35..7e5bfe4 100644 --- a/app/src/main/java/com/morlunk/mumbleclient/service/PlumbleOverlay.java +++ b/app/src/main/java/com/morlunk/mumbleclient/service/PlumbleOverlay.java @@ -19,7 +19,6 @@ package com.morlunk.mumbleclient.service; import android.content.Context; import android.graphics.PixelFormat; -import android.os.RemoteException; import android.util.DisplayMetrics; import android.view.Gravity; import android.view.MotionEvent; @@ -28,10 +27,8 @@ import android.view.WindowManager; import android.widget.ImageView; import android.widget.ListView; -import com.morlunk.jumble.model.Channel; import com.morlunk.jumble.model.IChannel; import com.morlunk.jumble.model.IUser; -import com.morlunk.jumble.model.User; import com.morlunk.jumble.util.JumbleObserver; import com.morlunk.mumbleclient.R; import com.morlunk.mumbleclient.Settings; @@ -61,7 +58,7 @@ public class PlumbleOverlay { @Override public void onUserJoinedChannel(IUser user, IChannel newChannel, IChannel oldChannel) { - if(user.getSession() == mService.getSession()) // Session user has changed channels + if(user.getSession() == mService.getSessionId()) // Session user has changed channels mChannelAdapter.setChannel(mService.getSessionChannel()); else if(newChannel.getId() == mService.getSessionChannel().getId() || oldChannel.getId() == mService.getSessionChannel().getId()) diff --git a/app/src/main/java/com/morlunk/mumbleclient/service/PlumbleService.java b/app/src/main/java/com/morlunk/mumbleclient/service/PlumbleService.java index 598127b..30865ba 100644 --- a/app/src/main/java/com/morlunk/mumbleclient/service/PlumbleService.java +++ b/app/src/main/java/com/morlunk/mumbleclient/service/PlumbleService.java @@ -19,10 +19,13 @@ package com.morlunk.mumbleclient.service; import android.app.AlertDialog; import android.content.BroadcastReceiver; +import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.media.AudioManager; +import android.os.Binder; import android.os.Bundle; +import android.os.IBinder; import android.os.PowerManager; import android.preference.PreferenceManager; import android.speech.tts.TextToSpeech; @@ -55,7 +58,7 @@ import java.util.List; public class PlumbleService extends JumbleService implements SharedPreferences.OnSharedPreferenceChangeListener, PlumbleConnectionNotification.OnActionListener, - PlumbleReconnectNotification.OnActionListener { + PlumbleReconnectNotification.OnActionListener, IPlumbleService { /** Undocumented constant that permits a proximity-sensing wake lock. */ public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = 32; public static final int TTS_THRESHOLD = 250; // Maximum number of characters to read @@ -162,7 +165,7 @@ public class PlumbleService extends JumbleService implements @Override public void onUserStateUpdated(IUser user) { - if(user.getSession() == getSession()) { + if(user.getSession() == getSessionId()) { mSettings.setMutedAndDeafened(user.isSelfMuted(), user.isSelfDeafened()); // Update settings mute/deafen state if(mNotification != null && !mSuppressNotifications) { String contentText; @@ -254,7 +257,7 @@ public class PlumbleService extends JumbleService implements @Override public void onUserTalkStateUpdated(IUser user) { if (isConnectionEstablished() && - getSession() == user.getSession() && + getSessionId() == user.getSession() && getTransmitMode() == Constants.TRANSMIT_PUSH_TO_TALK && user.getTalkState() == TalkState.TALKING && mPTTSoundEnabled) { @@ -294,6 +297,11 @@ public class PlumbleService extends JumbleService implements } @Override + public IBinder onBind(Intent intent) { + return new PlumbleBinder(this); + } + + @Override public void onDestroy() { if (mNotification != null) { mNotification.hide(); @@ -505,6 +513,7 @@ public class PlumbleService extends JumbleService implements super.cancelReconnect(); } + @Override public void setOverlayShown(boolean showOverlay) { if(!mChannelOverlay.isShown()) { mChannelOverlay.show(); @@ -513,14 +522,17 @@ public class PlumbleService extends JumbleService implements } } + @Override public boolean isOverlayShown() { return mChannelOverlay.isShown(); } + @Override public void clearChatNotifications() { mMessageNotification.dismiss(); } + @Override public void markErrorShown() { mErrorShown = true; // Dismiss the reconnection prompt if a reconnection isn't in progress. @@ -530,6 +542,7 @@ public class PlumbleService extends JumbleService implements } } + @Override public boolean isErrorShown() { return mErrorShown; } @@ -538,6 +551,7 @@ public class PlumbleService extends JumbleService implements * Called when a user presses a talk key down (i.e. when they want to talk). * Accounts for talk logic if toggle PTT is on. */ + @Override public void onTalkKeyDown() { if(isConnectionEstablished() && Settings.ARRAY_INPUT_METHOD_PTT.equals(mSettings.getInputMethod())) { @@ -551,6 +565,7 @@ public class PlumbleService extends JumbleService implements * Called when a user releases a talk key (i.e. when they do not want to talk). * Accounts for talk logic if toggle PTT is on. */ + @Override public void onTalkKeyUp() { if(isConnectionEstablished() && Settings.ARRAY_INPUT_METHOD_PTT.equals(mSettings.getInputMethod())) { @@ -562,10 +577,12 @@ public class PlumbleService extends JumbleService implements } } + @Override public List<IChatMessage> getMessageLog() { return Collections.unmodifiableList(mMessageLog); } + @Override public void clearMessageLog() { mMessageLog.clear(); } @@ -581,7 +598,20 @@ public class PlumbleService extends JumbleService implements * * @param suppressNotifications true if Plumble is to disable notifications. */ + @Override public void setSuppressNotifications(boolean suppressNotifications) { mSuppressNotifications = suppressNotifications; } + + public static class PlumbleBinder extends Binder { + private final PlumbleService mService; + + private PlumbleBinder(PlumbleService service) { + mService = service; + } + + public IPlumbleService getService() { + return mService; + } + } } diff --git a/app/src/main/java/com/morlunk/mumbleclient/service/ipc/TalkBroadcastReceiver.java b/app/src/main/java/com/morlunk/mumbleclient/service/ipc/TalkBroadcastReceiver.java index 9166fbf..4a8853a 100644 --- a/app/src/main/java/com/morlunk/mumbleclient/service/ipc/TalkBroadcastReceiver.java +++ b/app/src/main/java/com/morlunk/mumbleclient/service/ipc/TalkBroadcastReceiver.java @@ -22,6 +22,7 @@ import android.content.Context; import android.content.Intent; import com.morlunk.jumble.IJumbleService; +import com.morlunk.jumble.IJumbleSession; /** * Created by andrew on 08/08/14. @@ -42,14 +43,17 @@ public class TalkBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (BROADCAST_TALK.equals(intent.getAction())) { + if (!mService.isConnected()) + return; + IJumbleSession session = mService.getSession(); String status = intent.getStringExtra(EXTRA_TALK_STATUS); if (status == null) status = TALK_STATUS_TOGGLE; if (TALK_STATUS_ON.equals(status)) { - mService.setTalkingState(true); + session.setTalkingState(true); } else if (TALK_STATUS_OFF.equals(status)) { - mService.setTalkingState(false); + session.setTalkingState(false); } else if (TALK_STATUS_TOGGLE.equals(status)) { - mService.setTalkingState(!mService.isTalking()); + session.setTalkingState(!session.isTalking()); } } else { throw new UnsupportedOperationException(); diff --git a/app/src/main/java/com/morlunk/mumbleclient/util/JumbleServiceFragment.java b/app/src/main/java/com/morlunk/mumbleclient/util/JumbleServiceFragment.java index cde3c7c..c7f57ea 100644 --- a/app/src/main/java/com/morlunk/mumbleclient/util/JumbleServiceFragment.java +++ b/app/src/main/java/com/morlunk/mumbleclient/util/JumbleServiceFragment.java @@ -26,6 +26,7 @@ import android.view.View; import com.morlunk.jumble.IJumbleService; import com.morlunk.jumble.util.IJumbleObserver; +import com.morlunk.mumbleclient.service.IPlumbleService; import com.morlunk.mumbleclient.service.PlumbleService; /** @@ -99,7 +100,7 @@ public abstract class JumbleServiceFragment extends Fragment { onServiceDetached(mServiceProvider.getService()); } - public PlumbleService getService() { + public IPlumbleService getService() { return mServiceProvider.getService(); } } diff --git a/app/src/main/java/com/morlunk/mumbleclient/util/JumbleServiceProvider.java b/app/src/main/java/com/morlunk/mumbleclient/util/JumbleServiceProvider.java index 797c68a..36ac810 100644 --- a/app/src/main/java/com/morlunk/mumbleclient/util/JumbleServiceProvider.java +++ b/app/src/main/java/com/morlunk/mumbleclient/util/JumbleServiceProvider.java @@ -18,13 +18,14 @@ package com.morlunk.mumbleclient.util; import com.morlunk.jumble.IJumbleService; +import com.morlunk.mumbleclient.service.IPlumbleService; import com.morlunk.mumbleclient.service.PlumbleService; /** * Created by andrew on 03/08/13. */ public interface JumbleServiceProvider { - PlumbleService getService(); + IPlumbleService getService(); void addServiceFragment(JumbleServiceFragment fragment); void removeServiceFragment(JumbleServiceFragment fragment); } diff --git a/libraries/Jumble b/libraries/Jumble -Subproject dfdd83dee1707ddc90776e0483ad1b5f9c9db29 +Subproject 4a44ab69bdf4bd2c755f694dbac95fcc0637307 |