This commit is contained in:
Sergey Solovyev
2012-11-24 21:12:35 +04:00
parent cd41a35093
commit e54c5c97e6
24 changed files with 323 additions and 144 deletions

View File

@@ -1,12 +1,9 @@
package org.solovyev.android.calculator;
import android.*;
import android.Manifest;
import android.app.Activity;
import android.app.KeyguardManager;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.util.Log;
@@ -67,9 +64,7 @@ public abstract class AbstractCalculatorHelper implements SharedPreferences.OnSh
preferences.registerOnSharedPreferenceChangeListener(this);
// let's disable locking of screen for monkeyrunner
// NOTE: this code is only for monkeyrunner
final String permission = Manifest.permission.DISABLE_KEYGUARD;
if (activity.checkCallingOrSelfPermission(permission) == PackageManager.PERMISSION_GRANTED) {
if (CalculatorApplication.isMonkeyRunner(activity)) {
final KeyguardManager km = (KeyguardManager) activity.getSystemService(Context.KEYGUARD_SERVICE);
km.newKeyguardLock(activity.getClass().getName()).disableKeyguard();
}

View File

@@ -81,6 +81,12 @@ public class CalculatorActivity extends SherlockFragmentActivity implements Shar
preferences.registerOnSharedPreferenceChangeListener(this);
Locator.getInstance().getPreferenceService().checkPreferredPreferences(false);
if ( CalculatorApplication.isMonkeyRunner(this) ) {
Locator.getInstance().getKeyboard().buttonPressed("123");
Locator.getInstance().getKeyboard().buttonPressed("+");
Locator.getInstance().getKeyboard().buttonPressed("321");
}
}
@NotNull
@@ -100,35 +106,38 @@ public class CalculatorActivity extends SherlockFragmentActivity implements Shar
CalculatorPreferences.appVersion.putPreference(preferences, appVersion);
boolean dialogShown = false;
if (EqualsTool.areEqual(savedVersion, CalculatorPreferences.appVersion.getDefaultValue())) {
// new start
final AlertDialog.Builder builder = new AlertDialog.Builder(context).setMessage(R.string.c_first_start_text);
builder.setPositiveButton(android.R.string.ok, null);
builder.setTitle(R.string.c_first_start_text_title);
builder.create().show();
dialogShown = true;
} else {
if (savedVersion < appVersion) {
final boolean showReleaseNotes = CalculatorPreferences.Gui.showReleaseNotes.getPreference(preferences);
if (showReleaseNotes) {
final String releaseNotes = CalculatorReleaseNotesFragment.getReleaseNotes(context, savedVersion + 1);
if (!StringUtils.isEmpty(releaseNotes)) {
final AlertDialog.Builder builder = new AlertDialog.Builder(context).setMessage(Html.fromHtml(releaseNotes));
builder.setPositiveButton(android.R.string.ok, null);
builder.setTitle(R.string.c_release_notes);
builder.create().show();
dialogShown = true;
if (!CalculatorApplication.isMonkeyRunner(context)) {
boolean dialogShown = false;
if (EqualsTool.areEqual(savedVersion, CalculatorPreferences.appVersion.getDefaultValue())) {
// new start
final AlertDialog.Builder builder = new AlertDialog.Builder(context).setMessage(R.string.c_first_start_text);
builder.setPositiveButton(android.R.string.ok, null);
builder.setTitle(R.string.c_first_start_text_title);
builder.create().show();
dialogShown = true;
} else {
if (savedVersion < appVersion) {
final boolean showReleaseNotes = CalculatorPreferences.Gui.showReleaseNotes.getPreference(preferences);
if (showReleaseNotes) {
final String releaseNotes = CalculatorReleaseNotesFragment.getReleaseNotes(context, savedVersion + 1);
if (!StringUtils.isEmpty(releaseNotes)) {
final AlertDialog.Builder builder = new AlertDialog.Builder(context).setMessage(Html.fromHtml(releaseNotes));
builder.setPositiveButton(android.R.string.ok, null);
builder.setTitle(R.string.c_release_notes);
builder.create().show();
dialogShown = true;
}
}
}
}
}
//Log.d(this.getClass().getName(), "Application was opened " + appOpenedCounter + " time!");
if (!dialogShown) {
if (appOpenedCounter != null && appOpenedCounter > 10) {
dialogShown = showSpecialWindow(preferences, CalculatorPreferences.Gui.feedbackWindowShown, R.layout.feedback, R.id.feedbackText, context);
//Log.d(this.getClass().getName(), "Application was opened " + appOpenedCounter + " time!");
if (!dialogShown) {
if (appOpenedCounter != null && appOpenedCounter > 10) {
dialogShown = showSpecialWindow(preferences, CalculatorPreferences.Gui.feedbackWindowShown, R.layout.feedback, R.id.feedbackText, context);
}
}
}
}

View File

@@ -1,6 +1,8 @@
package org.solovyev.android.calculator;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.preference.PreferenceManager;
import net.robotmedia.billing.BillingController;
import net.robotmedia.billing.helper.DefaultBillingObserver;
@@ -13,7 +15,6 @@ import org.solovyev.android.ads.AdsController;
import org.solovyev.android.calculator.external.AndroidExternalListenersContainer;
import org.solovyev.android.calculator.history.AndroidCalculatorHistory;
import org.solovyev.android.calculator.model.AndroidCalculatorEngine;
import org.solovyev.android.calculator.widget.CalculatorWidgetHelper;
/**
* User: serso
@@ -60,6 +61,7 @@ public class CalculatorApplication extends android.app.Application {
instance = this;
}
/*
**********************************************************************
*
@@ -160,4 +162,8 @@ public class CalculatorApplication extends android.app.Application {
return instance;
}
public static boolean isMonkeyRunner(@NotNull Context context) {
// NOTE: this code is only for monkeyrunner
return context.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) == PackageManager.PERMISSION_GRANTED;
}
}

View File

@@ -1,21 +0,0 @@
package org.solovyev.android.calculator;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import org.solovyev.android.calculator.external.AndroidExternalListenersContainer;
import org.solovyev.android.calculator.onscreen.CalculatorOnscreenService;
public class CalculatorOnscreenStartActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Intent intent = new Intent(AndroidExternalListenersContainer.INIT_ACTION);
intent.setClass(this, CalculatorOnscreenService.class);
startService(intent);
this.finish();
}
}

View File

@@ -1,9 +1,7 @@
package org.solovyev.android.calculator;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import org.solovyev.android.calculator.external.AndroidExternalListenersContainer;
import org.solovyev.android.calculator.onscreen.CalculatorOnscreenService;
public class CalculatorOnscreenStartActivity extends Activity {
@@ -12,9 +10,7 @@ public class CalculatorOnscreenStartActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Intent intent = new Intent(AndroidExternalListenersContainer.INIT_ACTION);
intent.setClass(this, CalculatorOnscreenService.class);
startService(intent);
CalculatorOnscreenService.showOnscreenView(this);
this.finish();
}

View File

@@ -28,6 +28,10 @@ public final class CalculatorPreferences {
public static final Preference<Integer> appVersion = new IntegerPreference("application.version", -1);
public static final Preference<Integer> appOpenedCounter = new IntegerPreference("app_opened_counter", 0);
public static class OnscreenCalculator {
public static final Preference<Boolean> startOnBoot = new BooleanPreference("onscreen_start_on_boot", false);
}
public static class Calculations {
public static final Preference<Boolean> calculateOnFly = new BooleanPreference("calculations_calculate_on_fly", true);

View File

@@ -42,10 +42,11 @@ public class CalculatorPreferencesActivity extends SherlockPreferenceActivity im
//noinspection deprecation
addPreferencesFromResource(R.xml.preferences);
//noinspection deprecation
addPreferencesFromResource(R.xml.calculations_preferences);
addPreferencesFromResource(R.xml.appearance_preferences);
addPreferencesFromResource(R.xml.plot_preferences);
addPreferencesFromResource(R.xml.other_preferences);
addPreferencesFromResource(R.xml.preferences_calculations);
addPreferencesFromResource(R.xml.preferences_appearance);
addPreferencesFromResource(R.xml.preferences_plot);
addPreferencesFromResource(R.xml.preferences_other);
addPreferencesFromResource(R.xml.preferences_onscreen);
final Preference adFreePreference = findPreference(CalculatorApplication.AD_FREE_P_KEY);
adFreePreference.setEnabled(false);

View File

@@ -41,6 +41,7 @@ public class AndroidExternalListenersContainer implements CalculatorExternalList
public static final String EVENT_ID_EXTRA = "eventId";
public static final String INIT_ACTION = "org.solovyev.android.calculator.INIT";
public static final String INIT_ACTION_CREATE_VIEW_EXTRA = "createView";
public static final String EDITOR_STATE_CHANGED_ACTION = "org.solovyev.android.calculator.EDITOR_STATE_CHANGED";
public static final String EDITOR_STATE_EXTRA = "editorState";

View File

@@ -3,7 +3,10 @@ package org.solovyev.android.calculator.onscreen;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import org.jetbrains.annotations.NotNull;
import org.solovyev.android.calculator.CalculatorPreferences;
/**
* User: serso
@@ -18,8 +21,15 @@ public final class CalculatorOnscreenBroadcastReceiver extends BroadcastReceiver
@Override
public void onReceive(@NotNull Context context,
@NotNull Intent intent) {
final Intent newIntent = new Intent(intent);
newIntent.setClass(context, CalculatorOnscreenService.class);
context.startService(newIntent);
if ( intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED) ) {
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
if ( CalculatorPreferences.OnscreenCalculator.startOnBoot.getPreferenceNoError(preferences) ) {
CalculatorOnscreenService.showNotification(context);
}
} else {
final Intent newIntent = new Intent(intent);
newIntent.setClass(context, CalculatorOnscreenService.class);
context.startService(newIntent);
}
}
}

View File

@@ -16,10 +16,7 @@ import org.solovyev.android.calculator.CalculatorDisplayViewState;
import org.solovyev.android.calculator.CalculatorEditorViewState;
import org.solovyev.android.calculator.Locator;
import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.external.AndroidExternalListenersContainer;
import org.solovyev.android.calculator.external.DefaultExternalCalculatorIntentHandler;
import org.solovyev.android.calculator.external.ExternalCalculatorIntentHandler;
import org.solovyev.android.calculator.external.ExternalCalculatorStateUpdater;
import org.solovyev.android.calculator.external.*;
/**
* User: serso
@@ -32,6 +29,7 @@ public class CalculatorOnscreenService extends Service implements ExternalCalcul
@NotNull
private final ExternalCalculatorIntentHandler intentHandler = new DefaultExternalCalculatorIntentHandler(this);
public static final Class<CalculatorOnscreenBroadcastReceiver> INTENT_LISTENER_CLASS = CalculatorOnscreenBroadcastReceiver.class;
@Nullable
private static String cursorColor;
@@ -41,6 +39,8 @@ public class CalculatorOnscreenService extends Service implements ExternalCalcul
private boolean compatibilityStart = true;
private boolean viewCreated = false;
@Override
public IBinder onBind(Intent intent) {
return null;
@@ -49,31 +49,37 @@ public class CalculatorOnscreenService extends Service implements ExternalCalcul
@Override
public void onCreate() {
super.onCreate();
final WindowManager wm = ((WindowManager) this.getSystemService(Context.WINDOW_SERVICE));
final DisplayMetrics dm = getResources().getDisplayMetrics();
int twoThirdWidth = 2 * wm.getDefaultDisplay().getWidth() / 3;
int twoThirdHeight = 2 * wm.getDefaultDisplay().getHeight() / 3;
twoThirdWidth = Math.min(twoThirdWidth, twoThirdHeight);
twoThirdHeight = Math.max(twoThirdWidth, getHeight(twoThirdWidth));
final int baseWidth = AndroidUtils.toPixels(dm, 300);
final int width0 = Math.min(twoThirdWidth, baseWidth);
final int height0 = Math.min(twoThirdHeight, getHeight(baseWidth));
final int width = Math.min(width0, height0);
final int height = Math.max(width0, height0);
view = CalculatorOnscreenView.newInstance(this, CalculatorOnscreenViewDef.newInstance(width, height, -1, -1), getCursorColor(this), this);
view.show();
startCalculatorListening();
}
private int getHeight(int width) {
private void createView() {
if (!viewCreated) {
final WindowManager wm = ((WindowManager) this.getSystemService(Context.WINDOW_SERVICE));
final DisplayMetrics dm = getResources().getDisplayMetrics();
int twoThirdWidth = 2 * wm.getDefaultDisplay().getWidth() / 3;
int twoThirdHeight = 2 * wm.getDefaultDisplay().getHeight() / 3;
twoThirdWidth = Math.min(twoThirdWidth, twoThirdHeight);
twoThirdHeight = Math.max(twoThirdWidth, getHeight(twoThirdWidth));
final int baseWidth = AndroidUtils.toPixels(dm, 300);
final int width0 = Math.min(twoThirdWidth, baseWidth);
final int height0 = Math.min(twoThirdHeight, getHeight(baseWidth));
final int width = Math.min(width0, height0);
final int height = Math.max(width0, height0);
view = CalculatorOnscreenView.newInstance(this, CalculatorOnscreenViewDef.newInstance(width, height, -1, -1), getCursorColor(this), this);
view.show();
startCalculatorListening();
viewCreated = true;
}
}
private int getHeight(int width) {
return 4 * width / 3;
}
@@ -82,8 +88,8 @@ public class CalculatorOnscreenService extends Service implements ExternalCalcul
}
@NotNull
private Class<?> getIntentListenerClass() {
return CalculatorOnscreenBroadcastReceiver.class;
private static Class<?> getIntentListenerClass() {
return INTENT_LISTENER_CLASS;
}
private void stopCalculatorListening() {
@@ -137,12 +143,30 @@ public class CalculatorOnscreenService extends Service implements ExternalCalcul
private void handleStart(@Nullable Intent intent) {
if ( intent != null ) {
intentHandler.onIntent(this, intent);
}
hideNotification();
if (isInitIntent(intent)) {
boolean createView = intent.getBooleanExtra(AndroidExternalListenersContainer.INIT_ACTION_CREATE_VIEW_EXTRA, false);
if (createView) {
hideNotification();
createView();
} else {
showNotification();
}
}
if (viewCreated) {
intentHandler.onIntent(this, intent);
}
}
}
private void hideNotification() {
private boolean isInitIntent(@NotNull Intent intent) {
return intent.getAction().equals(AndroidExternalListenersContainer.INIT_ACTION);
}
private void hideNotification() {
final NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
nm.cancel(NOTIFICATION_ID);
}
@@ -164,12 +188,30 @@ public class CalculatorOnscreenService extends Service implements ExternalCalcul
builder.setContentTitle(getText(R.string.c_app_name));
builder.setContentText(getString(R.string.open_onscreen_calculator));
final Intent intent = new Intent(AndroidExternalListenersContainer.INIT_ACTION);
intent.setClass(this, getIntentListenerClass());
final Intent intent = createShowOnscreenViewIntent(this);
builder.setContentIntent(PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
final NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
nm.notify(NOTIFICATION_ID, builder.getNotification());
}
public static void showNotification(@NotNull Context context) {
final Intent intent = new Intent(AndroidExternalListenersContainer.INIT_ACTION);
intent.setClass(context, getIntentListenerClass());
context.sendBroadcast(intent);
}
public static void showOnscreenView(@NotNull Context context) {
final Intent intent = createShowOnscreenViewIntent(context);
context.sendBroadcast(intent);
}
@NotNull
private static Intent createShowOnscreenViewIntent(@NotNull Context context) {
final Intent intent = new Intent(AndroidExternalListenersContainer.INIT_ACTION);
intent.setClass(context, getIntentListenerClass());
intent.putExtra(AndroidExternalListenersContainer.INIT_ACTION_CREATE_VIEW_EXTRA, true);
return intent;
}
}

View File

@@ -8,11 +8,7 @@ import android.view.WindowManager;
import android.widget.ImageView;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.AndroidCalculatorDisplayView;
import org.solovyev.android.calculator.AndroidCalculatorEditorView;
import org.solovyev.android.calculator.CalculatorDisplayViewState;
import org.solovyev.android.calculator.CalculatorEditorViewState;
import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.*;
import org.solovyev.android.calculator.widget.WidgetButton;
/**
@@ -333,15 +329,46 @@ public class CalculatorOnscreenView {
private static class WindowDragTouchListener implements View.OnTouchListener {
/*
**********************************************************************
*
* CONSTANTS
*
**********************************************************************
*/
private static final float DIST_EPS = 10f;
private static final float DIST_MAX = 100f;
private static final long TIME_EPS = 100L;
/*
**********************************************************************
*
* FIELDS
*
**********************************************************************
*/
@NotNull
private final WindowManager wm;
private float x0;
private float y0;
private long time = 0;
@NotNull
private final View view;
/*
**********************************************************************
*
* CONSTRUCTORS
*
**********************************************************************
*/
public WindowDragTouchListener(@NotNull WindowManager wm,
@NotNull View view) {
this.wm = wm;
@@ -364,25 +391,59 @@ public class CalculatorOnscreenView {
return true;
case MotionEvent.ACTION_MOVE:
final float Δx = x1 - x0;
final float Δy = y1 - y0;
final long currentTime = System.currentTimeMillis();
final WindowManager.LayoutParams params = (WindowManager.LayoutParams) view.getLayoutParams();
//Log.d(TAG, "0:" + toString(x0, y0) + ", 1: " + toString(x1, y1) + ", Δ: " + toString(Δx, Δy) + ", params: " + toString(params.x, params.y));
params.x = (int) (params.x + Δx);
params.y = (int) (params.y + Δy);
wm.updateViewLayout(view, params);
x0 = x1;
y0 = y1;
if ( currentTime - time >= TIME_EPS ) {
time = currentTime;
for (int i = 0; i < event.getHistorySize(); i++) {
final float xi = event.getHistoricalX(i);
final float yi = event.getHistoricalY(i);
processMove(xi, yi);
}
processMove(x1, y1);
}
return true;
}
return false;
}
private void processMove(float x1, float y1) {
final float Δx = x1 - x0;
final float Δy = y1 - y0;
final WindowManager.LayoutParams params = (WindowManager.LayoutParams) view.getLayoutParams();
//Log.d(TAG, "0:" + toString(x0, y0) + ", 1: " + toString(x1, y1) + ", Δ: " + toString(Δx, Δy) + ", params: " + toString(params.x, params.y));
boolean xInBounds = isDistanceInBounds(Δx);
boolean yInBounds = isDistanceInBounds(Δy);
if (xInBounds || yInBounds) {
if (xInBounds) {
params.x = (int) (params.x + Δx);
}
if (yInBounds) {
params.y = (int) (params.y + Δy);
}
wm.updateViewLayout(view, params);
if (xInBounds) {
x0 = x1;
}
if (yInBounds) {
y0 = y1;
}
}
}
private boolean isDistanceInBounds(float δx) {
δx = Math.abs(δx);
return δx >= DIST_EPS && δx < DIST_MAX;
}
@NotNull
private static String toString(float x, float y) {
return "(" + formatFloat(x) + ", " + formatFloat(y) + ")";

View File

@@ -16,6 +16,6 @@ public class CalculatorPlotPreferenceActivity extends SherlockPreferenceActivity
super.onCreate(savedInstanceState);
//noinspection deprecation
addPreferencesFromResource(R.xml.plot_preferences);
addPreferencesFromResource(R.xml.preferences_plot);
}
}