Skip to content
This repository was archived by the owner on Jul 25, 2024. It is now read-only.

Commit 95c7c1c

Browse files
committed
Connection Status: Added Network Broadcast Receiver
Fixes #312
1 parent a4374c1 commit 95c7c1c

File tree

4 files changed

+206
-1
lines changed

4 files changed

+206
-1
lines changed

app/src/main/java/com/zulip/android/activities/ZulipActivity.java

+37
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
import android.graphics.Bitmap;
2929
import android.graphics.PorterDuff;
3030
import android.graphics.drawable.Drawable;
31+
import android.net.ConnectivityManager;
32+
import android.net.NetworkInfo;
3133
import android.net.Uri;
3234
import android.os.Build;
3335
import android.os.Bundle;
@@ -183,6 +185,7 @@ public class ZulipActivity extends BaseActivity implements
183185
private SimpleCursorAdapter emailActvAdapter;
184186
private AppBarLayout appBarLayout;
185187
private MutedTopics mMutedTopics;
188+
private BroadcastReceiver networkStateReceiver;
186189
private BroadcastReceiver onGcmMessage = new BroadcastReceiver() {
187190
public void onReceive(Context contenxt, Intent intent) {
188191
// Block the event before it propagates to show a notification.
@@ -553,6 +556,7 @@ public Cursor runQuery(CharSequence charSequence) {
553556
handleOnFragmentChange();
554557
calendar = Calendar.getInstance();
555558
setupSnackBar();
559+
setupNetworkBroadcastReceiver();
556560
}
557561

558562
/**
@@ -1976,6 +1980,7 @@ protected void onPause() {
19761980
Log.i("status", "suspend");
19771981

19781982
unregisterReceiver(onGcmMessage);
1983+
unregisterReceiver(networkStateReceiver);
19791984

19801985
if (event_poll != null) {
19811986
event_poll.abort();
@@ -1997,6 +2002,9 @@ protected void onResume() {
19972002
filter.setPriority(2);
19982003
registerReceiver(onGcmMessage, filter);
19992004

2005+
// Registering network state broadcast receiver
2006+
setupNetworkBroadcastReceiver();
2007+
20002008
homeList.onActivityResume();
20012009
if (narrowedList != null) {
20022010
narrowedList.onActivityResume();
@@ -2141,4 +2149,33 @@ public void onClick(View view) {
21412149
public enum Flag {
21422150
RESET_DATABASE,
21432151
}
2152+
public void setupNetworkBroadcastReceiver()
2153+
{
2154+
networkStateReceiver = new BroadcastReceiver() {
2155+
final CoordinatorLayout coordinatorLayout = (CoordinatorLayout) findViewById(R.id.coordinatorLayout);
2156+
@Override
2157+
public void onReceive(Context context, Intent intent) {
2158+
Log.d("Network Listener", "Network Type Changed");
2159+
if(!isNetworkAvailable()){
2160+
//Remove chatBox when network connectivity is lost
2161+
displayChatBox(false);
2162+
Snackbar.make(coordinatorLayout,R.string.no_connection,Snackbar.LENGTH_INDEFINITE).show();
2163+
Log.d("Network Listener", "No Internet");
2164+
}
2165+
else{
2166+
Snackbar.make(coordinatorLayout,R.string.connection_established,Snackbar.LENGTH_SHORT).show();
2167+
Log.d("Network Listener", "Internet");
2168+
}
2169+
}
2170+
};
2171+
2172+
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
2173+
registerReceiver(networkStateReceiver, filter);
2174+
}
2175+
private boolean isNetworkAvailable() {
2176+
ConnectivityManager connectivityManager
2177+
= (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
2178+
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
2179+
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
2180+
}
21442181
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
package com.zulip.android.util;
2+
3+
import android.animation.Animator;
4+
import android.annotation.SuppressLint;
5+
import android.content.Context;
6+
import android.support.design.widget.AppBarLayout;
7+
import android.support.design.widget.CoordinatorLayout;
8+
import android.support.design.widget.FloatingActionButton;
9+
import android.support.design.widget.Snackbar;
10+
import android.support.v4.view.ViewCompat;
11+
import android.support.v4.view.animation.FastOutSlowInInterpolator;
12+
import android.util.AttributeSet;
13+
import android.util.TypedValue;
14+
import android.view.View;
15+
import android.view.ViewPropertyAnimator;
16+
import android.view.animation.Interpolator;
17+
18+
import com.zulip.android.R;
19+
20+
import java.util.List;
21+
22+
/**
23+
* This hides the {@link AppBarLayout} and {@link android.support.design.widget.FloatingActionButton} when the
24+
* recyclerView is scrolled, used in here {@link com.zulip.android.R.layout#main} as a behaviour.
25+
*/
26+
public class RemoveFabOnScroll extends CoordinatorLayout.Behavior<FloatingActionButton> {
27+
private static final Interpolator FAST_OUT_SLOW_IN_INTERPOLATOR = new FastOutSlowInInterpolator();
28+
private static float toolbarHeight;
29+
private int changeInYDir;
30+
private boolean mIsShowing;
31+
private boolean isViewHidden;
32+
private View chatBox;
33+
34+
public RemoveFabOnScroll(Context context, AttributeSet attrs) {
35+
super(context, attrs);
36+
TypedValue tv = new TypedValue();
37+
if (context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true))
38+
toolbarHeight = TypedValue.complexToDimensionPixelSize(tv.data, context.getResources().getDisplayMetrics());
39+
}
40+
41+
@Override
42+
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View directTargetChild, View target, int nestedScrollAxes) {
43+
return (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0;
44+
}
45+
46+
@SuppressLint("NewApi")
47+
@Override
48+
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View target, int dx, int dy, int[] consumed) {
49+
if (dy > 0 && changeInYDir < 0 || dy < 0 && changeInYDir > 0) {
50+
child.animate().cancel();
51+
changeInYDir = 0;
52+
}
53+
54+
changeInYDir += dy;
55+
if (changeInYDir > toolbarHeight && child.getVisibility() == View.VISIBLE && !isViewHidden)
56+
hideView(child);
57+
else if (changeInYDir < 0 && child.getVisibility() == View.GONE && !mIsShowing) {
58+
if (child instanceof FloatingActionButton) {
59+
if (chatBox == null)
60+
chatBox = coordinatorLayout.findViewById(R.id.messageBoxContainer);
61+
if (chatBox.getVisibility() == View.VISIBLE) {
62+
return;
63+
}
64+
}
65+
showView(child);
66+
}
67+
68+
}
69+
70+
@SuppressLint("NewApi")
71+
private void hideView(final View view) {
72+
isViewHidden = true;
73+
ViewPropertyAnimator animator = view.animate()
74+
.translationY((view instanceof AppBarLayout) ? -1 * view.getHeight() : view.getHeight())
75+
.setInterpolator(FAST_OUT_SLOW_IN_INTERPOLATOR)
76+
.setDuration(200);
77+
78+
animator.setListener(new Animator.AnimatorListener() {
79+
@Override
80+
public void onAnimationStart(Animator animator) {
81+
}
82+
83+
@Override
84+
public void onAnimationEnd(Animator animator) {
85+
isViewHidden = false;
86+
view.setVisibility(View.GONE);
87+
}
88+
89+
@Override
90+
public void onAnimationCancel(Animator animator) {
91+
isViewHidden = false;
92+
if (!mIsShowing)
93+
showView(view);
94+
}
95+
96+
@Override
97+
public void onAnimationRepeat(Animator animator) {
98+
}
99+
});
100+
animator.start();
101+
}
102+
103+
@SuppressLint("NewApi")
104+
private void showView(final View view) {
105+
mIsShowing = true;
106+
ViewPropertyAnimator animator = view.animate()
107+
.translationY(0)
108+
.setInterpolator(FAST_OUT_SLOW_IN_INTERPOLATOR)
109+
.setDuration(200);
110+
111+
animator.setListener(new Animator.AnimatorListener() {
112+
@Override
113+
public void onAnimationStart(Animator animator) {
114+
view.setVisibility(View.VISIBLE);
115+
}
116+
117+
@Override
118+
public void onAnimationEnd(Animator animator) {
119+
mIsShowing = false;
120+
}
121+
122+
@Override
123+
public void onAnimationCancel(Animator animator) {
124+
mIsShowing = false;
125+
if (!isViewHidden)
126+
hideView(view);
127+
}
128+
129+
@Override
130+
public void onAnimationRepeat(Animator animator) {
131+
}
132+
});
133+
animator.start();
134+
}
135+
136+
@Override
137+
public boolean layoutDependsOn(CoordinatorLayout parent, FloatingActionButton child, View dependency) {
138+
return dependency instanceof Snackbar.SnackbarLayout;
139+
}
140+
141+
@Override
142+
public boolean onDependentViewChanged(CoordinatorLayout parent, FloatingActionButton child, View dependency) {
143+
float translationY = getFabTranslationYForSnackbar(parent, child);
144+
float percentComplete = -translationY / dependency.getHeight();
145+
float scaleFactor = 1 - percentComplete;
146+
147+
child.setScaleX(scaleFactor);
148+
child.setScaleY(scaleFactor);
149+
return false;
150+
}
151+
152+
private float getFabTranslationYForSnackbar(CoordinatorLayout parent,
153+
FloatingActionButton fab) {
154+
float minOffset = 0;
155+
final List<View> dependencies = parent.getDependencies(fab);
156+
for (int i = 0, z = dependencies.size(); i < z; i++) {
157+
final View view = dependencies.get(i);
158+
if (view instanceof Snackbar.SnackbarLayout && parent.doViewsOverlap(fab, view)) {
159+
minOffset = Math.min(minOffset,
160+
ViewCompat.getTranslationY(view) - view.getHeight());
161+
}
162+
}
163+
164+
return minOffset;
165+
}
166+
}

app/src/main/res/layout/main.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
android:src="@drawable/ic_mode_edit_24dp"
5454
app:backgroundTint="@color/colorPrimary"
5555
app:borderWidth="0dp"
56-
app:layout_behavior="com.zulip.android.util.RemoveViewsOnScroll" />
56+
app:layout_behavior="com.zulip.android.util.RemoveFabOnScroll" />
5757
</android.support.design.widget.CoordinatorLayout>
5858

5959
<android.support.design.widget.NavigationView

app/src/main/res/values/strings.xml

+2
Original file line numberDiff line numberDiff line change
@@ -129,4 +129,6 @@
129129
<item quantity="one">%d new message</item>
130130
<item quantity="other">%d new messages</item>
131131
</plurals>
132+
<string name="no_connection">No Connection!</string>
133+
<string name="connection_established">Connection Established</string>
132134
</resources>

0 commit comments

Comments
 (0)