Merge remote-tracking branch 'server/bug3741'

This commit is contained in:
Axel Uhl committed 2016-07-14 22:01:39 +02:00
commit 6755744183
19 files changed
+131 -110

No files matched your search

Binary file not shown.

After

Width:  |  Height:  |  Size: 818 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 597 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 971 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- disabled -->
<item android:drawable="@drawable/ic_refresh_black_48dp" android:state_enabled="false" />
<!-- default -->
<item android:drawable="@drawable/ic_refresh_white_48dp" />
</selector>
@@ -8,7 +8,7 @@
<item android:drawable="@drawable/round_button_normal" android:state_focused="true" />
<!-- disabled -->
<item android:drawable="@drawable/round_button_normal" android:state_enabled="false" />
<item android:drawable="@drawable/round_button_disabled" android:state_enabled="false" />
<!-- default -->
<item android:drawable="@drawable/round_button_normal" />
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/light_sap_gray_white_10" />
<stroke
android:width="@dimen/thin_line"
android:color="@color/dark_sap_gray" />
</shape>
@@ -26,7 +26,7 @@
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_margin="@dimen/default_margin"
android:src="@drawable/ic_refresh_white_48dp"/>
android:src="@drawable/ic_refresh_48dp"/>
<TextView
android:id="@+id/regatta_data"
@@ -4,6 +4,6 @@
<item name="drag_handle" type="id" />
<item name="fling_remove" type="id" />
<item name="click_remove" type="id" />
<item name="protest_flag_image_click_listener" type="id" />
<item name="race_list_header" type="id" />
</resources>
@@ -25,8 +25,6 @@ public class AppConstants {
private final static String INTENT_ACTION = PACKAGE_NAME + ".action";
public final static String INTENT_ACTION_RESET = INTENT_ACTION + ".reset";
public final static String INTENT_ACTION_REGISTER_RACE = INTENT_ACTION + ".registerRace";
public final static String INTENT_ACTION_UNREGISTER_RACE = INTENT_ACTION + ".unregisterRace";
public final static String INTENT_ACTION_CLEAR_RACES = INTENT_ACTION + ".clearRaces";
public final static String INTENT_ACTION_CLEANUP_RACES = INTENT_ACTION + ".cleanupRaces";
public final static String INTENT_ACTION_ALARM_ACTION = INTENT_ACTION + ".alarmAction";
@@ -15,6 +15,7 @@ public abstract class DataManager implements ReadonlyDataManager {
public static ReadonlyDataManager create(Context context) {
DataStore dataStore = InMemoryDataStore.INSTANCE;
dataStore.setContext(context);
if (AppPreferences.on(context).isOfflineMode()) {
return new OfflineDataManager(context, dataStore, dataStore.getDomainFactory());
}
@@ -5,6 +5,8 @@ import java.util.Collection;
import java.util.Set;
import java.util.UUID;
import android.content.Context;
import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier;
import com.sap.sailing.domain.base.CourseArea;
import com.sap.sailing.domain.base.CourseBase;
@@ -15,7 +17,8 @@ import com.sap.sailing.domain.base.racegroup.RaceGroup;
import com.sap.sailing.racecommittee.app.domain.ManagedRace;
public interface DataStore {
void setContext(Context context);
void reset();
SharedDomainFactory getDomainFactory();
@@ -38,6 +41,7 @@ public interface DataStore {
ManagedRace getRace(SimpleRaceLogIdentifier id);
boolean hasRace(String id);
boolean hasRace(SimpleRaceLogIdentifier id);
void registerRaces(Collection<ManagedRace> races);
Collection<Mark> getMarks();
Mark getMark(Serializable id);
@@ -8,6 +8,12 @@ import java.util.Map;
import java.util.Set;
import java.util.UUID;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import com.sap.sailing.android.shared.util.CollectionUtils;
import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier;
import com.sap.sailing.domain.abstractlog.race.impl.SimpleRaceLogIdentifierImpl;
@@ -21,11 +27,13 @@ import com.sap.sailing.domain.base.racegroup.RaceGroup;
import com.sap.sailing.racecommittee.app.domain.ManagedRace;
import com.sap.sailing.racecommittee.app.domain.ManagedRaceIdentifier;
import com.sap.sailing.racecommittee.app.domain.impl.FleetIdentifierImpl;
import com.sap.sailing.racecommittee.app.services.RaceStateService;
import com.sap.sse.common.Util.Triple;
public enum InMemoryDataStore implements DataStore {
INSTANCE;
private Context mContext;
private LinkedHashMap<Serializable, EventBase> eventsById;
private LinkedHashMap<SimpleRaceLogIdentifier, ManagedRace> managedRaceById;
private LinkedHashMap<Serializable, Mark> marksById;
@@ -35,10 +43,22 @@ public enum InMemoryDataStore implements DataStore {
private Serializable eventUUID;
private UUID courseUUID;
private RaceStateService mService;
private boolean mBound;
InMemoryDataStore() {
reset();
}
@Override
public void setContext(Context context) {
if (mContext == null) {
mContext = context.getApplicationContext();
}
Intent intent = new Intent(mContext, RaceStateService.class);
mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
@Override
public void reset() {
eventsById = new LinkedHashMap<>();
@@ -49,6 +69,11 @@ public enum InMemoryDataStore implements DataStore {
eventUUID = null;
courseUUID = null;
if (mContext != null && mBound) {
mContext.unbindService(mConnection);
mBound = false;
}
}
@Override
@@ -185,6 +210,7 @@ public enum InMemoryDataStore implements DataStore {
@Override
public void removeRace(ManagedRace race) {
unregisterRace(race);
managedRaceById.remove(convertManagedRaceIdentifierToSimpleRaceLogIdentifier(race.getIdentifier()));
}
@@ -303,4 +329,32 @@ public enum InMemoryDataStore implements DataStore {
courseUUID = uuid;
}
public void registerRaces(Collection<ManagedRace> races) {
if (mBound) {
for (ManagedRace race : races) {
mService.registerRace(race);
}
}
}
private void unregisterRace(ManagedRace race) {
if (mBound) {
mService.unregisterRace(race);
}
}
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
RaceStateService.RaceStateServiceBinder binder = (RaceStateService.RaceStateServiceBinder) service;
mService = binder.getService();
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
mBound = false;
}
};
}
@@ -39,6 +39,7 @@ public class ManagedRacesDataHandler extends DataHandler<Collection<ManagedRace>
}
manager.addRaces(data);
calcRaceState(data);
manager.getDataStore().registerRaces(data);
}
}
@@ -118,7 +118,7 @@ public class RaceStateService extends Service {
}
@Override
public IBinder onBind(Intent arg0) {
public IBinder onBind(Intent intent) {
return mBinder;
}
@@ -167,7 +167,7 @@ public class RaceStateService extends Service {
ExLog.i(this, TAG, "All races unregistered.");
}
private void unregisterRace(ManagedRace race) {
public void unregisterRace(ManagedRace race) {
poller.unregister(race);
race.getState().getRaceLog().removeAllListeners();
@@ -183,6 +183,7 @@ public class RaceStateService extends Service {
managedIntents.remove(race.getId());
ExLog.i(this, TAG, "Race " + race.getId() + " unregistered");
updateNotification();
}
private void unregisterRace(@Nullable String raceId) {
@@ -212,16 +213,6 @@ public class RaceStateService extends Service {
return;
}
if (AppConstants.INTENT_ACTION_REGISTER_RACE.equals(action)) {
handleRegisterRace(intent);
return;
}
if (AppConstants.INTENT_ACTION_UNREGISTER_RACE.equals(action)) {
handleUnregisterRace(intent);
return;
}
if (!serviceId.equals(intent.getSerializableExtra(EXTRAS_SERVICE_ID))) {
ExLog.w(this, TAG, "Received event for different service version.");
return;
@@ -293,28 +284,6 @@ public class RaceStateService extends Service {
return false;
}
private void handleRegisterRace(Intent intent) {
ManagedRace race = getRaceFromIntent(intent);
if (race == null) {
ExLog.w(this, TAG, "Intent did not carry valid race information.");
return;
}
registerRace(race);
updateNotification();
}
private void handleUnregisterRace(Intent intent) {
ManagedRace race = getRaceFromIntent(intent);
if (race == null) {
ExLog.w(this, TAG, "Intent did not carry valid race information");
return;
}
unregisterRace(race);
updateNotification();
}
private void updateNotification() {
int numRaces = managedIntents.keySet().size();
notificationManager.notify(NOTIFICATION_ID, notificationBuilder
@@ -323,15 +292,7 @@ public class RaceStateService extends Service {
startForeground(NOTIFICATION_ID, notificationBuilder.build());
}
private ManagedRace getRaceFromIntent(Intent intent) {
if (intent.getExtras() == null || !intent.getExtras().containsKey(AppConstants.RACE_ID_KEY)) {
return null;
}
String raceId = intent.getExtras().getString(AppConstants.RACE_ID_KEY);
return dataManager.getDataStore().getRace(raceId);
}
private void registerRace(final ManagedRace race) {
public void registerRace(ManagedRace race) {
ExLog.i(this, TAG, "Trying to register race " + race.getId());
if (!managedIntents.containsKey(race.getId())) {
@@ -360,6 +321,8 @@ public class RaceStateService extends Service {
unregisterRace(race.getId());
registerRace(race);
}
updateNotification();
}
private PendingIntent createAlarmPendingIntent(ManagedRace managedRace, RaceStateEvent event) {
@@ -372,7 +335,7 @@ public class RaceStateService extends Service {
}
@TargetApi(Build.VERSION_CODES.KITKAT)
public void setAlarm(ManagedRace race, RaceStateEvent event) {
/* package */ void setAlarm(ManagedRace race, RaceStateEvent event) {
PendingIntent intent = createAlarmPendingIntent(race, event);
managedIntents.get(race.getId()).add(Pair.create(intent, event.getEventName()));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
@@ -383,7 +346,7 @@ public class RaceStateService extends Service {
ExLog.i(this, TAG, "The alarm " + event.getEventName() + " will be fired at " + event.getTimePoint());
}
public void clearAlarmByName(ManagedRace race, RaceStateEvents stateEventName) {
/* package */ void clearAlarmByName(ManagedRace race, RaceStateEvents stateEventName) {
List<Pair<PendingIntent, RaceStateEvents>> intents = managedIntents.get(race.getId());
Pair<PendingIntent, RaceStateEvents> toBeRemoved = null;
for (Pair<PendingIntent, RaceStateEvents> intentPair : intents) {
@@ -400,7 +363,7 @@ public class RaceStateService extends Service {
}
}
public void clearAllAlarms(ManagedRace race) {
/* package */ void clearAllAlarms(ManagedRace race) {
Serializable raceId = race.getId();
List<Pair<PendingIntent, RaceStateEvents>> intents = managedIntents.get(raceId);
@@ -316,7 +316,7 @@ public class RacingActivity extends SessionActivity implements RaceListCallbacks
}
}
public void onRaceItemClicked(ManagedRace managedRace) {
private void onRaceItemClicked(ManagedRace managedRace) {
onRaceItemClicked(managedRace, false);
}
@@ -380,7 +380,7 @@ public class RacingActivity extends SessionActivity implements RaceListCallbacks
}
}
public void onWindEntered(Wind windFix) {
private void onWindEntered(Wind windFix) {
PanelButton windValue = (PanelButton) findViewById(R.id.button_wind);
if (windFix != null) {
if (windValue != null) {
@@ -407,35 +407,7 @@ public class RacingActivity extends SessionActivity implements RaceListCallbacks
}
}
private void registerOnService(final Collection<ManagedRace> races) {
// close current race, if no longer on server
if (!races.contains(mSelectedRace)) {
BroadcastManager.getInstance(this).addIntent(new Intent(AppConstants.INTENT_ACTION_SHOW_WELCOME));
mSelectedRace = null;
}
// since the service is the long-living component
// he should decide whether these races are already
// registered or not.
new Thread(new Runnable() {
@Override
public void run() {
// add all received races to the service
for (ManagedRace race : races) {
Intent registerIntent = new Intent(RacingActivity.this, RaceStateService.class);
registerIntent.setAction(AppConstants.INTENT_ACTION_REGISTER_RACE);
registerIntent.putExtra(AppConstants.RACE_ID_KEY, race.getId());
RacingActivity.this.startService(registerIntent);
}
Intent cleanupIntent = new Intent(RacingActivity.this, RaceStateService.class);
cleanupIntent.setAction(AppConstants.INTENT_ACTION_CLEANUP_RACES);
RacingActivity.this.startService(cleanupIntent);
}
}).start();
}
public void setProgressSpinnerVisibility(boolean visible) {
private void setProgressSpinnerVisibility(boolean visible) {
if (mProgressSpinner != null) {
if (visible) {
mProgressSpinner.setVisibility(View.VISIBLE);
@@ -459,7 +431,7 @@ public class RacingActivity extends SessionActivity implements RaceListCallbacks
}
}
public void resetRace() {
private void resetRace() {
AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.AppTheme_AlertDialog);
builder.setTitle(getString(R.string.race_reset_confirmation_title));
builder.setMessage(getString(R.string.race_reset_message));
@@ -576,7 +548,7 @@ public class RacingActivity extends SessionActivity implements RaceListCallbacks
}
}
public void processIntent(final Intent intent) {
private void processIntent(final Intent intent) {
final Bundle args = new Bundle();
if (mSelectedRace != null) {
args.putSerializable(AppConstants.RACE_ID_KEY, mSelectedRace.getId());
@@ -717,14 +689,17 @@ public class RacingActivity extends SessionActivity implements RaceListCallbacks
@Override
public void onLoadSucceeded(Collection<ManagedRace> data, boolean isCached) {
// Let's do the setup stuff only when the data is changed (or its the first time)
if (lastSeenRaces != null && CollectionUtils.isEqualCollection(data, lastSeenRaces)) {
ExLog.i(RacingActivity.this, TAG, "Same races are already loaded...");
} else {
lastSeenRaces = data;
registerOnService(data);
mRaceList.setupOn(data);
setupRegattaSpecificConfiguration();
// need to be a new instance, because of Activity restart after background kill
// more information see bug 3741
lastSeenRaces = new ArrayList<>(data);
mRaceList.setupOn(data);
setupRegattaSpecificConfiguration();
if (!isCached) {
// close current race, if no longer on server
if (!data.contains(mSelectedRace)) {
BroadcastManager.getInstance(RacingActivity.this).addIntent(new Intent(AppConstants.INTENT_ACTION_SHOW_WELCOME));
mSelectedRace = null;
}
Toast.makeText(RacingActivity.this, String.format(getString(R.string.racing_load_success), data.size()), Toast.LENGTH_SHORT).show();
}
setProgressSpinnerVisibility(false);
@@ -161,20 +161,20 @@ public class ManagedRaceListAdapter extends ArrayAdapter<RaceListDataType> imple
if (type == ViewType.HEADER.index) {
final RaceListDataTypeHeader header = (RaceListDataTypeHeader) raceListElement;
String regatta = header.getRaceGroup().getDisplayName();
if (TextUtils.isEmpty(regatta)) {
regatta = header.getRaceGroup().getName();
}
boat_class.setText(regatta);
fleet_series.setText(RaceHelper.getSeriesName(header.getSeries(), ""));
if (fleet_series.getText().length() == 0) {
fleet_series.setVisibility(View.GONE);
} else {
fleet_series.setVisibility(View.VISIBLE);
}
protest_image.setImageDrawable(FlagsResources.getFlagDrawable(getContext(), Flags.BRAVO.name(), flag_size));
if (protest_image.getTag(R.id.protest_flag_image_click_listener) == null ||
protest_image.getTag(R.id.protest_flag_image_click_listener) != Boolean.TRUE) {
protest_image.setTag(R.id.protest_flag_image_click_listener, Boolean.TRUE);
String series = RaceHelper.getSeriesName(header.getSeries(), "");
if (!(regatta + series).equals(convertView.getTag(R.id.race_list_header))) {
if (TextUtils.isEmpty(regatta)) {
regatta = header.getRaceGroup().getName();
}
boat_class.setText(regatta);
fleet_series.setText(series);
if (fleet_series.getText().length() == 0) {
fleet_series.setVisibility(View.GONE);
} else {
fleet_series.setVisibility(View.VISIBLE);
}
protest_image.setImageDrawable(FlagsResources.getFlagDrawable(getContext(), Flags.BRAVO.name(), flag_size));
protest_image.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -184,6 +184,7 @@ public class ManagedRaceListAdapter extends ArrayAdapter<RaceListDataType> imple
BroadcastManager.getInstance(getContext()).addIntent(intent);
}
});
convertView.setTag(R.id.race_list_header, regatta + series);
}
} else if (type == ViewType.RACE.index) {
final RaceListDataTypeRace race = (RaceListDataTypeRace) raceListElement;
@@ -76,6 +76,7 @@ public class RaceListFragment extends LoggableFragment implements OnItemClickLis
private Button mAllRacesButton;
private TextView mCourse;
private TextView mData;
private ImageView mRefresh;
private DrawerLayout mDrawerLayout;
private ActionBarDrawerToggle mDrawerToggle;
private FilterMode mFilterMode;
@@ -256,9 +257,9 @@ public class RaceListFragment extends LoggableFragment implements OnItemClickLis
mCourse = (TextView) view.findViewById(R.id.regatta_course);
mData = (TextView) view.findViewById(R.id.regatta_data);
ImageView imageView = (ImageView) view.findViewById(R.id.nav_button);
if (imageView != null) {
imageView.setOnClickListener(new OnClickListener() {
mRefresh = (ImageView) view.findViewById(R.id.nav_button);
if (mRefresh != null) {
mRefresh.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
@@ -481,10 +482,14 @@ public class RaceListFragment extends LoggableFragment implements OnItemClickLis
public void showSpinner(boolean visible) {
if (mProgress != null) {
if (visible) {
mRefresh.setEnabled(false);
mProgress.setVisibility(View.VISIBLE);
mListView.setVisibility(View.GONE);
mUpdateList = false;
} else {
mRefresh.setEnabled(true);
mProgress.setVisibility(View.GONE);
mListView.setVisibility(View.VISIBLE);
mUpdateList = true;
}
}