KVV as a service to connect SyncAdapter with MainActivity

This commit is contained in:
Caesar2011
2019-02-09 01:14:20 +01:00
parent 28e99f1fa5
commit 489212c26a
16 changed files with 434 additions and 232 deletions

View File

@@ -80,6 +80,13 @@
android:name="android.content.SyncAdapter" android:name="android.content.SyncAdapter"
android:resource="@xml/syncadapter_kvv" /> android:resource="@xml/syncadapter_kvv" />
</service> </service>
<service
android:name=".services.kvv.KVV"
android:exported="false">
<intent-filter>
<action android:name="android.app.Service" />
</intent-filter>
</service>
</application> </application>

View File

@@ -2,9 +2,13 @@ package de.sebse.fuplanner;
import android.accounts.Account; import android.accounts.Account;
import android.accounts.AccountManager; import android.accounts.AccountManager;
import android.content.ComponentName;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle; import android.os.Bundle;
import android.os.IBinder;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
@@ -16,6 +20,7 @@ import com.google.android.material.navigation.NavigationView;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Locale; import java.util.Locale;
@@ -80,12 +85,40 @@ public class MainActivity extends AppCompatActivity
private static final int DOUBLE_CLICK_TO_EXIT_MILLIS = 2000; private static final int DOUBLE_CLICK_TO_EXIT_MILLIS = 2000;
private FragmentManager mFragmentManager; private FragmentManager mFragmentManager;
private KVV mKVV;
private NewsManager mNewsManager; private NewsManager mNewsManager;
private CanteenBrowser mCanteenBrowser; private CanteenBrowser mCanteenBrowser;
private final Logger log = new Logger(this); private final Logger log = new Logger(this);
private NavigationView mNavigationView; private NavigationView mNavigationView;
// KVV service
private ArrayList<KVVCallback> mCallbacks = new ArrayList<>();
private KVV mKVV;
boolean mBound = false;
/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className,
IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
KVV.LocalBinder binder = (KVV.LocalBinder) service;
mKVV = binder.getService();
mKVV.addListener("mainactivity", MainActivity.this);
for (KVVCallback callback : mCallbacks) {
callback.get(mKVV);
}
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
mKVV.removeListener("mainactivity");
mBound = false;
}
};
private int mFragmentPage = FRAGMENT_NONE; private int mFragmentPage = FRAGMENT_NONE;
@NotNull @NotNull
private String mFragmentData = ""; private String mFragmentData = "";
@@ -146,12 +179,14 @@ public class MainActivity extends AppCompatActivity
changeFragment(FRAGMENT_STARTUP); changeFragment(FRAGMENT_STARTUP);
int targetPage = desiredPage; int targetPage = desiredPage;
String targetData = desiredData; String targetData = desiredData;
getKVV().account().restoreOnlineLogin(restoreResult -> { getKVV(kvv -> {
updateNavigation(); kvv.account().restoreOnlineLogin(restoreResult -> {
if (restoreResult != Login.RESTORE_STATUS_INVALID_PASSWORD) updateNavigation();
changeFragment(targetPage, targetData); if (restoreResult != Login.RESTORE_STATUS_INVALID_PASSWORD)
else changeFragment(targetPage, targetData);
changeFragment(getDefaultFragmentAfterLogout()); else
changeFragment(getDefaultFragmentAfterLogout());
});
}); });
} }
@@ -168,6 +203,21 @@ public class MainActivity extends AppCompatActivity
}, log::e);*/ }, log::e);*/
} }
@Override
protected void onStart() {
super.onStart();
Intent intent = new Intent(this, KVV.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
mKVV.removeListener("mainactivity");
unbindService(mConnection);
mBound = false;
}
@Override @Override
protected void onNewIntent(Intent intent) { protected void onNewIntent(Intent intent) {
super.onNewIntent(intent); super.onNewIntent(intent);
@@ -184,24 +234,26 @@ public class MainActivity extends AppCompatActivity
protected void onPause() { protected void onPause() {
super.onPause(); super.onPause();
isPaused = true; isPaused = true;
isLoggedInBeforePause = getKVV().account().isLoggedIn(); getKVV(kvv -> isLoggedInBeforePause = kvv.account().isLoggedIn());
} }
@Override @Override
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
if (isPaused) { if (isPaused) {
getKVV().account().restoreOnlineLogin(restoreResult -> { getKVV(kvv -> {
updateNavigation(); kvv.account().restoreOnlineLogin(restoreResult -> {
if (restoreResult == Login.RESTORE_STATUS_SUCCESS && !isLoggedInBeforePause) { updateNavigation();
changeFragment(getDefaultFragmentAfterLogin()); if (restoreResult == Login.RESTORE_STATUS_SUCCESS && !isLoggedInBeforePause) {
registerSync(true); changeFragment(getDefaultFragmentAfterLogin());
} else if (restoreResult == Login.RESTORE_STATUS_INVALID_PASSWORD && isLoggedInBeforePause) { registerSync(true);
getKVV().account().logout(false); } else if (restoreResult == Login.RESTORE_STATUS_INVALID_PASSWORD && isLoggedInBeforePause) {
changeFragment(getDefaultFragmentAfterLogout()); kvv.account().logout(false);
} changeFragment(getDefaultFragmentAfterLogout());
}
});
kvv.modules().list().reloadIfOutdated();
}); });
getKVV().modules().list().reloadIfOutdated();
} }
isPaused = false; isPaused = false;
} }
@@ -217,27 +269,29 @@ public class MainActivity extends AppCompatActivity
if (drawer.isDrawerOpen(GravityCompat.START) && !isDrawerFixed) { if (drawer.isDrawerOpen(GravityCompat.START) && !isDrawerFixed) {
drawer.closeDrawer(GravityCompat.START); drawer.closeDrawer(GravityCompat.START);
} else { } else {
if (mFragmentPage == FRAGMENT_MODULES_DETAILS) { getKVV(kvv -> {
ModDetailFragment fragment = (ModDetailFragment) mFragmentManager.findFragmentByTag(String.valueOf(FRAGMENT_MODULES_DETAILS)); if (mFragmentPage == FRAGMENT_MODULES_DETAILS) {
if (fragment != null && fragment.isVisible() && Regex.has("\\.[1-9][0-9]*", fragment.getData())) { ModDetailFragment fragment = (ModDetailFragment) mFragmentManager.findFragmentByTag(String.valueOf(FRAGMENT_MODULES_DETAILS));
fragment.gotoFragmentPart(0, -1); if (fragment != null && fragment.isVisible() && Regex.has("\\.[1-9][0-9]*", fragment.getData())) {
fragment.gotoFragmentPart(0, -1);
} else {
changeFragment(FRAGMENT_MODULES);
}
} else if (mFragmentPage == FRAGMENT_CANTEENS_DETAILS) {
DaySwitcherFragment fragment = (DaySwitcherFragment) mFragmentManager.findFragmentByTag(String.valueOf(FRAGMENT_CANTEENS_DETAILS));
if (fragment != null && fragment.isVisible() && Regex.has("\\.[1-9][0-9]*", fragment.getData())) {
fragment.gotoFragmentPart(0);
} else {
changeFragment(FRAGMENT_CANTEENS);
}
} else if (kvv.account().isLoggedIn() && mFragmentPage != getDefaultFragmentAfterLogin()) {
changeFragment(getDefaultFragmentAfterLogin());
} else { } else {
changeFragment(FRAGMENT_MODULES); mDoubleBackToExitPressedOnce = System.currentTimeMillis();
showToast(R.string.back_to_exit);
//getTokenForAccountCreateIfNeeded(AccountGeneral.ACCOUNT_TYPE, AccountGeneral.AUTHTOKEN_TYPE_KVV);
} }
} else if (mFragmentPage == FRAGMENT_CANTEENS_DETAILS) { });
DaySwitcherFragment fragment = (DaySwitcherFragment) mFragmentManager.findFragmentByTag(String.valueOf(FRAGMENT_CANTEENS_DETAILS));
if (fragment != null && fragment.isVisible() && Regex.has("\\.[1-9][0-9]*", fragment.getData())) {
fragment.gotoFragmentPart(0);
} else {
changeFragment(FRAGMENT_CANTEENS);
}
} else if (getKVV().account().isLoggedIn() && mFragmentPage != getDefaultFragmentAfterLogin()) {
changeFragment(getDefaultFragmentAfterLogin());
} else {
mDoubleBackToExitPressedOnce = System.currentTimeMillis();
showToast(R.string.back_to_exit);
//getTokenForAccountCreateIfNeeded(AccountGeneral.ACCOUNT_TYPE, AccountGeneral.AUTHTOKEN_TYPE_KVV);
}
} }
} }
@@ -304,8 +358,10 @@ public class MainActivity extends AppCompatActivity
startActivity(sendIntent); startActivity(sendIntent);
break; break;
case R.id.nav_logout: case R.id.nav_logout:
getKVV().account().logout(true); getKVV(kvv -> {
getKVV().modules().list().delete(); kvv.account().logout(true);
kvv.modules().list().delete();
});
break; break;
} }
@@ -357,11 +413,12 @@ public class MainActivity extends AppCompatActivity
return this.mNewsManager; return this.mNewsManager;
} }
public KVV getKVV() { public void getKVV(KVVCallback callback) {
if (this.mKVV == null) { if (this.mKVV == null) {
this.mKVV = new KVV(this, this); mCallbacks.add(callback);
} else {
callback.get(this.mKVV);
} }
return this.mKVV;
} }
public CanteenBrowser getCanteenBrowser() { public CanteenBrowser getCanteenBrowser() {
@@ -484,18 +541,21 @@ public class MainActivity extends AppCompatActivity
moduleId = moduleId.substring(0, dotPos); moduleId = moduleId.substring(0, dotPos);
switch (mFragmentPage) { switch (mFragmentPage) {
case FRAGMENT_MODULES_DETAILS: case FRAGMENT_MODULES_DETAILS:
getKVV().modules().list().find(moduleId, success -> { String finalModuleId = moduleId;
int size = mNavigationView.getMenu().size(); getKVV(kvv -> {
//noinspection ConstantConditions kvv.modules().list().find(finalModuleId, success -> {
String title = success == null ? null : success.title; int size = mNavigationView.getMenu().size();
for (int k = 0; k < size; k++) { //noinspection ConstantConditions
MenuItem menuItem = mNavigationView.getMenu().getItem(k); String title = success == null ? null : success.title;
if (menuItem.getTitle().equals(title)) { for (int k = 0; k < size; k++) {
menuItem.setChecked(true); MenuItem menuItem = mNavigationView.getMenu().getItem(k);
break; if (menuItem.getTitle().equals(title)) {
menuItem.setChecked(true);
break;
}
} }
} }, log::e);
}, log::e); });
return; return;
case FRAGMENT_MODULES: case FRAGMENT_MODULES:
item = mNavigationView.getMenu().findItem(R.id.nav_modules); item = mNavigationView.getMenu().findItem(R.id.nav_modules);
@@ -561,21 +621,23 @@ public class MainActivity extends AppCompatActivity
int MAX_COUNT = isLoggedIn ? 3 : 2; int MAX_COUNT = isLoggedIn ? 3 : 2;
final int[] count = {0}; final int[] count = {0};
if (isLoggedIn) { if (isLoggedIn) {
getKVV().modules().list().recv(success -> { getKVV(kvv -> {
int i = 0; kvv.modules().list().recv(success -> {
for (Iterator<Modules.Module> it = success.latestSemesterIterator(); it.hasNext(); ) { int i = 0;
Modules.Module module = it.next(); for (Iterator<Modules.Module> it = success.latestSemesterIterator(); it.hasNext(); ) {
MenuItem menuItem = mNavigationView.getMenu().add(Menu.NONE, Menu.NONE, 101 + i, module.title); Modules.Module module = it.next();
menuItem.setOnMenuItemClickListener(item -> { MenuItem menuItem = mNavigationView.getMenu().add(Menu.NONE, Menu.NONE, 101 + i, module.title);
onModulesFragmentInteraction(module.getID()); menuItem.setOnMenuItemClickListener(item -> {
return false; onModulesFragmentInteraction(module.getID());
}); return false;
i++; });
} i++;
if (++count[0] == MAX_COUNT) done.run(); }
}, error -> { if (++count[0] == MAX_COUNT) done.run();
if (++count[0] == MAX_COUNT) done.run(); }, error -> {
log.e(error); if (++count[0] == MAX_COUNT) done.run();
log.e(error);
});
}); });
} }
getCanteenBrowser().getCanteens(success -> { getCanteenBrowser().getCanteens(success -> {
@@ -616,16 +678,18 @@ public class MainActivity extends AppCompatActivity
private void updateNavigation() { private void updateNavigation() {
mQueue.add(() -> { mQueue.add(() -> {
boolean isLoggedIn = getKVV().account().isLoggedIn(); getKVV(kvv -> {
setNavigationHeader(isLoggedIn); boolean isLoggedIn = kvv.account().isLoggedIn();
mNavigationView.getMenu().clear(); setNavigationHeader(isLoggedIn);
if (isLoggedIn) mNavigationView.getMenu().clear();
mNavigationView.inflateMenu(R.menu.activity_main_drawer_login); if (isLoggedIn)
else mNavigationView.inflateMenu(R.menu.activity_main_drawer_login);
mNavigationView.inflateMenu(R.menu.activity_main_drawer); else
afterAnyMenuInflate(isLoggedIn, () -> { mNavigationView.inflateMenu(R.menu.activity_main_drawer);
setNavigationSelection(); afterAnyMenuInflate(isLoggedIn, () -> {
mQueue.next(); setNavigationSelection();
mQueue.next();
});
}); });
}); });
} }
@@ -722,4 +786,8 @@ public class MainActivity extends AppCompatActivity
public CustomAccountManager getAccountManager() { public CustomAccountManager getAccountManager() {
return mAccountManager; return mAccountManager;
} }
public interface KVVCallback {
void get(KVV kvv);
}
} }

View File

@@ -66,15 +66,15 @@ public class ModulesFragment extends Fragment {
private void refresh(boolean forceRefresh) { private void refresh(boolean forceRefresh) {
if (mMainActivityListener != null) { if (mMainActivityListener != null) {
mMainActivityListener.getKVV().modules().list().recv(success -> { mMainActivityListener.getKVV(kvv -> {
adapter.setModules(success); kvv.modules().list().recv(success -> {
//if (mMainActivityListener != null) adapter.setModules(success);
// mMainActivityListener.refreshNavigation(); swipeLayout.setRefreshing(false);
swipeLayout.setRefreshing(false); }, error -> {
}, error -> { log.e(error.toString());
log.e(error.toString()); swipeLayout.setRefreshing(false);
swipeLayout.setRefreshing(false); }, forceRefresh);
}, forceRefresh); });
} }
} }

View File

@@ -64,23 +64,25 @@ public class ScheduleFragment extends Fragment implements
public void invalidate(boolean forceRefresh) { public void invalidate(boolean forceRefresh) {
if (mListener == null) return; if (mListener == null) return;
mListener.getKVV().modules().list().recv(modules -> { mListener.getKVV(kvv -> {
mModules = modules; kvv.modules().list().recv(modules -> {
final int[] i = {0}; mModules = modules;
Iterator<Modules.Module> iter = mModules.latestSemesterIterator(); final int[] i = {0};
while (iter.hasNext()) { Iterator<Modules.Module> iter = mModules.latestSemesterIterator();
Modules.Module module = iter.next(); while (iter.hasNext()) {
mListener.getKVV().modules().events().recv(module, success1 -> { Modules.Module module = iter.next();
i[0]++; kvv.modules().events().recv(module, success1 -> {
if (i[0] >= mModules.size()) { i[0]++;
if (mWeekView != null) { if (i[0] >= mModules.size()) {
mWeekView.invalidate(); if (mWeekView != null) {
mWeekView.notifyDatasetChanged(); mWeekView.invalidate();
mWeekView.notifyDatasetChanged();
}
} }
} }, log::e, forceRefresh);
}, log::e, forceRefresh); }
} }, log::e, forceRefresh);
}, log::e, forceRefresh); });
} }
@Override @Override
@@ -187,20 +189,22 @@ public class ScheduleFragment extends Fragment implements
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext()); AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext());
if (mListener == null) return; if (mListener == null) return;
mListener.getKVV().modules().list().find(moduleId, module -> { mListener.getKVV(kvv -> {
String moduleName = module.title; kvv.modules().list().find(moduleId, module -> {
alertDialogBuilder String moduleName = module.title;
.setTitle(event.getName()) alertDialogBuilder
.setMessage( .setTitle(event.getName())
getResources().getString(R.string.module_name, moduleName) + "\n" + .setMessage(
getResources().getString(R.string.location_name, event.getLocation()) + "\n" + getResources().getString(R.string.module_name, moduleName) + "\n" +
getResources().getString(R.string.date_scale, UtilsDate.getModifiedTime(getContext(), event.getStartTime().getTimeInMillis()), UtilsDate.getModifiedTime(getContext(), event.getEndTime().getTimeInMillis()+1)) getResources().getString(R.string.location_name, event.getLocation()) + "\n" +
) getResources().getString(R.string.date_scale, UtilsDate.getModifiedTime(getContext(), event.getStartTime().getTimeInMillis()), UtilsDate.getModifiedTime(getContext(), event.getEndTime().getTimeInMillis()+1))
.setCancelable(true) )
.setNeutralButton(R.string.close, (dialog, id) -> dialog.cancel()); .setCancelable(true)
.setNeutralButton(R.string.close, (dialog, id) -> dialog.cancel());
AlertDialog alertDialog = alertDialogBuilder.create(); AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show(); alertDialog.show();
}, log::e); }, log::e);
});
} }
} }

View File

@@ -82,27 +82,31 @@ public class ModDetailAnnounceFragment extends Fragment implements Download.OnDo
} }
private void refresh(boolean forceRefresh) { private void refresh(boolean forceRefresh) {
if (mListener == null) if (mListener != null) {
return; mListener.getKVV(kvv -> {
mListener.getKVV().modules().details().recv(mItemPos, pair -> { kvv.modules().details().recv(mItemPos, pair -> {
adapter.setModule(pair.first); adapter.setModule(pair.first);
if (pair.second) if (pair.second)
swipeLayout.setRefreshing(false); swipeLayout.setRefreshing(false);
}, error -> { }, error -> {
swipeLayout.setRefreshing(false); swipeLayout.setRefreshing(false);
log.e(error); log.e(error);
}, forceRefresh); }, forceRefresh);
});
}
} }
@Override @Override
public void request(String title, String url) { public void request(String title, String url) {
if (mListener == null) if (mListener == null)
return; return;
mListener.getKVV().modules().list().find(mItemPos, (Modules.Module module) -> { mListener.getKVV(kvv -> {
String folderName = "FU-"+module.title.replaceAll("[:*<>|/\"\\\\]", "-"); kvv.modules().list().find(mItemPos, (Modules.Module module) -> {
folderName += "/Announcement"; String folderName = "FU-"+module.title.replaceAll("[:*<>|/\"\\\\]", "-");
getDownload().openDownloadDialog(title, url, folderName); folderName += "/Announcement";
}, log::e); getDownload().openDownloadDialog(title, url, folderName);
}, log::e);
});
} }
@Override @Override

View File

@@ -82,27 +82,31 @@ public class ModDetailAssignmentFragment extends Fragment implements Download.On
} }
private void refresh(boolean forceRefresh) { private void refresh(boolean forceRefresh) {
if (mListener == null) if (mListener != null) {
return; mListener.getKVV(kvv -> {
mListener.getKVV().modules().details().recv(mItemPos, pair -> { kvv.modules().details().recv(mItemPos, pair -> {
adapter.setModule(pair.first); adapter.setModule(pair.first);
if (pair.second) if (pair.second)
swipeLayout.setRefreshing(false); swipeLayout.setRefreshing(false);
}, error -> { }, error -> {
swipeLayout.setRefreshing(false); swipeLayout.setRefreshing(false);
log.e(error); log.e(error);
}, forceRefresh); }, forceRefresh);
});
}
} }
@Override @Override
public void request(String title, String url) { public void request(String title, String url) {
if (mListener == null) if (mListener == null)
return; return;
mListener.getKVV().modules().list().find(mItemPos, (Modules.Module module) -> { mListener.getKVV(kvv -> {
String folderName = "FU-"+module.title.replaceAll("[:*<>|/\"\\\\]", "-"); kvv.modules().list().find(mItemPos, (Modules.Module module) -> {
folderName += "/Assignment"; String folderName = "FU-"+module.title.replaceAll("[:*<>|/\"\\\\]", "-");
getDownload().openDownloadDialog(title, url, folderName); folderName += "/Announcement";
}, log::e); getDownload().openDownloadDialog(title, url, folderName);
}, log::e);
});
} }
@Override @Override

View File

@@ -81,16 +81,18 @@ public class ModDetailEventFragment extends Fragment {
} }
private void refresh(boolean forceRefresh) { private void refresh(boolean forceRefresh) {
if (mListener == null) if (mListener != null) {
return; mListener.getKVV(kvv -> {
mListener.getKVV().modules().details().recv(mItemPos, pair -> { kvv.modules().details().recv(mItemPos, pair -> {
adapter.setModule(pair.first); adapter.setModule(pair.first);
if (pair.second) if (pair.second)
swipeLayout.setRefreshing(false); swipeLayout.setRefreshing(false);
}, error -> { }, error -> {
swipeLayout.setRefreshing(false); swipeLayout.setRefreshing(false);
log.e(error); log.e(error);
}, forceRefresh); }, forceRefresh);
});
}
} }
@Override @Override

View File

@@ -72,11 +72,13 @@ public class ModDetailFragment extends Fragment implements ModDetailListener {
} }
if (mListener != null) { if (mListener != null) {
mListener.onTitleTextChange(R.string.courses); mListener.onTitleTextChange(R.string.courses);
mListener.getKVV().modules().list().recv(success -> { mListener.getKVV(kvv -> {
Modules.Module module = success.get(mItemPos); kvv.modules().list().recv(success -> {
if (mListener != null && module != null) Modules.Module module = success.get(mItemPos);
mListener.onTitleTextChange(module.title); if (mListener != null && module != null)
}, log::e); mListener.onTitleTextChange(module.title);
}, log::e);
});
} }
} }

View File

@@ -81,16 +81,18 @@ public class ModDetailGradebookFragment extends Fragment {
} }
private void refresh(boolean forceRefresh) { private void refresh(boolean forceRefresh) {
if (mListener == null) if (mListener != null) {
return; mListener.getKVV(kvv -> {
mListener.getKVV().modules().details().recv(mItemPos, pair -> { kvv.modules().details().recv(mItemPos, pair -> {
adapter.setModule(pair.first); adapter.setModule(pair.first);
if (pair.second) if (pair.second)
swipeLayout.setRefreshing(false); swipeLayout.setRefreshing(false);
}, error -> { }, error -> {
swipeLayout.setRefreshing(false); swipeLayout.setRefreshing(false);
log.e(error); log.e(error);
}, forceRefresh); }, forceRefresh);
});
}
} }
@Override @Override

View File

@@ -86,14 +86,16 @@ public class ModDetailOverviewFragment extends Fragment {
private void refresh(boolean forceRefresh) { private void refresh(boolean forceRefresh) {
if (mListener != null) { if (mListener != null) {
mListener.getKVV().modules().details().recv(mItemPos, pair -> { mListener.getKVV(kvv -> {
adapter.setModule(pair.first); kvv.modules().details().recv(mItemPos, pair -> {
if (pair.second) adapter.setModule(pair.first);
if (pair.second)
swipeLayout.setRefreshing(false);
}, error -> {
swipeLayout.setRefreshing(false); swipeLayout.setRefreshing(false);
}, error -> { log.e(error);
swipeLayout.setRefreshing(false); }, forceRefresh);
log.e(error); });
}, forceRefresh);
} }
} }

View File

@@ -90,11 +90,13 @@ public class ModDetailResourceFragment extends Fragment implements Download.OnDo
// Update and toggle the node. // Update and toggle the node.
onToggle(!node.isExpand(), holder); onToggle(!node.isExpand(), holder);
} else if (node.getContent() instanceof Resource.File && ModDetailResourceFragment.this.mListener != null) { // if leaf is file } else if (node.getContent() instanceof Resource.File && ModDetailResourceFragment.this.mListener != null) { // if leaf is file
ModDetailResourceFragment.this.mListener.getKVV().modules().resources().recv(mItemPos, (Modules.Module module) -> { ModDetailResourceFragment.this.mListener.getKVV(kvv -> {
String folderName = "FU-"+module.title.replaceAll("[:*<>|/\"\\\\]", "-"); kvv.modules().resources().recv(mItemPos, (Modules.Module module) -> {
Resource.File file = (Resource.File) node.getContent(); String folderName = "FU-"+module.title.replaceAll("[:*<>|/\"\\\\]", "-");
getDownload().openDownloadDialog(file, folderName); Resource.File file = (Resource.File) node.getContent();
}, log::e); getDownload().openDownloadDialog(file, folderName);
}, log::e);
});
} }
return false; return false;
} }
@@ -123,11 +125,13 @@ public class ModDetailResourceFragment extends Fragment implements Download.OnDo
public void request(String title, String url) { public void request(String title, String url) {
if (mListener == null) if (mListener == null)
return; return;
mListener.getKVV().modules().list().find(mItemPos, (Modules.Module module) -> { mListener.getKVV(kvv -> {
String folderName = "FU-"+module.title.replaceAll("[:*<>|/\"\\\\]", "-"); kvv.modules().list().find(mItemPos, (Modules.Module module) -> {
folderName += "/Announcement"; String folderName = "FU-"+module.title.replaceAll("[:*<>|/\"\\\\]", "-");
getDownload().openDownloadDialog(title, url, folderName); folderName += "/Announcement";
}, log::e); getDownload().openDownloadDialog(title, url, folderName);
}, log::e);
});
} }
@Override @Override
@@ -150,16 +154,18 @@ public class ModDetailResourceFragment extends Fragment implements Download.OnDo
} }
private void refresh(boolean forceRefresh) { private void refresh(boolean forceRefresh) {
if (mListener == null) if (mListener != null) {
return; mListener.getKVV(kvv -> {
mListener.getKVV().modules().details().recv(mItemPos, pair -> { kvv.modules().details().recv(mItemPos, pair -> {
adapter.setModule(pair.first); adapter.setModule(pair.first);
if (pair.second) if (pair.second)
swipeLayout.setRefreshing(false); swipeLayout.setRefreshing(false);
}, error -> { }, error -> {
swipeLayout.setRefreshing(false); swipeLayout.setRefreshing(false);
log.e(error); log.e(error);
}, forceRefresh); }, forceRefresh);
});
}
} }
private Download getDownload() { private Download getDownload() {

View File

@@ -1,31 +1,98 @@
package de.sebse.fuplanner.services.kvv; package de.sebse.fuplanner.services.kvv;
import android.accounts.AccountManager;
import android.app.Service;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import com.android.volley.NetworkResponse;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
public class KVV { import de.sebse.fuplanner.services.kvv.types.LoginTokenKVV;
private final HashMap<String, Object> addons = new HashMap<>(); import de.sebse.fuplanner.tools.CustomAccountManager;
private final KVVListener mListener;
private final Context mContext;
public KVV(KVVListener listener, Context context) { public class KVV extends Service {
this.mListener = listener; private final HashMap<String, Object> addons = new HashMap<>();
this.mContext = context; private final HashMap<String, KVVListener> mListeners = new HashMap<>();
} private final KVVListener mListener = new KVVListener() {
CustomAccountManager accountManager = null;
@Override
public CustomAccountManager getAccountManager() {
if (accountManager == null)
accountManager = new CustomAccountManager(AccountManager.get(KVV.this.getApplicationContext()), () -> null);
return accountManager;
}
@Override
public void onKVVNetworkResponse(NetworkResponse error) {
for (KVVListener listener : mListeners.values())
listener.onKVVNetworkResponse(error);
}
@Override
public void onLogin(LoginTokenKVV token, boolean isOnlyRefresh) {
for (KVVListener listener : mListeners.values())
listener.onLogin(token, isOnlyRefresh);
}
@Override
public void onLogout() {
for (KVVListener listener : mListeners.values())
listener.onLogout();
}
@Override
public void onModuleListChange() {
for (KVVListener listener : mListeners.values())
listener.onModuleListChange();
}
};
// Binder given to clients
private final IBinder mBinder = new LocalBinder();
@NotNull @NotNull
public Login account() { public Login account() {
return (Login) addAndGet("account", () -> new Login(mListener, mContext)); return (Login) addAndGet("account", () -> new Login(mListener, getApplicationContext()));
} }
@NotNull @NotNull
public Modules modules() { public Modules modules() {
return (Modules) addAndGet("module", () -> new Modules(account(), mListener, mContext)); return (Modules) addAndGet("module", () -> new Modules(account(), mListener, getApplicationContext()));
} }
public void addListener(String key, KVVListener listener) {
mListeners.put(key, listener);
}
public void removeListener(String key) {
mListeners.remove(key);
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
/**
* Class used for the client Binder. Because we know this service always
* runs in the same process as its clients, we don't need to deal with IPC.
*/
public class LocalBinder extends Binder {
public KVV getService() {
// Return this instance of LocalService so clients can call public methods
return KVV.this;
}
}

View File

@@ -3,10 +3,14 @@ package de.sebse.fuplanner.services.kvv.sync;
import android.accounts.Account; import android.accounts.Account;
import android.accounts.AccountManager; import android.accounts.AccountManager;
import android.content.AbstractThreadedSyncAdapter; import android.content.AbstractThreadedSyncAdapter;
import android.content.ComponentName;
import android.content.ContentProviderClient; import android.content.ContentProviderClient;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SyncResult; import android.content.SyncResult;
import android.os.Bundle; import android.os.Bundle;
import android.os.IBinder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
@@ -36,6 +40,26 @@ public class KVVSyncAdapter extends AbstractThreadedSyncAdapter {
private Logger log = new Logger(this); private Logger log = new Logger(this);
private NewAsyncQueue mQueue = new NewAsyncQueue(); private NewAsyncQueue mQueue = new NewAsyncQueue();
boolean mBound = false;
boolean mWaitForBound = false;
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
KVV.LocalBinder binder = (KVV.LocalBinder) service;
mKVV = binder.getService();
if (mWaitForBound) mQueue.next();
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
/** /**
* Set up the sync adapter * Set up the sync adapter
*/ */
@@ -57,15 +81,13 @@ public class KVVSyncAdapter extends AbstractThreadedSyncAdapter {
} }
private void init(Context context) { private void init(Context context) {
mKVV = new KVV(new KVVListener() { // Bind to LocalService
CustomAccountManager accountManager = null; Intent intent = new Intent(getContext(), KVV.class);
@Override getContext().bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
public CustomAccountManager getAccountManager() { if (!mBound) {
if (accountManager == null) mWaitForBound = true;
accountManager = new CustomAccountManager(AccountManager.get(context), () -> null); mQueue.add(() -> {});
return accountManager; }
}
}, context);
mQueue.add(() -> { mQueue.add(() -> {
mKVV.account().restoreOnlineLogin(bool -> { mKVV.account().restoreOnlineLogin(bool -> {
mQueue.next(); mQueue.next();

View File

@@ -104,20 +104,22 @@ public class Download {
showDownloadError(); showDownloadError();
return; return;
} }
activity.getKVV().modules().resources().file(file.getTitle(), file.getUrl(), folderName, success -> { activity.getKVV(kvv -> {
Context context = contextInterface.get(); kvv.modules().resources().file(file.getTitle(), file.getUrl(), folderName, success -> {
if (success.equals("") || context== null) { Context context = contextInterface.get();
showDownloadError(); if (success.equals("") || context== null) {
} else { showDownloadError();
if (Regex.has("^http", success)){ } else {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(success)); if (Regex.has("^http", success)){
context.startActivity(intent); Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(success));
context.startActivity(intent);
}
else {
fileOpen(new File(success));
}
} }
else { }, log::e, downloadNew);
fileOpen(new File(success)); });
}
}
}, log::e, downloadNew);
} }
private void showDownloadError() { private void showDownloadError() {

View File

@@ -2,8 +2,10 @@ package de.sebse.fuplanner.tools;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
import de.sebse.fuplanner.MainActivity;
import de.sebse.fuplanner.services.canteen.CanteenBrowser; import de.sebse.fuplanner.services.canteen.CanteenBrowser;
import de.sebse.fuplanner.services.kvv.KVV; import de.sebse.fuplanner.services.kvv.KVV;
import de.sebse.fuplanner.services.kvv.KVVListener;
import de.sebse.fuplanner.services.news.NewsManager; import de.sebse.fuplanner.services.news.NewsManager;
public interface MainActivityListener { public interface MainActivityListener {
@@ -15,7 +17,7 @@ public interface MainActivityListener {
void showToast(@StringRes int msgStringRes); void showToast(@StringRes int msgStringRes);
KVV getKVV(); void getKVV(MainActivity.KVVCallback kvv);
CanteenBrowser getCanteenBrowser(); CanteenBrowser getCanteenBrowser();

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
android:contentAuthority="de.sebse.fuplanner.contentprovider.kvv.modules"
android:accountType="de.sebse.fuplanner.fuauth"
android:userVisible="true"
android:allowParallelSyncs="false"
android:isAlwaysSyncable="true"
android:supportsUploading="false"/>