Add pattern protection

This commit is contained in:
seven332 committed 2015-04-29 23:00:24 +08:00
1 parent 017ee1c538
commit 65feff57c0
15 files changed
+1594 -6

No files matched your search

+23
View File
@@ -135,6 +135,22 @@
android:theme="@style/AppTheme.NoActionBar.Transparent" >
</activity>
<activity
android:name=".ui.PatternProtectionActivity"
android:configChanges="orientation|screenSize|uiMode"
android:label="@string/app_name"
android:screenOrientation="portrait"
android:theme="@style/AppTheme" >
</activity>
<activity
android:name=".ui.EnterPatternActivity"
android:configChanges="orientation|screenSize|uiMode"
android:label="@string/app_name"
android:screenOrientation="portrait"
android:theme="@style/AppTheme" >
</activity>
<service
android:name=".service.DownloadService"
android:label="DownloadService" />
@@ -144,6 +160,13 @@
android:authorities="com.hippo.ehviewer.SimpleSuggestionProvider"
android:exported="false" />
<receiver android:name=".receiver.RestPatternReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SECRET_CODE"/>
<data android:scheme="android_secret_code" android:host="110722"/>
</intent-filter>
</receiver>
</application>
</manifest>
@@ -27,14 +27,16 @@ import android.widget.ImageView;
import android.widget.TextView;
import com.hippo.ehviewer.app.MaterialAlertDialog;
import com.hippo.ehviewer.miscellaneous.ActivityHelper;
import com.hippo.ehviewer.network.Network;
import com.hippo.ehviewer.ui.AbsActivity;
import com.hippo.ehviewer.ui.EnterPatternActivity;
import com.hippo.ehviewer.ui.GalleryListActivity;
import com.hippo.ehviewer.miscellaneous.ActivityHelper;
import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.Crash;
import com.hippo.ehviewer.util.Secret;
import com.hippo.ehviewer.util.ViewUtils;
import com.hippo.ehviewer.widget.LockPatternUtils;
import com.larvalabs.svgandroid.SVGBuilder;
public class StartActivity extends AbsActivity {
@@ -42,6 +44,8 @@ public class StartActivity extends AbsActivity {
@SuppressWarnings("unused")
private static final String TAG = StartActivity.class.getSimpleName();
private static final int REQUEST_CODE_PATTERN = 0;
private static final int CHECK_WARING = 0;
private static final int CHECK_ANALYTICS = 1;
private static final int CHECK_NETWORK = 2;
@@ -51,6 +55,7 @@ public class StartActivity extends AbsActivity {
private static final String KEY_SET_ANALYTICS = "set_analyics";
private String lastCrash;
private boolean isEnterPattern = false;
private boolean isAnimationOver = false;
private boolean isCheckOver = false;
@@ -196,12 +201,37 @@ public class StartActivity extends AbsActivity {
AppHandler.getInstance().postDelayed(new Runnable() {
@Override
public void run() {
if (isCheckOver)
redirectTo();
isAnimationOver = true;
if (!StartActivity.this.isFinishing()) {
if (isCheckOver && isEnterPattern)
redirectTo();
isAnimationOver = true;
}
}
}, 3000);
check(CHECK_WARING);
// Enter Pattern
String pattern = Config.getPatternProtection();
if (LockPatternUtils.isPatternVaild(pattern)) {
// Start activity to enter pattern
Intent intent = new Intent(this, EnterPatternActivity.class);
startActivityForResult(intent, REQUEST_CODE_PATTERN);
} else {
isEnterPattern = true;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE_PATTERN) {
if (resultCode == RESULT_OK) {
if (isAnimationOver && isCheckOver)
redirectTo();
isEnterPattern = true;
} else {
finish();
}
}
}
/**
@@ -239,7 +269,7 @@ public class StartActivity extends AbsActivity {
}
private void checkOver() {
if (isAnimationOver)
if (isAnimationOver && isEnterPattern)
redirectTo();
isCheckOver = true;
}
@@ -0,0 +1,18 @@
package com.hippo.ehviewer.receiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.widget.MaterialToast;
public class RestPatternReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Config.setPatternProtection("");
MaterialToast.showToast(R.string.reset_pattern_protection);
}
}
@@ -0,0 +1,95 @@
package com.hippo.ehviewer.ui;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.view.MenuItem;
import android.widget.TextView;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.drawable.MaterialIndicatorDrawable;
import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.Ui;
import com.hippo.ehviewer.widget.LockPatternUtils;
import com.hippo.ehviewer.widget.LockPatternView;
import java.util.List;
public class EnterPatternActivity extends AbsActivity {
private static final String KEY_LAST_BAD_PATTERN_RETRY = "last_bad_pattern_retry";
private static final int MAX_RETRY_TIMES = 5;
private int mRetryTimes = 0;
@SuppressWarnings("ConstantConditions")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_enter_pattern);
// Set random color
int themeColor = Config.getCustomThemeColor() ? Config.getThemeColor() : Ui.THEME_COLOR;
getActionBar().setBackgroundDrawable(new ColorDrawable(themeColor));
Ui.colorStatusBarL(this, themeColor);
// Menu
MaterialIndicatorDrawable materialIndicator = new MaterialIndicatorDrawable(this, Color.WHITE, MaterialIndicatorDrawable.Stroke.THIN);
materialIndicator.setIconState(MaterialIndicatorDrawable.IconState.ARROW);
Ui.setMaterialIndicator(getActionBar(), materialIndicator);
// Can't try if bad retry happened in 10 mins
long lastBadRetry = Config.getLong(KEY_LAST_BAD_PATTERN_RETRY, Long.MAX_VALUE);
if (System.currentTimeMillis() - lastBadRetry < 1000 * 60 * 10) {
mRetryTimes = 10;
}
final TextView textView = (TextView) findViewById(R.id.text);
LockPatternView patternView = (LockPatternView) findViewById(R.id.pattern_view);
patternView.setOnPatternListener(new LockPatternView.OnPatternListener() {
@Override
public void onPatternStart() {
}
@Override
public void onPatternCleared() {
}
@Override
public void onPatternCellAdded(List<LockPatternView.Cell> pattern) {
}
@Override
public void onPatternDetected(List<LockPatternView.Cell> pattern) {
if (mRetryTimes > MAX_RETRY_TIMES) {
textView.setText(R.string.no_more_retries);
Config.setLong(KEY_LAST_BAD_PATTERN_RETRY, System.currentTimeMillis());
} else {
String enterPatter = LockPatternUtils.patternToString(pattern);
if (enterPatter.equals(Config.getPatternProtection())) {
setResult(RESULT_OK);
finish();
} else {
textView.setText(R.string.error_pattern);
}
}
mRetryTimes++;
}
});
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
}
@@ -0,0 +1,82 @@
package com.hippo.ehviewer.ui;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.drawable.MaterialIndicatorDrawable;
import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.Ui;
import com.hippo.ehviewer.widget.LockPatternUtils;
import com.hippo.ehviewer.widget.LockPatternView;
public class PatternProtectionActivity extends AbsActivity implements View.OnClickListener{
private TextView mTextView;
private LockPatternView mPatternView;
private View mCancel;
private View mOK;
@SuppressWarnings("ConstantConditions")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pattern_protection);
// Set random color
int themeColor = Config.getCustomThemeColor() ? Config.getThemeColor() : Ui.THEME_COLOR;
getActionBar().setBackgroundDrawable(new ColorDrawable(themeColor));
Ui.colorStatusBarL(this, themeColor);
// Menu
MaterialIndicatorDrawable materialIndicator = new MaterialIndicatorDrawable(this, Color.WHITE, MaterialIndicatorDrawable.Stroke.THIN);
materialIndicator.setIconState(MaterialIndicatorDrawable.IconState.ARROW);
Ui.setMaterialIndicator(getActionBar(), materialIndicator);
mTextView = (TextView) findViewById(R.id.text);
mPatternView = (LockPatternView) findViewById(R.id.pattern_view);
mCancel = findViewById(R.id.cancel);
mOK = findViewById(R.id.ok);
mOK.setOnClickListener(this);
mCancel.setOnClickListener(this);
String pattern = Config.getPatternProtection();
boolean setPattern = LockPatternUtils.isPatternVaild(pattern);
Resources resources = getResources();
int patternProtectionStateId = setPattern ?
R.string.pattern_protection_set : R.string.pattern_protection_not_set;
mTextView.setText(resources.getString(patternProtectionStateId) + "\n\n" +
getString(R.string.pattern_protection_warning));
if (setPattern) {
mPatternView.setPattern(LockPatternView.DisplayMode.Correct, LockPatternUtils.stringToPattern(pattern));
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onClick(View v) {
if (v == mOK) {
Config.setPatternProtection(mPatternView.getPatternString());
finish();
} else if (v == mCancel) {
finish();
}
}
}
@@ -688,9 +688,11 @@ public class SettingsActivity extends AbsPreferenceActivity {
private static final String KEY_FIX_DIRNAME = "fix_dirname";
private static final String KEY_LOGIN_VIA_COOKIE = "login_via_cookie";
private static final String KEY_PATTERN_PROTECTION = "pattern_protection";
private Preference mFixDirname;
private Preference mLoginViaCookie;
private Preference mPatternProtection;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -701,6 +703,8 @@ public class SettingsActivity extends AbsPreferenceActivity {
mFixDirname.setOnPreferenceClickListener(this);
mLoginViaCookie = findPreference(KEY_LOGIN_VIA_COOKIE);
mLoginViaCookie.setOnPreferenceClickListener(this);
mPatternProtection = findPreference(KEY_PATTERN_PROTECTION);
mPatternProtection.setOnPreferenceClickListener(this);
}
@Override
@@ -820,6 +824,9 @@ public class SettingsActivity extends AbsPreferenceActivity {
return true;
}
}).show();
} else if (KEY_PATTERN_PROTECTION.equals(key)) {
Intent intent = new Intent(getActivity(), PatternProtectionActivity.class);
getActivity().startActivity(intent);
}
return true;
}
@@ -96,6 +96,14 @@ public final class Config {
mConfigPre.edit().putInt(key, value).apply();
}
public static long getLong(String key, long defValue) {
return mConfigPre.getLong(key, defValue);
}
public static void setLong(String key, long value) {
mConfigPre.edit().putLong(key, value).apply();
}
public static String getString(String key, String defValue) {
return mConfigPre.getString(key, defValue);
}
@@ -563,6 +571,9 @@ public final class Config {
private static final String KEY_EH_MIN_INTERVAL = "eh_min_interval";
private static final int DEFAULT_EH_MIN_INTERVAL = 0;
private static final String KEY_PATTERN_PROTECTION = "pattern_protection";
private static final String DEFAULT_PATTERN_PROTECTION = "";
public static int getHttpRetry() {
return getIntFromStr(KEY_HTTP_RETRY, DEFAULT_HTTP_RETRY);
}
@@ -579,6 +590,14 @@ public final class Config {
return getIntFromStr(KEY_EH_MIN_INTERVAL, DEFAULT_EH_MIN_INTERVAL);
}
public static String getPatternProtection() {
return getString(KEY_PATTERN_PROTECTION, DEFAULT_PATTERN_PROTECTION);
}
public static void setPatternProtection(String value) {
setString(KEY_PATTERN_PROTECTION, value);
}
/****** About ******/
@@ -0,0 +1,75 @@
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.ehviewer.widget;
import java.util.ArrayList;
import java.util.List;
/**
* Utilities for the lock pattern and its settings.
*/
public class LockPatternUtils {
/**
* Deserialize a pattern.
* @param string The pattern serialized with {@link #patternToString}
* @return The pattern.
*/
public static List<LockPatternView.Cell> stringToPattern(String string) {
List<LockPatternView.Cell> result = new ArrayList<>();
final byte[] bytes = string.getBytes();
for (int i = 0; i < bytes.length; i++) {
byte b = bytes[i];
result.add(LockPatternView.Cell.of(b / 3, b % 3));
}
return result;
}
/**
* Serialize a pattern.
* @param pattern The pattern.
* @return The pattern in string form.
*/
public static String patternToString(List<LockPatternView.Cell> pattern) {
if (pattern == null) {
return "";
}
final int patternSize = pattern.size();
byte[] res = new byte[patternSize];
for (int i = 0; i < patternSize; i++) {
LockPatternView.Cell cell = pattern.get(i);
res[i] = (byte) (cell.getRow() * 3 + cell.getColumn());
}
return new String(res);
}
public static boolean isPatternVaild(String pattern) {
byte[] bytes = pattern.getBytes();
if (bytes.length <= 9 && bytes.length >= 2) {
for (byte b : bytes) {
if (b >= 9 || b < 0) {
return false;
}
}
return true;
} else {
return false;
}
}
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.hippo.ehviewer.widget.LockPatternView
android:id="@+id/pattern_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginLeft="32dp"
android:layout_marginRight="32dp"/>
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/pattern_view"
android:layout_centerHorizontal="true"
android:textColor="@android:color/holo_red_light"/>
</RelativeLayout>
@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/text_little_small"
android:padding="32dp"/>
<LinearLayout
android:id="@+id/button_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal"
android:paddingBottom="16dp">
<TextView
android:id="@+id/cancel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:minHeight="36dp"
android:gravity="center"
android:text="@android:string/cancel"
android:textColor="@color/theme"
android:textSize="@dimen/text_medium"/>
<TextView
android:id="@+id/ok"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:minHeight="36dp"
android:gravity="center"
android:text="@android:string/ok"
android:textColor="@color/theme"
android:textSize="@dimen/text_medium"/>
</LinearLayout>
<com.hippo.ehviewer.widget.LockPatternView
android:id="@+id/pattern_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/button_bar"
android:layout_marginLeft="32dp"
android:layout_marginRight="32dp"/>
</RelativeLayout>
+5 -1
View File
@@ -90,4 +90,8 @@
<color name="theme">@color/material_deep_teal_500</color>
<color name="theme_dark">@color/material_deep_teal_200</color>
</resources>
<color name="lock_pattern_view_regular_color">#8a000000</color>
<color name="lock_pattern_view_success_color">#8a000000</color>
<color name="lock_pattern_view_error_color">#fff4511e</color>
</resources>
+4
View File
@@ -37,4 +37,8 @@
<dimen name="text_small">14sp</dimen>
<dimen name="text_super_small">12sp</dimen>
<dimen name="lock_pattern_dot_line_width">3dp</dimen>
<dimen name="lock_pattern_dot_size">12dp</dimen>
<dimen name="lock_pattern_dot_size_activated">28dp</dimen>
</resources>
+11
View File
@@ -105,6 +105,16 @@
<string name="click_retry">Click to retry</string>
<string name="click_first_page">Click to go to first page</string>
<!-- PatternProtectionActivity -->
<string name="pattern_protection_not_set">Pattern protection has not been set.</string>
<string name="pattern_protection_set">Pattern protection has been set.</string>
<string name="pattern_protection_warning">NO guarantee for anything.\nOpen a dial application and enter *#*#110722#*#* if you forget password.</string>
<string name="reset_pattern_protection">Pattern protection has been reset</string>
<!-- EnterPatternActivity -->
<string name="error_pattern">Error pattern</string>
<string name="no_more_retries">No more retries</string>
<!-- Download -->
<string name="legacy_pages">%d pages leaved</string>
<string name="download_over">Download over</string>
@@ -295,6 +305,7 @@
<string name="no_need_fixing">No need to fix</string>
<string name="fixing_over">%d item(s) fixed</string>
<string name="login_via_cookie_title">Login via cookie</string>
<string name="pattern_protection_title">Pattern protection</string>
<string name="about_settings_title">About</string>
<string name="author_title">Author</string>
@@ -81,5 +81,9 @@
android:key="login_via_cookie"
android:title="@string/login_via_cookie_title"/>
<Preference
android:key="pattern_protection"
android:title="@string/pattern_protection_title"/>
</PreferenceCategory>
</PreferenceScreen>