Fixes with TLSv1.1, TLSv1.2

This commit is contained in:
tom79 2017-05-20 19:40:46 +02:00
parent 3d23b66d81
commit 0775271098
13 changed files with 267 additions and 48 deletions

View File

@ -7,8 +7,8 @@ android {
applicationId "fr.gouv.etalab.mastodon"
minSdkVersion 15
targetSdkVersion 25
versionCode 5
versionName "1.0.5"
versionCode 6
versionName "1.0.6"
}
buildTypes {
release {

View File

@ -17,13 +17,9 @@ package fr.gouv.etalab.mastodon.activities;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.Html;
import android.text.method.LinkMovementMethod;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;

View File

@ -49,12 +49,22 @@ public class LoginActivity extends AppCompatActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
final Button connectionButton = (Button) findViewById(R.id.login_button);
final Intent webviewIntent = new Intent(this, WebviewActivity.class);
Button connectionButton = (Button) findViewById(R.id.login_button);
connectionButton.setEnabled(false);
}
@Override
protected void onResume(){
super.onResume();
Button connectionButton = (Button) findViewById(R.id.login_button);
if( !connectionButton.isEnabled())
retrievesClientId();
}
private void retrievesClientId(){
final Button connectionButton = (Button) findViewById(R.id.login_button);
final Intent webviewIntent = new Intent(this, WebviewActivity.class);
String action = "/api/v1/apps";
HashMap<String,String> parameters = new HashMap<>();
parameters.put(Helper.CLIENT_NAME, Helper.OAUTH_REDIRECT_HOST);
@ -99,10 +109,8 @@ public class LoginActivity extends AppCompatActivity {
finish();
}
});
}
}

View File

@ -115,6 +115,7 @@ public class MainActivity extends AppCompatActivity
navigationView.setNavigationItemSelectedListener(this);
//Image loader configuration
imageLoader = ImageLoader.getInstance();
File cacheDir = new File(getCacheDir(), getString(R.string.app_name));

View File

@ -14,7 +14,10 @@
* see <http://www.gnu.org/licenses>. */
package fr.gouv.etalab.mastodon.activities;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Build;
@ -23,6 +26,7 @@ import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
@ -31,6 +35,7 @@ import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
@ -79,8 +84,9 @@ public class ShowAccountActivity extends AppCompatActivity implements OnPostActi
private ViewPager mPager;
private String accountId;
private TabLayout tabLayout;
private BroadcastReceiver hide_header;
private TextView account_note;
private String userId;
public enum action{
FOLLOW,
@ -96,6 +102,9 @@ public class ShowAccountActivity extends AppCompatActivity implements OnPostActi
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_account);
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
imageLoader = ImageLoader.getInstance();
statuses = new ArrayList<>();
@ -111,7 +120,7 @@ public class ShowAccountActivity extends AppCompatActivity implements OnPostActi
accountId = b.getString("accountId");
new RetrieveRelationshipAsyncTask(getApplicationContext(), accountId,ShowAccountActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
new RetrieveAccountAsyncTask(getApplicationContext(),accountId, ShowAccountActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
if( accountId != null && accountId.equals(userId)){
account_follow.setVisibility(View.GONE);
}
@ -166,6 +175,30 @@ public class ShowAccountActivity extends AppCompatActivity implements OnPostActi
}
});
account_note = (TextView) findViewById(R.id.account_note);
//Register LocalBroadcast to receive selected accounts after search
hide_header = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
boolean hide = intent.getBooleanExtra("hide", false);
if( hide){
account_follow.setVisibility(View.GONE);
account_note.setVisibility(View.GONE);
tabLayout.setVisibility(View.GONE);
}else {
account_follow.setVisibility(View.VISIBLE);
if( accountId != null && accountId.equals(userId)){
account_follow.setVisibility(View.GONE);
}
tabLayout.setVisibility(View.VISIBLE);
account_note.setVisibility(View.VISIBLE);
}
}
};
LocalBroadcastManager.getInstance(this).registerReceiver(hide_header, new IntentFilter(Helper.HEADER_ACCOUNT));
//Follow button
account_follow.setOnClickListener(new View.OnClickListener() {
@Override
@ -208,7 +241,7 @@ public class ShowAccountActivity extends AppCompatActivity implements OnPostActi
TextView account_dn = (TextView) findViewById(R.id.account_dn);
TextView account_un = (TextView) findViewById(R.id.account_un);
TextView account_ac = (TextView) findViewById(R.id.account_ac);
TextView account_note = (TextView) findViewById(R.id.account_note);
if( account != null){
setTitle(account.getAcct());
account_dn.setText(account.getDisplay_name());
@ -239,6 +272,12 @@ public class ShowAccountActivity extends AppCompatActivity implements OnPostActi
}
}
@Override
public void onDestroy(){
super.onDestroy();
LocalBroadcastManager.getInstance(this).unregisterReceiver(hide_header);
}
@Override
public void onRetrieveRelationship(Relationship relationship) {
if( relationship.isBlocking()){
@ -287,18 +326,21 @@ public class ShowAccountActivity extends AppCompatActivity implements OnPostActi
DisplayStatusFragment displayStatusFragment = new DisplayStatusFragment();
bundle.putSerializable("type", RetrieveFeedsAsyncTask.Type.USER);
bundle.putString("targetedId", accountId);
bundle.putBoolean("hideHeader",true);
displayStatusFragment.setArguments(bundle);
return displayStatusFragment;
case 1:
DisplayAccountsFragment displayAccountsFragment = new DisplayAccountsFragment();
bundle.putSerializable("type", RetrieveAccountsAsyncTask.Type.FOLLOWING);
bundle.putString("targetedId", accountId);
bundle.putBoolean("hideHeader",true);
displayAccountsFragment.setArguments(bundle);
return displayAccountsFragment;
case 2:
displayAccountsFragment = new DisplayAccountsFragment();
bundle.putSerializable("type", RetrieveAccountsAsyncTask.Type.FOLLOWERS);
bundle.putString("targetedId", accountId);
bundle.putBoolean("hideHeader",true);
displayAccountsFragment.setArguments(bundle);
return displayAccountsFragment;
}

View File

@ -16,10 +16,12 @@ package fr.gouv.etalab.mastodon.asynctasks;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import java.util.List;
import fr.gouv.etalab.mastodon.client.API;
import fr.gouv.etalab.mastodon.helper.Helper;
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveFeedsInterface;

View File

@ -16,7 +16,6 @@ package fr.gouv.etalab.mastodon.client;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
import com.loopj.android.http.AsyncHttpResponseHandler;
import com.loopj.android.http.JsonHttpResponseHandler;
@ -29,6 +28,10 @@ import org.json.JSONObject;
import java.io.InputStream;
import java.lang.*;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.util.ArrayList;
import java.util.List;
@ -42,6 +45,8 @@ import fr.gouv.etalab.mastodon.client.Entities.Notification;
import fr.gouv.etalab.mastodon.client.Entities.Relationship;
import fr.gouv.etalab.mastodon.client.Entities.Status;
import static fr.gouv.etalab.mastodon.helper.Helper.USER_AGENT;
/**
* Created by Thomas on 23/04/2017.
@ -66,7 +71,6 @@ public class API {
private List<Notification> notifications;
private int tootPerPage, accountPerPage, notificationPerPage;
private int actionCode;
private String userId;
public enum StatusAction{
FAVOURITE,
@ -90,7 +94,6 @@ public class API {
tootPerPage = sharedpreferences.getInt(Helper.SET_TOOTS_PER_PAGE, 40);
accountPerPage = sharedpreferences.getInt(Helper.SET_ACCOUNTS_PER_PAGE, 40);
notificationPerPage = sharedpreferences.getInt(Helper.SET_NOTIFICATIONS_PER_PAGE, 40);
userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
}
/***
@ -308,7 +311,7 @@ public class API {
}
/**
* Retrieves home timeline for the account since an id *synchronously*
* Retrieves home timeline for the account since an Id value *synchronously*
* @return List<Status>
*/
public List<Status> getHomeTimelineSinceId(String since_id) {
@ -352,14 +355,6 @@ public class API {
return statuses;
}
/**
* Retrieves public timeline for the account *synchronously*
* @param local boolean only local timeline
* @return List<Status>
*/
public List<Status> getPublicTimeline(boolean local){
return getPublicTimeline(local, null, null, tootPerPage);
}
/**
* Retrieves public timeline for the account *synchronously*
@ -670,10 +665,8 @@ public class API {
if( status.getIn_reply_to_id() != null)
params.put("in_reply_to_id", status.getIn_reply_to_id());
if( status.getMedia_attachments() != null && status.getMedia_attachments().size() > 0 ) {
int i = 0;
for(Attachment attachment: status.getMedia_attachments()) {
params.add("media_ids[]", attachment.getId());
i++;
}
}
if( status.isSensitive())
@ -704,7 +697,7 @@ public class API {
}
});
}else{
delete(action, params, new JsonHttpResponseHandler() {
delete(action, null, new JsonHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
@ -1167,21 +1160,39 @@ public class API {
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
String prefKeyOauthTokenT = sharedpreferences.getString(Helper.PREF_KEY_OAUTH_TOKEN, null);
client.addHeader("Authorization", "Bearer "+prefKeyOauthTokenT);
client.get(getAbsoluteUrl(action), params, responseHandler);
try {
client.setUserAgent(USER_AGENT);
client.setSSLSocketFactory(new MastalabSSLSocketFactory(MastalabSSLSocketFactory.getKeystore()));
client.get(getAbsoluteUrl(action), params, responseHandler);
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException e) {
e.printStackTrace();
}
}
private void post(String action, RequestParams params, AsyncHttpResponseHandler responseHandler) {
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
String prefKeyOauthTokenT = sharedpreferences.getString(Helper.PREF_KEY_OAUTH_TOKEN, null);
client.addHeader("Authorization", "Bearer "+prefKeyOauthTokenT);
client.post(getAbsoluteUrl(action), params, responseHandler);
try {
client.setUserAgent(USER_AGENT);
client.setSSLSocketFactory(new MastalabSSLSocketFactory(MastalabSSLSocketFactory.getKeystore()));
client.post(getAbsoluteUrl(action), params, responseHandler);
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException e) {
e.printStackTrace();
}
}
private void delete(String action, RequestParams params, AsyncHttpResponseHandler responseHandler){
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
String prefKeyOauthTokenT = sharedpreferences.getString(Helper.PREF_KEY_OAUTH_TOKEN, null);
client.addHeader("Authorization", "Bearer "+prefKeyOauthTokenT);
client.delete(getAbsoluteUrl(action), params, responseHandler);
try {
client.setUserAgent(USER_AGENT);
client.setSSLSocketFactory(new MastalabSSLSocketFactory(MastalabSSLSocketFactory.getKeystore()));
client.delete(getAbsoluteUrl(action), params, responseHandler);
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException e) {
e.printStackTrace();
}
}
private String getAbsoluteUrl(String action) {

View File

@ -0,0 +1,74 @@
package fr.gouv.etalab.mastodon.client;
/**
* Created by Thomas on 20/05/2017.
* Custom MySSLSocketFactory
*/
import java.io.IOException;
import java.net.Socket;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
/**
* This file is introduced to fix HTTPS Post bug on API &lt; ICS see
* https://code.google.com/p/android/issues/detail?id=13117#c14 <p>&nbsp;</p> Warning! This omits SSL
* certificate validation on every device, use with caution
*/
class MastalabSSLSocketFactory extends com.loopj.android.http.MySSLSocketFactory {
private final SSLContext sslContext = SSLContext.getInstance("TLS");
/**
* Creates a new SSL Socket Factory with the given KeyStore.
*
* @param truststore A KeyStore to create the SSL Socket Factory in context of
* @throws NoSuchAlgorithmException NoSuchAlgorithmException
* @throws KeyManagementException KeyManagementException
* @throws KeyStoreException KeyStoreException
* @throws UnrecoverableKeyException UnrecoverableKeyException
*/
MastalabSSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
super(truststore);
X509TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
sslContext.init(null, new TrustManager[]{tm}, null);
}
@Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException {
return enableTLSOnSocket(sslContext.getSocketFactory().createSocket(socket, host, port, autoClose));
}
@Override
public Socket createSocket() throws IOException {
return enableTLSOnSocket(sslContext.getSocketFactory().createSocket());
}
private Socket enableTLSOnSocket(Socket socket) {
if(socket != null && (socket instanceof SSLSocket)) {
((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.1", "TLSv1.2"});
}
return socket;
}
}

View File

@ -14,16 +14,24 @@
* see <http://www.gnu.org/licenses>. */
package fr.gouv.etalab.mastodon.client;
import android.os.Build;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;
import com.loopj.android.http.RequestParams;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import fr.gouv.etalab.mastodon.helper.Helper;
import static fr.gouv.etalab.mastodon.helper.Helper.USER_AGENT;
/**
* Created by Thomas on 23/04/2017.
* Client to call urls
@ -37,13 +45,26 @@ public class OauthClient {
public void get(String action, HashMap<String, String> paramaters, AsyncHttpResponseHandler responseHandler) {
client.setTimeout(5000);
client.setUserAgent(USER_AGENT);
RequestParams params = hashToRequestParams(paramaters);
try {
client.setSSLSocketFactory(new MastalabSSLSocketFactory(MastalabSSLSocketFactory.getKeystore()));
client.post(getAbsoluteUrl(action), params, responseHandler);
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException e) {
e.printStackTrace();
}
client.get(getAbsoluteUrl(action), params, responseHandler);
}
public void post(String action, HashMap<String, String> paramaters, AsyncHttpResponseHandler responseHandler) {
RequestParams params = hashToRequestParams(paramaters);
client.post(getAbsoluteUrl(action), params, responseHandler);
try {
client.setUserAgent(USER_AGENT);
client.setSSLSocketFactory(new MastalabSSLSocketFactory(MastalabSSLSocketFactory.getKeystore()));
client.post(getAbsoluteUrl(action), params, responseHandler);
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException e) {
e.printStackTrace();
}
}
private String getAbsoluteUrl(String action) {

View File

@ -14,10 +14,12 @@ package fr.gouv.etalab.mastodon.fragments;
* You should have received a copy of the GNU General Public License along with Thomas Schneider; if not,
* see <http://www.gnu.org/licenses>. */
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.widget.SwipeRefreshLayout;
import android.view.LayoutInflater;
import android.view.View;
@ -58,6 +60,7 @@ public class DisplayAccountsFragment extends Fragment implements OnRetrieveAccou
private SwipeRefreshLayout swipeRefreshLayout;
private int accountPerPage;
private String targetedId;
private boolean hideHeader = false;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@ -69,6 +72,7 @@ public class DisplayAccountsFragment extends Fragment implements OnRetrieveAccou
if (bundle != null) {
type = (RetrieveAccountsAsyncTask.Type) bundle.get("type");
targetedId = bundle.getString("targetedId", null);
hideHeader = bundle.getBoolean("hideHeader", false);
}
max_id = null;
firstLoad = true;
@ -78,7 +82,7 @@ public class DisplayAccountsFragment extends Fragment implements OnRetrieveAccou
swipeRefreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.swipeContainer);
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
accountPerPage = sharedpreferences.getInt(Helper.SET_ACCOUNTS_PER_PAGE, 40);
ListView lv_accounts = (ListView) rootView.findViewById(R.id.lv_accounts);
final ListView lv_accounts = (ListView) rootView.findViewById(R.id.lv_accounts);
mainLoader = (RelativeLayout) rootView.findViewById(R.id.loader);
nextElementLoader = (RelativeLayout) rootView.findViewById(R.id.loading_next_accounts);
@ -109,6 +113,35 @@ public class DisplayAccountsFragment extends Fragment implements OnRetrieveAccou
}
});
//Hide account header when scrolling for ShowAccountActivity
if( hideHeader ) {
lv_accounts.setOnScrollListener(new AbsListView.OnScrollListener() {
int lastFirstVisibleItem = 0;
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (view.getId() == lv_accounts.getId() && totalItemCount > visibleItemCount) {
final int currentFirstVisibleItem = lv_accounts.getFirstVisiblePosition();
if (currentFirstVisibleItem > lastFirstVisibleItem) {
Intent intent = new Intent(Helper.HEADER_ACCOUNT);
intent.putExtra("hide", true);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
} else if (currentFirstVisibleItem < lastFirstVisibleItem) {
Intent intent = new Intent(Helper.HEADER_ACCOUNT);
intent.putExtra("hide", false);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
}
lastFirstVisibleItem = currentFirstVisibleItem;
}
}
});
}
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
@ -157,7 +190,6 @@ public class DisplayAccountsFragment extends Fragment implements OnRetrieveAccou
}
@Override
public void onRetrieveAccounts(List<Account> accounts) {

View File

@ -14,10 +14,12 @@ package fr.gouv.etalab.mastodon.fragments;
* You should have received a copy of the GNU General Public License along with Thomas Schneider; if not,
* see <http://www.gnu.org/licenses>. */
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.widget.SwipeRefreshLayout;
import android.view.LayoutInflater;
import android.view.View;
@ -25,7 +27,7 @@ import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
@ -46,7 +48,6 @@ import fr.gouv.etalab.mastodon.interfaces.OnRetrieveFeedsInterface;
public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsInterface {
private TextView noAction;
private boolean flag_loading;
private Context context;
private AsyncTask<Void, Void, Void> asyncTask;
@ -57,9 +58,9 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
private RelativeLayout mainLoader, nextElementLoader, textviewNoAction;
private boolean firstLoad;
private SwipeRefreshLayout swipeRefreshLayout;
private int tootPerPage;
private String targetedId;
private String tag;
private boolean hideHeader = false;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@ -72,6 +73,7 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
type = (RetrieveFeedsAsyncTask.Type) bundle.get("type");
targetedId = bundle.getString("targetedId", null);
tag = bundle.getString("tag", null);
hideHeader = bundle.getBoolean("hideHeader", false);
}
max_id = null;
flag_loading = true;
@ -80,10 +82,9 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
boolean isOnWifi = Helper.isOnWIFI(context);
swipeRefreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.swipeContainer);
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
tootPerPage = sharedpreferences.getInt(Helper.SET_TOOTS_PER_PAGE, 40);
int behaviorWithAttachments = sharedpreferences.getInt(Helper.SET_ATTACHMENT_ACTION, Helper.ATTACHMENT_ALWAYS);
ListView lv_status = (ListView) rootView.findViewById(R.id.lv_status);
final ListView lv_status = (ListView) rootView.findViewById(R.id.lv_status);
mainLoader = (RelativeLayout) rootView.findViewById(R.id.loader);
nextElementLoader = (RelativeLayout) rootView.findViewById(R.id.loading_next_status);
@ -117,6 +118,35 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
}
});
//Hide account header when scrolling for ShowAccountActivity
if( hideHeader ) {
lv_status.setOnScrollListener(new AbsListView.OnScrollListener() {
int lastFirstVisibleItem = 0;
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (view.getId() == lv_status.getId() && totalItemCount > visibleItemCount) {
final int currentFirstVisibleItem = lv_status.getFirstVisiblePosition();
if (currentFirstVisibleItem > lastFirstVisibleItem) {
Intent intent = new Intent(Helper.HEADER_ACCOUNT);
intent.putExtra("hide", true);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
} else if (currentFirstVisibleItem < lastFirstVisibleItem) {
Intent intent = new Intent(Helper.HEADER_ACCOUNT);
intent.putExtra("hide", false);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
}
lastFirstVisibleItem = currentFirstVisibleItem;
}
}
});
}
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
@ -193,9 +223,7 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
}
swipeRefreshLayout.setRefreshing(false);
firstLoad = false;
if( statuses != null && statuses.size() < tootPerPage )
flag_loading = true;
else
flag_loading = false;
flag_loading = false;
}
}

View File

@ -36,6 +36,8 @@ import android.support.v4.app.NotificationManagerCompat;
import android.view.WindowManager;
import android.widget.Toast;
import com.loopj.android.http.BuildConfig;
import java.io.File;
import java.net.InetAddress;
import java.text.ParseException;
@ -124,9 +126,10 @@ public class Helper {
//Receiver
public static final String SEARCH_VALIDATE_ACCOUNT = "search_validate_account";
public static final String HEADER_ACCOUNT = "header_account";
//User agent
public static final String USER_AGENT = "Mastalab/"+ BuildConfig.VERSION_NAME + " Android/"+ Build.VERSION.RELEASE;
/***
* Check if the user is connected to Internet

View File

@ -20,6 +20,7 @@
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:orientation="vertical"
>
<LinearLayout