fix for widget

This commit is contained in:
Sergey Solovyev 2013-06-28 15:59:57 +04:00
parent 6ab63bfbbc
commit 5a94e633e7
7 changed files with 100 additions and 268 deletions

View File

@ -0,0 +1,46 @@
package org.solovyev.android.calculator;
import android.content.Context;
import android.content.Intent;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public final class CalculatorBroadcaster implements CalculatorEventListener {
public static final String ACTION_INIT = "org.solovyev.android.calculator.INIT";
public static final String ACTION_EDITOR_STATE_CHANGED = "org.solovyev.android.calculator.EDITOR_STATE_CHANGED";
public static final String ACTION_DISPLAY_STATE_CHANGED = "org.solovyev.android.calculator.DISPLAY_STATE_CHANGED";
@Nonnull
private final Context context;
public CalculatorBroadcaster(@Nonnull Context context) {
this.context = context;
}
@Override
public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, @Nonnull CalculatorEventType calculatorEventType, @Nullable Object data) {
switch (calculatorEventType) {
case editor_state_changed:
case editor_state_changed_light:
sendEditorStateChangedIntent();
break;
case display_state_changed:
sendDisplayStateChanged();
break;
}
}
private void sendDisplayStateChanged() {
sendBroadcastIntent(ACTION_DISPLAY_STATE_CHANGED);
}
private void sendEditorStateChangedIntent() {
sendBroadcastIntent(ACTION_EDITOR_STATE_CHANGED);
}
private void sendBroadcastIntent(@Nonnull String action) {
context.sendBroadcast(new Intent(action));
}
}

View File

@ -1,131 +0,0 @@
/*
* Copyright 2013 serso aka se.solovyev
*
* 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.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Contact details
*
* Email: se.solovyev@gmail.com
* Site: http://se.solovyev.org
*/
package org.solovyev.android.calculator;
import android.os.Parcel;
import android.os.Parcelable;
import jscl.math.Generic;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.android.calculator.jscl.JsclOperation;
/**
* User: serso
* Date: 11/18/12
* Time: 1:40 PM
*/
public final class ParcelableCalculatorDisplayViewState implements CalculatorDisplayViewState, Parcelable {
public static final Creator<ParcelableCalculatorDisplayViewState> CREATOR = new Creator<ParcelableCalculatorDisplayViewState>() {
@Override
public ParcelableCalculatorDisplayViewState createFromParcel(@Nonnull Parcel in) {
return ParcelableCalculatorDisplayViewState.fromParcel(in);
}
@Override
public ParcelableCalculatorDisplayViewState[] newArray(int size) {
return new ParcelableCalculatorDisplayViewState[size];
}
};
@Nonnull
private static ParcelableCalculatorDisplayViewState fromParcel(@Nonnull Parcel in) {
final int selection = in.readInt();
final boolean valid = in.readInt() == 1;
final String stringResult = in.readString();
final String errorMessage = in.readString();
final JsclOperation operation = (JsclOperation) in.readSerializable();
CalculatorDisplayViewState calculatorDisplayViewState;
if (valid) {
calculatorDisplayViewState = CalculatorDisplayViewStateImpl.newValidState(operation, null, stringResult, selection);
} else {
calculatorDisplayViewState = CalculatorDisplayViewStateImpl.newErrorState(operation, errorMessage);
}
return new ParcelableCalculatorDisplayViewState(calculatorDisplayViewState);
}
@Nonnull
private CalculatorDisplayViewState viewState;
public ParcelableCalculatorDisplayViewState(@Nonnull CalculatorDisplayViewState viewState) {
this.viewState = viewState;
}
@Override
@Nonnull
public String getText() {
return viewState.getText();
}
@Override
public int getSelection() {
return viewState.getSelection();
}
@Override
@Nullable
public Generic getResult() {
return viewState.getResult();
}
@Override
public boolean isValid() {
return viewState.isValid();
}
@Override
@Nullable
public String getErrorMessage() {
return viewState.getErrorMessage();
}
@Override
@Nonnull
public JsclOperation getOperation() {
return viewState.getOperation();
}
@Override
@Nullable
public String getStringResult() {
return viewState.getStringResult();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@Nonnull Parcel out, int flags) {
out.writeInt(viewState.getSelection());
out.writeInt(viewState.isValid() ? 1 : 0);
out.writeString(viewState.getStringResult());
out.writeString(viewState.getErrorMessage());
out.writeSerializable(viewState.getOperation());
}
}

View File

@ -1,90 +0,0 @@
/*
* Copyright 2013 serso aka se.solovyev
*
* 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.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Contact details
*
* Email: se.solovyev@gmail.com
* Site: http://se.solovyev.org
*/
package org.solovyev.android.calculator;
import android.os.Parcel;
import android.os.Parcelable;
import javax.annotation.Nonnull;
/**
* User: serso
* Date: 11/18/12
* Time: 1:40 PM
*/
public final class ParcelableCalculatorEditorViewState implements CalculatorEditorViewState, Parcelable {
public static final Creator<ParcelableCalculatorEditorViewState> CREATOR = new Creator<ParcelableCalculatorEditorViewState>() {
@Override
public ParcelableCalculatorEditorViewState createFromParcel(@Nonnull Parcel in) {
return ParcelableCalculatorEditorViewState.fromParcel(in);
}
@Override
public ParcelableCalculatorEditorViewState[] newArray(int size) {
return new ParcelableCalculatorEditorViewState[size];
}
};
@Nonnull
private CalculatorEditorViewState viewState;
public ParcelableCalculatorEditorViewState(@Nonnull CalculatorEditorViewState viewState) {
this.viewState = viewState;
}
@Nonnull
private static ParcelableCalculatorEditorViewState fromParcel(@Nonnull Parcel in) {
final String text = in.readString();
final int selection = in.readInt();
return new ParcelableCalculatorEditorViewState(CalculatorEditorViewStateImpl.newInstance(text, selection));
}
@Override
@Nonnull
public String getText() {
return viewState.getText();
}
@Nonnull
@Override
public CharSequence getTextAsCharSequence() {
return getText();
}
@Override
public int getSelection() {
return viewState.getSelection();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@Nonnull Parcel out, int flags) {
out.writeString(viewState.getText());
out.writeInt(viewState.getSelection());
}
}

View File

@ -44,8 +44,8 @@ import javax.annotation.Nullable;
*/ */
public class CalculatorOnscreenService extends Service implements OnscreenViewListener, CalculatorEventListener { public class CalculatorOnscreenService extends Service implements OnscreenViewListener, CalculatorEventListener {
private static final String INIT_ACTION = "org.solovyev.android.calculator.INIT"; private static final String SHOW_WINDOW_ACTION = "org.solovyev.android.calculator.onscreen.SHOW_WINDOW";
private static final String INIT_ACTION_CREATE_VIEW_EXTRA = "createView"; private static final String SHOW_NOTIFICATION_ACTION = "org.solovyev.android.calculator.onscreen.SHOW_NOTIFICATION";
private static final int NOTIFICATION_ID = 9031988; // my birthday =) private static final int NOTIFICATION_ID = 9031988; // my birthday =)
@ -151,21 +151,21 @@ public class CalculatorOnscreenService extends Service implements OnscreenViewLi
private void handleStart(@Nullable Intent intent) { private void handleStart(@Nullable Intent intent) {
if (intent != null) { if (intent != null) {
if (isInitIntent(intent)) { if (isShowWindowIntent(intent)) {
boolean createView = intent.getBooleanExtra(INIT_ACTION_CREATE_VIEW_EXTRA, false);
if (createView) {
hideNotification(); hideNotification();
createView(); createView();
} else { } else if (isShowNotificationIntent(intent)) {
showNotification(); showNotification();
} }
} }
} }
private boolean isShowNotificationIntent(@Nonnull Intent intent) {
return intent.getAction().equals(SHOW_NOTIFICATION_ACTION);
} }
private boolean isInitIntent(@Nonnull Intent intent) { private boolean isShowWindowIntent(@Nonnull Intent intent) {
return intent.getAction().equals(INIT_ACTION); return intent.getAction().equals(SHOW_WINDOW_ACTION);
} }
private void hideNotification() { private void hideNotification() {
@ -191,7 +191,7 @@ public class CalculatorOnscreenService extends Service implements OnscreenViewLi
builder.setContentText(getString(R.string.open_onscreen_calculator)); builder.setContentText(getString(R.string.open_onscreen_calculator));
builder.setOngoing(true); builder.setOngoing(true);
final Intent intent = createShowOnscreenViewIntent(this); final Intent intent = createShowWindowIntent(this);
builder.setContentIntent(PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)); builder.setContentIntent(PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
final NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); final NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
@ -199,21 +199,20 @@ public class CalculatorOnscreenService extends Service implements OnscreenViewLi
} }
public static void showNotification(@Nonnull Context context) { public static void showNotification(@Nonnull Context context) {
final Intent intent = new Intent(INIT_ACTION); final Intent intent = new Intent(SHOW_NOTIFICATION_ACTION);
intent.setClass(context, getIntentListenerClass()); intent.setClass(context, getIntentListenerClass());
context.sendBroadcast(intent); context.sendBroadcast(intent);
} }
public static void showOnscreenView(@Nonnull Context context) { public static void showOnscreenView(@Nonnull Context context) {
final Intent intent = createShowOnscreenViewIntent(context); final Intent intent = createShowWindowIntent(context);
context.sendBroadcast(intent); context.sendBroadcast(intent);
} }
@Nonnull @Nonnull
private static Intent createShowOnscreenViewIntent(@Nonnull Context context) { private static Intent createShowWindowIntent(@Nonnull Context context) {
final Intent intent = new Intent(INIT_ACTION); final Intent intent = new Intent(SHOW_WINDOW_ACTION);
intent.setClass(context, getIntentListenerClass()); intent.setClass(context, getIntentListenerClass());
intent.putExtra(INIT_ACTION_CREATE_VIEW_EXTRA, true);
return intent; return intent;
} }

View File

@ -36,6 +36,8 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import static android.content.Intent.ACTION_CONFIGURATION_CHANGED; import static android.content.Intent.ACTION_CONFIGURATION_CHANGED;
import static org.solovyev.android.calculator.CalculatorBroadcaster.ACTION_DISPLAY_STATE_CHANGED;
import static org.solovyev.android.calculator.CalculatorBroadcaster.ACTION_EDITOR_STATE_CHANGED;
/** /**
* User: Solovyev_S * User: Solovyev_S
@ -44,8 +46,8 @@ import static android.content.Intent.ACTION_CONFIGURATION_CHANGED;
*/ */
abstract class AbstractCalculatorWidgetProvider extends AppWidgetProvider { abstract class AbstractCalculatorWidgetProvider extends AppWidgetProvider {
static final String BUTTON_ID_EXTRA = "buttonId"; static final String ACTION_BUTTON_ID_EXTRA = "buttonId";
static final String BUTTON_PRESSED_ACTION = "org.solovyev.android.calculator.widget.BUTTON_PRESSED"; static final String ACTION_BUTTON_PRESSED = "org.solovyev.android.calculator.BUTTON_PRESSED";
private static final String TAG = "Calculator++ Widget"; private static final String TAG = "Calculator++ Widget";
@ -99,18 +101,15 @@ abstract class AbstractCalculatorWidgetProvider extends AppWidgetProvider{
@Nonnull int[] appWidgetIds) { @Nonnull int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds); super.onUpdate(context, appWidgetManager, appWidgetIds);
updateWidget(context, appWidgetManager, appWidgetIds, Locator.getInstance().getEditor().getViewState(), Locator.getInstance().getDisplay().getViewState()); updateWidget(context, appWidgetManager, appWidgetIds);
} }
public void updateState(@Nonnull Context context, public void updateState(@Nonnull Context context) {
@Nonnull CalculatorEditorViewState editorState,
@Nonnull CalculatorDisplayViewState displayState) {
final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
final int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, getComponentClass())); final int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, getComponentClass()));
updateWidget(context, appWidgetManager, appWidgetIds, editorState, displayState); updateWidget(context, appWidgetManager, appWidgetIds);
} }
@Nonnull @Nonnull
protected Class<? extends AbstractCalculatorWidgetProvider> getComponentClass() { protected Class<? extends AbstractCalculatorWidgetProvider> getComponentClass() {
return this.getClass(); return this.getClass();
@ -118,16 +117,17 @@ abstract class AbstractCalculatorWidgetProvider extends AppWidgetProvider{
private void updateWidget(@Nonnull Context context, private void updateWidget(@Nonnull Context context,
@Nonnull AppWidgetManager appWidgetManager, @Nonnull AppWidgetManager appWidgetManager,
@Nonnull int[] appWidgetIds, @Nonnull int[] appWidgetIds) {
@Nonnull CalculatorEditorViewState editorState, final CalculatorEditorViewState editorState = Locator.getInstance().getEditor().getViewState();
@Nonnull CalculatorDisplayViewState displayState) { final CalculatorDisplayViewState displayState = Locator.getInstance().getDisplay().getViewState();
for (int appWidgetId : appWidgetIds) { for (int appWidgetId : appWidgetIds) {
final RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout); final RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
for (CalculatorButton button : CalculatorButton.values()) { for (CalculatorButton button : CalculatorButton.values()) {
final Intent onButtonClickIntent = new Intent(context, getComponentClass()); final Intent onButtonClickIntent = new Intent(context, getComponentClass());
onButtonClickIntent.setAction(BUTTON_PRESSED_ACTION); onButtonClickIntent.setAction(ACTION_BUTTON_PRESSED);
onButtonClickIntent.putExtra(BUTTON_ID_EXTRA, button.getButtonId()); onButtonClickIntent.putExtra(ACTION_BUTTON_ID_EXTRA, button.getButtonId());
final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, button.getButtonId(), onButtonClickIntent, PendingIntent.FLAG_UPDATE_CURRENT); final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, button.getButtonId(), onButtonClickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
if (pendingIntent != null) { if (pendingIntent != null) {
views.setOnClickPendingIntent(button.getButtonId(), pendingIntent); views.setOnClickPendingIntent(button.getButtonId(), pendingIntent);
@ -147,15 +147,20 @@ abstract class AbstractCalculatorWidgetProvider extends AppWidgetProvider{
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent); super.onReceive(context, intent);
if (BUTTON_PRESSED_ACTION.equals(intent.getAction())) { final String action = intent.getAction();
final int buttonId = intent.getIntExtra(AbstractCalculatorWidgetProvider.BUTTON_ID_EXTRA, 0); if (ACTION_BUTTON_PRESSED.equals(action)) {
final int buttonId = intent.getIntExtra(ACTION_BUTTON_ID_EXTRA, 0);
final CalculatorButton button = CalculatorButton.getById(buttonId); final CalculatorButton button = CalculatorButton.getById(buttonId);
if (button != null) { if (button != null) {
button.onClick(context); button.onClick(context);
} }
} else if (ACTION_CONFIGURATION_CHANGED.equals(intent.getAction())) { } else if (ACTION_CONFIGURATION_CHANGED.equals(action)) {
updateState(context, Locator.getInstance().getEditor().getViewState(), Locator.getInstance().getDisplay().getViewState()); updateState(context);
} else if (ACTION_EDITOR_STATE_CHANGED.equals(action)) {
updateState(context);
} else if (ACTION_DISPLAY_STATE_CHANGED.equals(action)) {
updateState(context);
} }
} }

View File

@ -109,18 +109,16 @@
<service android:name=".onscreen.CalculatorOnscreenService" android:exported="false"> <service android:name=".onscreen.CalculatorOnscreenService" android:exported="false">
<intent-filter> <intent-filter>
<action android:name="org.solovyev.android.calculator.INIT"/> <action android:name="org.solovyev.android.calculator.onscreen.SHOW_WINDOW"/>
<action android:name="org.solovyev.android.calculator.EDITOR_STATE_CHANGED"/> <action android:name="org.solovyev.android.calculator.onscreen.SHOW_NOTIFICATION"/>
<action android:name="org.solovyev.android.calculator.DISPLAY_STATE_CHANGED"/>
</intent-filter> </intent-filter>
</service> </service>
<receiver android:name=".onscreen.CalculatorOnscreenBroadcastReceiver"> <receiver android:name=".onscreen.CalculatorOnscreenBroadcastReceiver">
<intent-filter> <intent-filter>
<action android:name="org.solovyev.android.calculator.INIT"/>
<action android:name="android.intent.action.BOOT_COMPLETED"/> <action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="org.solovyev.android.calculator.EDITOR_STATE_CHANGED"/> <action android:name="org.solovyev.android.calculator.onscreen.SHOW_WINDOW"/>
<action android:name="org.solovyev.android.calculator.DISPLAY_STATE_CHANGED"/> <action android:name="org.solovyev.android.calculator.onscreen.SHOW_NOTIFICATION"/>
</intent-filter> </intent-filter>
</receiver> </receiver>
@ -134,7 +132,7 @@
<action android:name="org.solovyev.android.calculator.INIT"/> <action android:name="org.solovyev.android.calculator.INIT"/>
<action android:name="org.solovyev.android.calculator.EDITOR_STATE_CHANGED"/> <action android:name="org.solovyev.android.calculator.EDITOR_STATE_CHANGED"/>
<action android:name="org.solovyev.android.calculator.DISPLAY_STATE_CHANGED"/> <action android:name="org.solovyev.android.calculator.DISPLAY_STATE_CHANGED"/>
<action android:name="org.solovyev.android.calculator.widget.BUTTON_PRESSED"/> <action android:name="org.solovyev.android.calculator.BUTTON_PRESSED"/>
</intent-filter> </intent-filter>
<meta-data android:name="android.appwidget.provider" android:resource="@xml/calculator_widget_info_3x3"/> <meta-data android:name="android.appwidget.provider" android:resource="@xml/calculator_widget_info_3x3"/>
@ -148,7 +146,7 @@
<action android:name="org.solovyev.android.calculator.INIT"/> <action android:name="org.solovyev.android.calculator.INIT"/>
<action android:name="org.solovyev.android.calculator.EDITOR_STATE_CHANGED"/> <action android:name="org.solovyev.android.calculator.EDITOR_STATE_CHANGED"/>
<action android:name="org.solovyev.android.calculator.DISPLAY_STATE_CHANGED"/> <action android:name="org.solovyev.android.calculator.DISPLAY_STATE_CHANGED"/>
<action android:name="org.solovyev.android.calculator.widget.BUTTON_PRESSED"/> <action android:name="org.solovyev.android.calculator.BUTTON_PRESSED"/>
</intent-filter> </intent-filter>
<meta-data android:name="android.appwidget.provider" android:resource="@xml/calculator_widget_info_3x4"/> <meta-data android:name="android.appwidget.provider" android:resource="@xml/calculator_widget_info_3x4"/>
@ -162,7 +160,7 @@
<action android:name="org.solovyev.android.calculator.INIT"/> <action android:name="org.solovyev.android.calculator.INIT"/>
<action android:name="org.solovyev.android.calculator.EDITOR_STATE_CHANGED"/> <action android:name="org.solovyev.android.calculator.EDITOR_STATE_CHANGED"/>
<action android:name="org.solovyev.android.calculator.DISPLAY_STATE_CHANGED"/> <action android:name="org.solovyev.android.calculator.DISPLAY_STATE_CHANGED"/>
<action android:name="org.solovyev.android.calculator.widget.BUTTON_PRESSED"/> <action android:name="org.solovyev.android.calculator.BUTTON_PRESSED"/>
</intent-filter> </intent-filter>
<meta-data android:name="android.appwidget.provider" android:resource="@xml/calculator_widget_info_4x4"/> <meta-data android:name="android.appwidget.provider" android:resource="@xml/calculator_widget_info_4x4"/>
@ -176,7 +174,7 @@
<action android:name="org.solovyev.android.calculator.INIT"/> <action android:name="org.solovyev.android.calculator.INIT"/>
<action android:name="org.solovyev.android.calculator.EDITOR_STATE_CHANGED"/> <action android:name="org.solovyev.android.calculator.EDITOR_STATE_CHANGED"/>
<action android:name="org.solovyev.android.calculator.DISPLAY_STATE_CHANGED"/> <action android:name="org.solovyev.android.calculator.DISPLAY_STATE_CHANGED"/>
<action android:name="org.solovyev.android.calculator.widget.BUTTON_PRESSED"/> <action android:name="org.solovyev.android.calculator.BUTTON_PRESSED"/>
</intent-filter> </intent-filter>
<meta-data android:name="android.appwidget.provider" android:resource="@xml/calculator_widget_info_4x5"/> <meta-data android:name="android.appwidget.provider" android:resource="@xml/calculator_widget_info_4x5"/>

View File

@ -96,6 +96,9 @@ public class CalculatorApplication extends android.app.Application implements Sh
@Nonnull @Nonnull
protected final Handler uiHandler = new Handler(); protected final Handler uiHandler = new Handler();
@Nonnull
private final CalculatorBroadcaster broadcaster = new CalculatorBroadcaster(this);
/* /*
********************************************************************** **********************************************************************
* *
@ -154,6 +157,8 @@ public class CalculatorApplication extends android.app.Application implements Sh
calculator.addCalculatorEventListener(listener); calculator.addCalculatorEventListener(listener);
} }
calculator.addCalculatorEventListener(broadcaster);
Locator.getInstance().getCalculator().init(); Locator.getInstance().getCalculator().init();
BillingDB.init(CalculatorApplication.this); BillingDB.init(CalculatorApplication.this);