Commit 85ba21df authored by Rufus's avatar Rufus

Merge branch 'master' of https://github.com/cbeyls/fosdem-companion-android

Set URL to test

# Conflicts:
#	README.md
#	app/build.gradle
#	app/src/main/AndroidManifest.xml
#	app/src/main/java/at/linuxtage/companion/GLTApplication.java
#	app/src/main/java/at/linuxtage/companion/activities/AppCompatPreferenceActivity.java
#	app/src/main/java/at/linuxtage/companion/activities/BaseActivity.java
#	app/src/main/java/at/linuxtage/companion/activities/EventDetailsActivity.java
#	app/src/main/java/at/linuxtage/companion/activities/MainActivity.java
#	app/src/main/java/at/linuxtage/companion/activities/PersonInfoActivity.java
#	app/src/main/java/at/linuxtage/companion/activities/RoomImageDialogActivity.java
#	app/src/main/java/at/linuxtage/companion/activities/SearchResultActivity.java
#	app/src/main/java/at/linuxtage/companion/activities/SettingsActivity.java
#	app/src/main/java/at/linuxtage/companion/activities/TrackScheduleActivity.java
#	app/src/main/java/at/linuxtage/companion/activities/TrackScheduleEventActivity.java
#	app/src/main/java/at/linuxtage/companion/adapters/BookmarksAdapter.java
#	app/src/main/java/at/linuxtage/companion/adapters/EventsAdapter.java
#	app/src/main/java/at/linuxtage/companion/adapters/RecyclerViewCursorAdapter.java
#	app/src/main/java/at/linuxtage/companion/alarms/FosdemAlarmManager.java
#	app/src/main/java/at/linuxtage/companion/api/GLTApi.java
#	app/src/main/java/at/linuxtage/companion/api/LiveRoomStatusesLiveData.java
#	app/src/main/java/at/linuxtage/companion/api/RoomStatusesLiveData.java
#	app/src/main/java/at/linuxtage/companion/db/DatabaseHelper.java
#	app/src/main/java/at/linuxtage/companion/db/DatabaseManager.java
#	app/src/main/java/at/linuxtage/companion/db/LocalBroadcastCursor.java
#	app/src/main/java/at/linuxtage/companion/fragments/BaseLiveListFragment.java
#	app/src/main/java/at/linuxtage/companion/fragments/BookmarksListFragment.java
#	app/src/main/java/at/linuxtage/companion/fragments/EventDetailsFragment.java
#	app/src/main/java/at/linuxtage/companion/fragments/LiveFragment.java
#	app/src/main/java/at/linuxtage/companion/fragments/MapFragment.java
#	app/src/main/java/at/linuxtage/companion/fragments/MessageDialogFragment.java
#	app/src/main/java/at/linuxtage/companion/fragments/NextLiveListFragment.java
#	app/src/main/java/at/linuxtage/companion/fragments/NowLiveListFragment.java
#	app/src/main/java/at/linuxtage/companion/fragments/PersonInfoListFragment.java
#	app/src/main/java/at/linuxtage/companion/fragments/PersonsListFragment.java
#	app/src/main/java/at/linuxtage/companion/fragments/RecyclerViewFragment.java
#	app/src/main/java/at/linuxtage/companion/fragments/RoomImageDialogFragment.java
#	app/src/main/java/at/linuxtage/companion/fragments/SearchResultListFragment.java
#	app/src/main/java/at/linuxtage/companion/fragments/SmoothListFragment.java
#	app/src/main/java/at/linuxtage/companion/fragments/TrackScheduleListFragment.java
#	app/src/main/java/at/linuxtage/companion/fragments/TracksFragment.java
#	app/src/main/java/at/linuxtage/companion/fragments/TracksListFragment.java
#	app/src/main/java/at/linuxtage/companion/livedata/AsyncTaskLiveData.java
#	app/src/main/java/at/linuxtage/companion/loaders/BaseLiveLoader.java
#	app/src/main/java/at/linuxtage/companion/loaders/SimpleCursorLoader.java
#	app/src/main/java/at/linuxtage/companion/loaders/TrackScheduleLoader.java
#	app/src/main/java/at/linuxtage/companion/model/Day.java
#	app/src/main/java/at/linuxtage/companion/model/Event.java
#	app/src/main/java/at/linuxtage/companion/model/Person.java
#	app/src/main/java/at/linuxtage/companion/model/RoomStatus.java
#	app/src/main/java/at/linuxtage/companion/model/Track.java
#	app/src/main/java/at/linuxtage/companion/parsers/EventsParser.java
#	app/src/main/java/at/linuxtage/companion/providers/BookmarksExportProvider.java
#	app/src/main/java/at/linuxtage/companion/providers/SearchSuggestionProvider.java
#	app/src/main/java/at/linuxtage/companion/services/AlarmIntentService.java
#	app/src/main/java/at/linuxtage/companion/utils/ArrayUtils.java
#	app/src/main/java/at/linuxtage/companion/utils/ThemeUtils.java
#	app/src/main/java/at/linuxtage/companion/viewmodels/EventDetailsViewModel.java
#	app/src/main/java/at/linuxtage/companion/viewmodels/EventViewModel.java
#	app/src/main/java/at/linuxtage/companion/widgets/AdapterLinearLayout.java
#	app/src/main/java/at/linuxtage/companion/widgets/ScrimInsetsFrameLayout.java
#	app/src/main/java/at/linuxtage/companion/widgets/SlidingTabLayout.java
#	app/src/main/java/be/digitalia/fosdem/utils/DateUtils.java
#	app/src/main/java/be/digitalia/fosdem/widgets/ForegroundLinearLayout.java
#	app/src/main/java/com/viewpagerindicator/UnderlinePageIndicator.java
#	app/src/main/res/drawable-hdpi/campusmap.png
#	app/src/main/res/layout/fragment_event_details.xml
#	app/src/main/res/layout/fragment_live.xml
#	app/src/main/res/layout/fragment_tracks.xml
#	app/src/main/res/layout/include_navigation_drawer.xml
#	app/src/main/res/layout/item_event.xml
#	app/src/main/res/layout/item_schedule_event.xml
#	app/src/main/res/layout/main.xml
parents 0075b41d 29af6e46
# GLT Companion
This is the schedule browser for the "[Grazer Linuxtage](https://linuxtage.at)" conference in Graz, Austria.
This is the schedule browser for the "[Grazer Linuxtage](https://linuxtage.at)" conference in Graz, Austria.
It's a fork of [FOSDEM companion](https://github.com/cbeyls/fosdem-companion-android) by [Christophe Beyls](https://github.com/cbeyls).
The code has been rewritten from scratch and the features have been extended. It is built on top of the latest Android support libraries in order to take advantage of the latest operating system features while preserving compatibility with older versions.
You can install the app from the [Google Play Store](https://play.google.com/store/apps/details?id=at.linuxtage.companion) or directly from the [GLT website](https://linuxtage.at/downloads/app).
It's a fork of [FOSDEM companion](https://github.com/cbeyls/fosdem-companion-android) by [Christophe Beyls](https://github.com/cbeyls). The code has been rewritten from scratch and the features have been extended. It is built on top of the latest [Jetpack](https://developer.android.com/jetpack/) libraries by Google.
Donations to Grazer Linuxtage are possible via Bitcoin: [1GLTBBirbj8GZ8uY1gwovZ1QEMjfWu3rWT](bitcoin:1GLTBBirbj8GZ8uY1gwovZ1QEMjfWu3rWT)
<a href="https://f-droid.org/repository/browse/?fdfilter=fosdem&fdid=be.digitalia.fosdem" target="_blank">
<img src="https://f-droid.org/badge/get-it-on.png" height="80"/>
</a>
<a href="https://play.google.com/store/apps/details?id=be.digitalia.fosdem" target="_blank">
<img src="https://play.google.com/intl/en_us/badges/images/generic/en-play-badge.png" height="80"/>
</a>
## How to build
......@@ -25,11 +29,13 @@ The result apk file will be placed in ```app/build/outputs/apk/```.
## Used libraries
* [Android Support Library](http://developer.android.com/tools/support-library/) by The Android Open Source Project
* [ViewPagerIndicator](http://viewpagerindicator.com/) by Jake Wharton
* [PhotoView](https://github.com/chrisbanes/PhotoView) by Chris Banes
* [AndroidX](https://developer.android.com/jetpack/androidx/) by The Android Open Source Project
* [Android Architecture Components](https://developer.android.com/topic/libraries/architecture/) by The Android Open Source Project
* [Material Components for Android](https://material.io/develop/android/) by The Android Open Source Project
* [PhotoView](https://github.com/chrisbanes/PhotoView) by Chris Banes, Marek Sebera and John Carlson
## Contributors
* Christophe Beyls
* Florian Klien
* Georg Schlagholz
\ No newline at end of file
......@@ -6,36 +6,48 @@ android {
keyAlias 'klienuxAT'
}
}
compileSdkVersion 27
buildToolsVersion "27.0.3"
compileSdkVersion 28
buildToolsVersion "28.0.3"
defaultConfig {
applicationId "at.linuxtage.companion"
minSdkVersion 15
targetSdkVersion 27
versionCode 1500151
versionName "1.4.6"
minSdkVersion 16
targetSdkVersion 28
versionCode 1600162
versionName "1.6.2"
// Supported languages
resConfigs "en"
vectorDrawables.useSupportLibrary = true
}
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
postprocessing {
removeUnusedCode true
removeUnusedResources true
obfuscate true
optimizeCode false
proguardFiles 'proguard-rules.pro'
}
}
}
}
ext {
supportLibraryVersion = '27.0.2'
}
dependencies {
implementation "com.android.support:appcompat-v7:$supportLibraryVersion"
implementation "com.android.support:recyclerview-v7:$supportLibraryVersion"
implementation "com.android.support:cardview-v7:$supportLibraryVersion"
implementation "com.android.support:customtabs:$supportLibraryVersion"
implementation 'android.arch.lifecycle:extensions:1.1.0'
implementation 'com.github.chrisbanes:PhotoView:2.1.3'
def room_version = "2.1.0-alpha04"
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'com.google.android.material:material:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.0.0'
implementation 'androidx.cardview:cardview:1.0.0'
implementation('androidx.preference:preference:1.1.0-alpha02') {
// Alpha versions of these dependencies are unstable
exclude group: 'androidx.fragment', module: 'fragment'
exclude group: 'androidx.core', module: 'core'
}
implementation 'androidx.browser:browser:1.0.0'
implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'
implementation 'androidx.paging:paging-runtime:2.1.0'
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
implementation 'com.github.chrisbanes:PhotoView:2.3.0'
}
# Add project specific ProGuard rules here.
# Action Views
-keep class android.support.v7.widget.SearchView { public *; }
# keep setters in VectorDrawables so that animations can still work.
-keepclassmembers class android.support.graphics.drawable.VectorDrawableCompat$* {
void set*(***);
*** get*();
}
\ No newline at end of file
-keep class androidx.appcompat.widget.SearchView { <init>(...); }
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<manifest
package="at.linuxtage.companion"
xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="auto">
xmlns:tools="http://schemas.android.com/tools"
package="at.linuxtage.companion"
android:installLocation="auto"
tools:ignore="GoogleAppIndexingWarning">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.NFC"/>
......@@ -24,7 +26,7 @@
<application
android:name=".GLTApplication"
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
......@@ -48,18 +50,16 @@
<activity
android:name=".activities.TrackScheduleActivity"
android:parentActivityName=".activities.MainActivity"
android:theme="@style/AppTheme.NoActionBar">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activities.MainActivity"/>
</activity>
android:theme="@style/AppTheme.NoActionBar"/>
<activity
android:name=".activities.TrackScheduleEventActivity"
android:label="@string/event_details"/>
android:label="@string/event_details"
android:theme="@style/AppTheme.NoActionBar"/>
<activity
android:name=".activities.EventDetailsActivity"
android:label="@string/event_details"
android:parentActivityName=".activities.TrackScheduleActivity">
android:parentActivityName=".activities.TrackScheduleActivity"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
......@@ -67,9 +67,6 @@
<data android:mimeType="application/${applicationId}"/>
</intent-filter>
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activities.TrackScheduleActivity"/>
</activity>
<activity
android:name=".activities.PersonInfoActivity"
......@@ -90,6 +87,18 @@
android:name="android.app.searchable"
android:resource="@xml/main_searchable"/>
</activity>
<activity
android:name=".activities.ExternalBookmarksActivity"
android:label="@string/external_bookmarks_title"
android:parentActivityName=".activities.MainActivity">
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/${applicationId}-bookmarks" />
</intent-filter>
</activity>
<!-- Clearing the Task Affinity allows this dialog activity to be displayed without bringing to front the main application with it. -->
<activity
android:name=".activities.RoomImageDialogActivity"
......
package android.support.v4.app;
/**
* Contains utility method to prevent Loaders from being forcefully retained during a configuration change.
* Forceful retain currently causes all stopped Loaders to briefly start, causing unexpected issues for detached fragments.
* This restores the Loaders behavior of support libraries < 24.0.0 for fragments.
*
* @author Christophe Beyls
* @see <a href="https://issuetracker.google.com/issues/37916599">Bug report</a>
*/
public class SafeLoadersUtils {
public static void onRetainCustomNonConfigurationInstance(FragmentActivity activity) {
// All loaders are already stopped or retained at that point, but calling this method again
// sets a flag to prevent them from being forcefully retained during the next phase
activity.mFragments.doLoaderStop(false);
}
}
\ No newline at end of file
package at.linuxtage.companion;
import android.app.Application;
import android.preference.PreferenceManager;
import androidx.preference.PreferenceManager;
import at.linuxtage.companion.alarms.FosdemAlarmManager;
import at.linuxtage.companion.db.DatabaseManager;
public class GLTApplication extends Application {
......@@ -11,7 +10,6 @@ public class GLTApplication extends Application {
public void onCreate() {
super.onCreate();
DatabaseManager.init(this);
// Initialize settings
PreferenceManager.setDefaultValues(this, R.xml.settings, false);
// Alarms (requires settings)
......
package at.linuxtage.companion.activities;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.support.annotation.IdRes;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StyleRes;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatDelegate;
import android.support.v7.widget.Toolbar;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* A {@link android.preference.PreferenceActivity} which implements and proxies the necessary calls
* to be used with AppCompat.
*/
public class AppCompatPreferenceActivity extends PreferenceActivity {
private AppCompatDelegate mDelegate;
private int mThemeId = 0;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
final AppCompatDelegate delegate = getDelegate();
delegate.installViewFactory();
delegate.onCreate(savedInstanceState);
if (delegate.applyDayNight() && mThemeId != 0) {
// If DayNight has been applied, we need to re-apply the theme for
// the changes to take effect. On API 23+, we should bypass
// setTheme(), which will no-op if the theme ID is identical to the
// current theme ID.
if (Build.VERSION.SDK_INT >= 23) {
onApplyThemeResource(getTheme(), mThemeId, false);
} else {
setTheme(mThemeId);
}
}
super.onCreate(savedInstanceState);
}
@Override
public void setTheme(@StyleRes final int resid) {
super.setTheme(resid);
// Keep hold of the theme id so that we can re-set it later if needed
mThemeId = resid;
}
@Override
protected void onPostCreate(@Nullable Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
getDelegate().onPostCreate(savedInstanceState);
}
@Nullable
public ActionBar getSupportActionBar() {
return getDelegate().getSupportActionBar();
}
public void setSupportActionBar(@Nullable Toolbar toolbar) {
getDelegate().setSupportActionBar(toolbar);
}
@Override
@NonNull
public MenuInflater getMenuInflater() {
return getDelegate().getMenuInflater();
}
@Override
public void setContentView(@LayoutRes int layoutResID) {
getDelegate().setContentView(layoutResID);
}
@Override
public void setContentView(View view) {
getDelegate().setContentView(view);
}
@Override
public void setContentView(View view, ViewGroup.LayoutParams params) {
getDelegate().setContentView(view, params);
}
@Override
public void addContentView(View view, ViewGroup.LayoutParams params) {
getDelegate().addContentView(view, params);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
getDelegate().onConfigurationChanged(newConfig);
}
@Override
protected void onPostResume() {
super.onPostResume();
getDelegate().onPostResume();
}
@Override
protected void onStart() {
super.onStart();
getDelegate().onStart();
}
@Override
protected void onStop() {
super.onStop();
getDelegate().onStop();
}
@Override
@Nullable
public <T extends View> T findViewById(@IdRes int id) {
return getDelegate().findViewById(id);
}
@Override
protected void onDestroy() {
super.onDestroy();
getDelegate().onDestroy();
}
@Override
protected void onTitleChanged(CharSequence title, int color) {
super.onTitleChanged(title, color);
getDelegate().setTitle(title);
}
public boolean supportRequestWindowFeature(int featureId) {
return getDelegate().requestWindowFeature(featureId);
}
@Override
public void invalidateOptionsMenu() {
getDelegate().invalidateOptionsMenu();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
getDelegate().onSaveInstanceState(outState);
}
@NonNull
public AppCompatDelegate getDelegate() {
if (mDelegate == null) {
mDelegate = AppCompatDelegate.create(this, null);
}
return mDelegate;
}
}
\ No newline at end of file
package at.linuxtage.companion.activities;
import android.support.v4.app.SafeLoadersUtils;
import android.support.v7.app.AppCompatActivity;
/**
* Common activity code with fragment loaders fix.
*/
public abstract class BaseActivity extends AppCompatActivity {
@Override
public Object onRetainCustomNonConfigurationInstance() {
// TODO Remove when support-fragment Loaders bug is fixed
SafeLoadersUtils.onRetainCustomNonConfigurationInstance(this);
return super.onRetainCustomNonConfigurationInstance();
}
}
package at.linuxtage.companion.activities;
import android.arch.lifecycle.Observer;
import android.arch.lifecycle.ViewModelProviders;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.nfc.NdefRecord;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.NavUtils;
import android.support.v4.app.TaskStackBuilder;
import android.support.v7.app.ActionBar;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageButton;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import at.linuxtage.companion.R;
import at.linuxtage.companion.fragments.EventDetailsFragment;
import at.linuxtage.companion.model.Event;
import at.linuxtage.companion.model.Track;
import at.linuxtage.companion.utils.NfcUtils;
import at.linuxtage.companion.utils.NfcUtils.CreateNfcAppDataCallback;
import at.linuxtage.companion.utils.ThemeUtils;
import at.linuxtage.companion.viewmodels.BookmarkStatusViewModel;
import at.linuxtage.companion.viewmodels.EventViewModel;
import be.digitalia.fosdem.widgets.BookmarkStatusAdapter;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.bottomappbar.BottomAppBar;
/**
* Displays a single event passed either as a complete Parcelable object in extras or as an id in data.
*
* @author Christophe Beyls
*/
public class EventDetailsActivity extends BaseActivity implements Observer<Event>, CreateNfcAppDataCallback {
public class EventDetailsActivity extends AppCompatActivity implements Observer<Event>, CreateNfcAppDataCallback {
public static final String EXTRA_EVENT = "event";
private AppBarLayout appBarLayout;
private Toolbar toolbar;
private BottomAppBar bottomAppBar;
private BookmarkStatusViewModel bookmarkStatusViewModel;
private Event event;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.content);
setContentView(R.layout.single_event);
appBarLayout = findViewById(R.id.appbar);
toolbar = findViewById(R.id.toolbar);
bottomAppBar = findViewById(R.id.bottom_appbar);
setSupportActionBar(bottomAppBar);
ActionBar bar = getSupportActionBar();
bar.setDisplayHomeAsUpEnabled(false);
bar.setDisplayShowTitleEnabled(false);
ImageButton floatingActionButton = findViewById(R.id.fab);
bookmarkStatusViewModel = ViewModelProviders.of(this).get(BookmarkStatusViewModel.class);
BookmarkStatusAdapter.setupWithImageButton(bookmarkStatusViewModel, this, floatingActionButton);
Event event = getIntent().getParcelableExtra(EXTRA_EVENT);
......@@ -59,7 +75,7 @@ public class EventDetailsActivity extends BaseActivity implements Observer<Event
String eventIdString;
if (NfcUtils.hasAppData(intent)) {
// NFC intent
eventIdString = new String(NfcUtils.extractAppData(intent));
eventIdString = NfcUtils.toEventIdString((NfcUtils.extractAppData(intent)));
} else {
// Normal in-app intent
eventIdString = intent.getDataString();
......@@ -94,42 +110,51 @@ public class EventDetailsActivity extends BaseActivity implements Observer<Event
private void initEvent(@NonNull Event event) {
this.event = event;
// Enable up navigation only after getting the event details
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
ThemeUtils.setActionBarTrackColor(this, event.getTrack().getType());
toolbar.setNavigationIcon(R.drawable.abc_ic_ab_back_material);
toolbar.setNavigationContentDescription(R.string.abc_action_bar_up_description);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onSupportNavigateUp();
}
});
final Track.Type trackType = event.getTrack().getType();
ThemeUtils.setStatusBarTrackColor(this, trackType);
final ColorStateList trackColor = ContextCompat.getColorStateList(this, trackType.getColorResId());
appBarLayout.setBackgroundColor(trackColor.getDefaultColor());