Java tutorial
/** * Copyright (C) 2013 by Raphael Michel under the MIT license: * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the Software * is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ package de.geeksfactory.opacclient.frontend; import android.annotation.SuppressLint; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.preference.PreferenceManager; import android.support.v4.app.ActivityCompat; import android.support.v4.app.ActivityOptionsCompat; import android.support.v4.app.Fragment; import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.app.AlertDialog; import android.text.Html; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.ScrollView; import android.widget.TextView; import android.widget.Toast; import com.nineoldandroids.animation.Animator; import com.nineoldandroids.animation.ObjectAnimator; import com.nineoldandroids.view.ViewHelper; import org.apache.http.NoHttpResponseException; import org.joda.time.Days; import org.joda.time.LocalDate; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; import org.json.JSONException; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import de.geeksfactory.opacclient.OpacClient; import de.geeksfactory.opacclient.R; import de.geeksfactory.opacclient.apis.EbookServiceApi; import de.geeksfactory.opacclient.apis.EbookServiceApi.BookingResult; import de.geeksfactory.opacclient.apis.OpacApi; import de.geeksfactory.opacclient.apis.OpacApi.CancelResult; import de.geeksfactory.opacclient.apis.OpacApi.MultiStepResult; import de.geeksfactory.opacclient.apis.OpacApi.OpacErrorException; import de.geeksfactory.opacclient.apis.OpacApi.ProlongAllResult; import de.geeksfactory.opacclient.apis.OpacApi.ProlongResult; import de.geeksfactory.opacclient.apis.OpacApi.ReservationResult; import de.geeksfactory.opacclient.frontend.MultiStepResultHelper.Callback; import de.geeksfactory.opacclient.frontend.MultiStepResultHelper.StepTask; import de.geeksfactory.opacclient.frontend.OpacActivity.AccountSelectedListener; import de.geeksfactory.opacclient.networking.NotReachableException; import de.geeksfactory.opacclient.networking.SSLSecurityException; import de.geeksfactory.opacclient.objects.Account; import de.geeksfactory.opacclient.objects.AccountData; import de.geeksfactory.opacclient.objects.DetailledItem; import de.geeksfactory.opacclient.objects.LentItem; import de.geeksfactory.opacclient.objects.Library; import de.geeksfactory.opacclient.objects.ReservedItem; import de.geeksfactory.opacclient.reminder.ReminderHelper; import de.geeksfactory.opacclient.reminder.SyncAccountAlarmListener; import de.geeksfactory.opacclient.storage.AccountDataSource; import de.geeksfactory.opacclient.ui.AppCompatProgressDialog; import de.geeksfactory.opacclient.ui.ExpandingCardListManager; import de.geeksfactory.opacclient.utils.ErrorReporter; public class AccountFragment extends Fragment implements AccountSelectedListener { public static final long MAX_CACHE_AGE = (1000 * 3600 * 2); protected AppCompatProgressDialog dialog; protected AlertDialog adialog; protected OpacClient app; protected View view; protected ScrollView svAccount; protected FrameLayout errorView; protected View unsupportedErrorView, answerErrorView; protected SwipeRefreshLayout swipeRefreshLayout; protected Button btSend, btPrefs; protected LinearLayout llLent, llRes, llLoading; protected TextView tvError, tvResHeader, tvPendingFeesLabel, tvPendingFees, tvValidUntilLabel, tvValidUntil, tvAge, tvLentHeader, tvWarning, tvAccCity, tvAccUser, tvAccLabel, tvErrBodyA, tvErrHeadA, tvErrBodyU; protected ExpandingCardListManager lentManager; protected ExpandingCardListManager resManager; private LoadTask lt; private CancelTask ct; private DownloadTask dt; private Account account; private boolean refreshing = false; private long refreshtime; private boolean fromcache; private boolean supported = true; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreate(savedInstanceState); view = inflater.inflate(R.layout.fragment_account, container, false); findViews(); app = (OpacClient) getActivity().getApplication(); account = app.getAccount(); swipeRefreshLayout.setColorSchemeResources(R.color.primary_red); swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { refresh(); } }); setHasOptionsMenu(true); accountSelected(app.getAccount()); final Handler handler = new Handler(); // schedule alarm here and post runnable as soon as scheduled handler.post(new Runnable() { @Override public void run() { refreshage(); handler.postDelayed(this, 60000); } }); return view; } private void findViews() { swipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipe_container); svAccount = (ScrollView) view.findViewById(R.id.svAccount); errorView = (FrameLayout) view.findViewById(R.id.error_view); unsupportedErrorView = view.findViewById(R.id.unsupported_error); answerErrorView = view.findViewById(R.id.answer_error); llLoading = (LinearLayout) view.findViewById(R.id.llLoading); tvErrBodyU = (TextView) view.findViewById(R.id.tvErrBodyU); btSend = (Button) view.findViewById(R.id.btSend); btPrefs = (Button) view.findViewById(R.id.btPrefs); tvErrHeadA = (TextView) view.findViewById(R.id.tvErrHeadA); tvErrBodyA = (TextView) view.findViewById(R.id.tvErrBodyA); tvAccLabel = (TextView) view.findViewById(R.id.tvAccLabel); tvAccUser = (TextView) view.findViewById(R.id.tvAccUser); tvAccCity = (TextView) view.findViewById(R.id.tvAccCity); llLent = (LinearLayout) view.findViewById(R.id.llLent); tvWarning = (TextView) view.findViewById(R.id.tvWarning); tvLentHeader = (TextView) view.findViewById(R.id.tvLentHeader); llRes = (LinearLayout) view.findViewById(R.id.llReservations); tvError = (TextView) view.findViewById(R.id.tvError); tvResHeader = (TextView) view.findViewById(R.id.tvResHeader); tvPendingFeesLabel = (TextView) view.findViewById(R.id.tvPendingFeesLabel); tvPendingFees = (TextView) view.findViewById(R.id.tvPendingFees); tvValidUntilLabel = (TextView) view.findViewById(R.id.tvValidUntilLabel); tvValidUntil = (TextView) view.findViewById(R.id.tvValidUntil); tvAge = (TextView) view.findViewById(R.id.tvAge); } @SuppressLint("NewApi") @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.activity_account, menu); if (app.getAccount() != null && (app.getApi().getSupportFlags() & OpacApi.SUPPORT_FLAG_ACCOUNT_PROLONG_ALL) != 0) { menu.findItem(R.id.action_prolong_all).setVisible(true); } else { menu.findItem(R.id.action_prolong_all).setVisible(false); } menu.findItem(R.id.action_refresh).setVisible(supported); super.onCreateOptionsMenu(menu, inflater); } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == R.id.action_refresh) { refresh(); } else if (item.getItemId() == R.id.action_prolong_all) { prolongAllStart(); } return super.onOptionsItemSelected(item); } @Override public void onResume() { super.onResume(); account = app.getAccount(); accountSelected(account); } @Override public void accountSelected(Account account) { svAccount.setVisibility(View.GONE); unsupportedErrorView.setVisibility(View.GONE); answerErrorView.setVisibility(View.GONE); errorView.removeAllViews(); llLoading.setVisibility(View.VISIBLE); setRefreshing(false); supported = true; this.account = app.getAccount(); OpacApi api; try { api = app.getApi(); } catch (NullPointerException e) { e.printStackTrace(); return; } if (api != null && !app.getLibrary().isAccountSupported()) { supported = false; // Not supported with this api at all llLoading.setVisibility(View.GONE); unsupportedErrorView.setVisibility(View.VISIBLE); tvErrBodyU.setText(R.string.account_unsupported_api); btSend.setText(R.string.write_mail); btSend.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND); emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[] { "info@opacapp.de" }); emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Bibliothek " + app.getLibrary().getIdent()); emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, getResources().getString(R.string.interested_to_help)); emailIntent.setType("text/plain"); startActivity(Intent.createChooser(emailIntent, getString(R.string.write_mail))); } }); } else if (account.getPassword() == null || account.getPassword().equals("null") || account.getPassword().equals("") || account.getName() == null || account.getName().equals("null") || account.getName().equals("")) { // No credentials entered llLoading.setVisibility(View.GONE); answerErrorView.setVisibility(View.VISIBLE); btPrefs.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(getActivity(), AccountEditActivity.class); intent.putExtra(AccountEditActivity.EXTRA_ACCOUNT_ID, app.getAccount().getId()); startActivity(intent); } }); tvErrHeadA.setText(""); tvErrBodyA.setText(R.string.status_nouser); } else { // Supported Context ctx = getActivity() != null ? getActivity() : OpacClient.getEmergencyContext(); AccountDataSource adatasource = new AccountDataSource(ctx); adatasource.open(); refreshtime = adatasource.getCachedAccountDataTime(account); if (refreshtime > 0) { displaydata(adatasource.getCachedAccountData(account), true); if (System.currentTimeMillis() - refreshtime > MAX_CACHE_AGE) { refresh(); } } else { refresh(); } adatasource.close(); } } public void refresh() { if ((!app.getLibrary().isAccountSupported()) || account.getPassword() == null || account.getPassword().equals("null") || account.getPassword().equals("") || account.getName() == null || account.getName().equals("null") || account.getName().equals("")) { return; } setRefreshing(true); lt = new LoadTask(); lt.execute(); } protected void cancel(final String a) { long age = System.currentTimeMillis() - refreshtime; if (refreshing || fromcache || age > MAX_CACHE_AGE) { Toast.makeText(getActivity(), R.string.account_no_concurrent, Toast.LENGTH_LONG).show(); if (!refreshing) { refresh(); } return; } AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setMessage(R.string.cancel_confirm).setCancelable(true) .setNegativeButton(R.string.no, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface d, int id) { d.cancel(); } }).setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface d, int id) { d.dismiss(); MultiStepResultHelper<String> msrhCancel = new MultiStepResultHelper<>(getActivity(), a, R.string.doing_cancel); msrhCancel.setCallback(new Callback<String>() { @Override public void onSuccess(MultiStepResult result) { invalidateData(); } @Override public void onError(MultiStepResult result) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setMessage(result.getMessage()).setCancelable(true) .setNegativeButton(R.string.close, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface d, int id) { d.cancel(); } }).setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface d) { if (d != null) { d.cancel(); } } }); AlertDialog alert = builder.create(); alert.show(); } @Override public void onUnhandledResult(MultiStepResult result) { } @Override public void onUserCancel() { } @Override public StepTask<?> newTask(MultiStepResultHelper helper, int useraction, String selection, String argument) { return ct = new CancelTask(helper, useraction, selection, argument); } }); msrhCancel.start(); } }).setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface d) { if (d != null) { d.cancel(); } } }); AlertDialog alert = builder.create(); alert.show(); } protected void prolong(final String a) { long age = System.currentTimeMillis() - refreshtime; if (refreshing || age > MAX_CACHE_AGE) { Toast.makeText(getActivity(), R.string.account_no_concurrent, Toast.LENGTH_LONG).show(); if (!refreshing) { refresh(); } return; } MultiStepResultHelper<String> msrhProlong = new MultiStepResultHelper<>(getActivity(), a, R.string.doing_prolong); msrhProlong.setCallback(new Callback<String>() { @Override public void onSuccess(MultiStepResult result) { if (getActivity() == null) { return; } invalidateData(); if (result.getMessage() != null) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setMessage(result.getMessage()).setCancelable(false).setNegativeButton(R.string.close, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); AlertDialog alert = builder.create(); alert.show(); } } @Override public void onError(MultiStepResult result) { if (getActivity() == null) { return; } AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setMessage(result.getMessage()).setCancelable(true) .setNegativeButton(R.string.close, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface d, int id) { d.cancel(); } }).setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface d) { if (d != null) { d.cancel(); } } }); AlertDialog alert = builder.create(); alert.show(); } @Override public void onUnhandledResult(MultiStepResult result) { } @Override public void onUserCancel() { } @Override public StepTask<?> newTask(MultiStepResultHelper helper, int useraction, String selection, String argument) { return new ProlongTask(helper, useraction, selection, argument); } }); msrhProlong.start(); } protected void download(final String a) { if (app.getApi() instanceof EbookServiceApi) { dialog = AppCompatProgressDialog.show(getActivity(), "", getString(R.string.doing_download), true); dialog.show(); dt = new DownloadTask(a); dt.execute(); } } public void setRefreshing(boolean refreshing) { this.refreshing = refreshing; swipeRefreshLayout.setRefreshing(refreshing); } public void invalidateData() { AccountDataSource adatasource = new AccountDataSource(getActivity()); adatasource.open(); adatasource.invalidateCachedAccountData(account); adatasource.close(); svAccount.setVisibility(View.GONE); accountSelected(account); } public void show_connectivity_error(Exception e) { if (e != null) { e.printStackTrace(); } if (getActivity() == null) { return; } if (e instanceof OpacErrorException) { AccountDataSource adatasource = new AccountDataSource(getActivity()); adatasource.open(); adatasource.invalidateCachedAccountData(account); adatasource.close(); dialog_wrong_credentials(e.getMessage()); return; } if (getView() != null) { final FrameLayout errorView = (FrameLayout) getView().findViewById(R.id.error_view); errorView.removeAllViews(); View connError = getActivity().getLayoutInflater().inflate(R.layout.error_connectivity, errorView); if (e != null && e instanceof SSLSecurityException) { ((TextView) connError.findViewById(R.id.tvErrBody)) .setText(R.string.connection_error_detail_security); } else if (e != null && e instanceof NotReachableException) { ((TextView) connError.findViewById(R.id.tvErrBody)).setText(R.string.connection_error_detail_nre); } connError.findViewById(R.id.btRetry).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { refresh(); } }); llLoading.setVisibility(View.GONE); svAccount.setVisibility(View.GONE); connError.setVisibility(View.VISIBLE); } } protected void dialog_wrong_credentials(String s) { llLoading.setVisibility(View.GONE); answerErrorView.setVisibility(View.VISIBLE); btPrefs.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(getActivity(), AccountEditActivity.class); intent.putExtra(AccountEditActivity.EXTRA_ACCOUNT_ID, account.getId()); startActivity(intent); } }); tvErrBodyA.setText(s); } public void loaded(final AccountData result) { if (result.getAccount() == account.getId()) { // The account this data is for is still visible setRefreshing(false); refreshtime = System.currentTimeMillis(); displaydata(result, false); } } @SuppressWarnings("deprecation") public void displaydata(final AccountData result, boolean fromcache) { if (getActivity() == null) { return; } svAccount.setVisibility(View.VISIBLE); llLoading.setVisibility(View.GONE); unsupportedErrorView.setVisibility(View.GONE); answerErrorView.setVisibility(View.GONE); errorView.removeAllViews(); this.fromcache = fromcache; SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(app.getApplicationContext()); final int tolerance = Integer.parseInt(sp.getString("notification_warning", "3")); tvAccLabel.setText(account.getLabel()); tvAccUser.setText(account.getName()); Library lib; try { lib = app.getLibrary(account.getLibrary()); tvAccCity.setText(lib.getDisplayName()); } catch (IOException e) { ErrorReporter.handleException(e); e.printStackTrace(); } catch (JSONException e) { ErrorReporter.handleException(e); } /* Lent items */ llLent.removeAllViews(); final boolean notification_on = sp.getBoolean(SyncAccountAlarmListener.PREF_SYNC_SERVICE, false); boolean notification_problems = false; if (tvWarning != null) { if (result.getWarning() != null && result.getWarning().length() > 1) { tvWarning.setVisibility(View.VISIBLE); tvWarning.setText(result.getWarning()); } else { tvWarning.setVisibility(View.GONE); } } if (result.getLent().size() == 0) { TextView t1 = new TextView(getActivity()); t1.setText(R.string.entl_none); llLent.addView(t1); tvLentHeader.setText(getActivity().getString(R.string.lent_head) + " (0)"); } else { tvLentHeader .setText(getActivity().getString(R.string.lent_head) + " (" + result.getLent().size() + ")"); lentManager = new ExpandingCardListManager(getActivity(), llLent) { @Override public View getView(final int position, ViewGroup container) { final View v = getLayoutInflater(null).inflate(R.layout.listitem_account_lent, container, false); LentViewHolder holder = new LentViewHolder(); holder.findViews(v); final LentItem item = result.getLent().get(position); // Expanding and closing details v.setClickable(true); v.setFocusable(true); v.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (getExpandedPosition() != position) { expand(position); } else { collapse(); } } }); if (item.getId() != null) { // Connection to detail view holder.ivDetails.setOnClickListener(new OnClickListener() { @Override public void onClick(View clicked) { Intent intent = new Intent(getActivity(), SearchResultDetailActivity.class); intent.putExtra(SearchResultDetailFragment.ARG_ITEM_ID, item.getId()); ActivityOptionsCompat options = ActivityOptionsCompat.makeScaleUpAnimation(v, v.getLeft(), v.getTop(), v.getWidth(), v.getHeight()); ActivityCompat.startActivity(getActivity(), intent, options.toBundle()); } }); holder.hasDetailLink = true; } // Overview (Title/Author, Status/Deadline) if (item.getTitle() != null && item.getAuthor() != null) { holder.tvTitleAndAuthor.setText(item.getTitle() + ", " + item.getAuthor()); } else if (item.getTitle() != null) { holder.tvTitleAndAuthor.setText(item.getTitle()); } else { setTextOrHide(item.getAuthor(), holder.tvTitleAndAuthor); } DateTimeFormatter fmt = DateTimeFormat.shortDate(); if (item.getDeadline() != null && item.getStatus() != null) { holder.tvStatus.setText( fmt.print(item.getDeadline()) + " (" + Html.fromHtml(item.getStatus()) + ")"); } else if (item.getDeadline() != null) { holder.tvStatus.setText(fmt.print(new LocalDate(item.getDeadline()))); } else { setHtmlTextOrHide(item.getStatus(), holder.tvStatus); } // Detail setTextOrHide(item.getAuthor(), holder.tvAuthorDetail); setHtmlTextOrHide(item.getFormat(), holder.tvFormatDetail); if (item.getLendingBranch() != null && item.getHomeBranch() != null) { holder.tvBranchDetail .setText(Html.fromHtml(item.getLendingBranch() + " / " + item.getHomeBranch())); } else if (item.getLendingBranch() != null) { holder.tvBranchDetail.setText(Html.fromHtml(item.getLendingBranch())); } else { setHtmlTextOrHide(item.getHomeBranch(), holder.tvBranchDetail); } // Color codes for return dates if (item.getDeadline() != null) { if (item.getDeadline().equals(LocalDate.now()) || item.getDeadline().isBefore(LocalDate.now())) { holder.vStatusColor.setBackgroundColor(getResources().getColor(R.color.date_overdue)); } else if (Days.daysBetween(LocalDate.now(), item.getDeadline()).getDays() <= tolerance) { holder.vStatusColor.setBackgroundColor(getResources().getColor(R.color.date_warning)); } else if (item.getDownloadData() != null) { holder.vStatusColor .setBackgroundColor(getResources().getColor(R.color.account_downloadable)); } } else if (item.getDownloadData() != null) { holder.vStatusColor .setBackgroundColor(getResources().getColor(R.color.account_downloadable)); } if (item.getProlongData() != null) { holder.ivProlong.setTag(item.getProlongData()); holder.ivProlong.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { prolong((String) arg0.getTag()); } }); holder.ivProlong.setVisibility(View.VISIBLE); holder.ivProlong.setAlpha(item.isRenewable() ? 255 : 100); } else if (item.getDownloadData() != null && app.getApi() instanceof EbookServiceApi) { holder.ivDownload.setTag(item.getDownloadData()); holder.ivDownload.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { download((String) arg0.getTag()); } }); holder.ivProlong.setVisibility(View.GONE); holder.ivDownload.setVisibility(View.VISIBLE); } else { holder.ivProlong.setVisibility(View.INVISIBLE); } v.setTag(holder); return v; } @Override public void expandView(int position, View view) { LentViewHolder holder = (LentViewHolder) view.getTag(); LentItem item = result.getLent().get(position); holder.llDetails.setVisibility(View.VISIBLE); setHtmlTextOrHide(item.getTitle(), holder.tvTitleAndAuthor); if (holder.hasDetailLink) holder.ivDetails.setVisibility(View.VISIBLE); } @Override public void collapseView(int position, View view) { LentViewHolder holder = (LentViewHolder) view.getTag(); LentItem item = result.getLent().get(position); holder.llDetails.setVisibility(View.GONE); if (item.getTitle() != null && item.getAuthor() != null) { holder.tvTitleAndAuthor.setText(item.getTitle() + ", " + item.getAuthor()); } else if (item.getAuthor() != null) { holder.tvTitleAndAuthor.setText(item.getAuthor()); holder.tvTitleAndAuthor.setVisibility(View.VISIBLE); } holder.ivDetails.setVisibility(View.GONE); } @Override public int getCount() { return result.getLent().size(); } }; lentManager.setAnimationInterceptor(new ExpandingCardListManager.AnimationInterceptor() { private float llDataY; private float llDataTranslationY = 0; @Override public void beforeExpand(View unexpandedView) { LentViewHolder holder = (LentViewHolder) unexpandedView.getTag(); llDataY = ViewHelper.getY(holder.llData); } @Override public Collection<Animator> getExpandAnimations(int heightDifference, View expandedView) { LentViewHolder holder = (LentViewHolder) expandedView.getTag(); Collection<Animator> anims = getAnimations(-heightDifference, 0); // Animate buttons to the side int difference = 2 * (getResources().getDimensionPixelSize(R.dimen.card_side_margin_selected) - getResources().getDimensionPixelSize(R.dimen.card_side_margin_default)); anims.add(ObjectAnimator.ofFloat(holder.llButtons, "translationX", difference, 0)); // Animate llData to the bottom if required if (ViewHelper.getY(holder.llData) != llDataY) { ViewHelper.setY(holder.llData, llDataY); llDataTranslationY = ViewHelper.getTranslationY(holder.llData); anims.add(ObjectAnimator.ofFloat(holder.llData, "translationY", 0)); } else { llDataTranslationY = 0; } return anims; } @Override public Collection<Animator> getCollapseAnimations(int heightDifference, View expandedView) { LentViewHolder holder = (LentViewHolder) expandedView.getTag(); Collection<Animator> anims = getAnimations(0, heightDifference); // Animate buttons back int difference = 2 * (getResources().getDimensionPixelSize(R.dimen.card_side_margin_selected) - getResources().getDimensionPixelSize(R.dimen.card_side_margin_default)); anims.add(ObjectAnimator.ofFloat(holder.llButtons, "translationX", 0, difference)); // Animate llData back anims.add(ObjectAnimator.ofFloat(holder.llData, "translationY", llDataTranslationY)); return anims; } @Override public void onCollapseAnimationEnd() { if (view.findViewById(R.id.rlMeta) != null) { // tablet ViewHelper.setTranslationY(view.findViewById(R.id.rlMeta), 0); } else { // phone ViewHelper.setTranslationY(tvResHeader, 0); ViewHelper.setTranslationY(llRes, 0); ViewHelper.setTranslationY(tvAge, 0); ViewHelper.setTranslationY(view.findViewById(R.id.tvNoWarranty), 0); } } private Collection<Animator> getAnimations(float from, float to) { List<Animator> animators = new ArrayList<>(); if (view.findViewById(R.id.rlMeta) != null) { // tablet if (result.getLent().size() >= result.getReservations().size()) { animators.add(ObjectAnimator.ofFloat(view.findViewById(R.id.rlMeta), "translationY", from, to)); } } else { // phone animators.add(ObjectAnimator.ofFloat(tvResHeader, "translationY", from, to)); animators.add(ObjectAnimator.ofFloat(llRes, "translationY", from, to)); animators.add(ObjectAnimator.ofFloat(tvAge, "translationY", from, to)); animators.add(ObjectAnimator.ofFloat(view.findViewById(R.id.tvNoWarranty), "translationY", from, to)); } return animators; } }); for (final LentItem item : result.getLent()) { try { if (notification_on && item.getDeadline() == null && !item.isEbook()) { notification_problems = true; } } catch (Exception e) { notification_problems = true; } } } if (notification_problems) { if (tvError != null) { tvError.setVisibility(View.VISIBLE); tvError.setText(R.string.notification_problems); } } /* Reservations */ llRes.removeAllViews(); if (result.getReservations().size() == 0) { TextView t1 = new TextView(getActivity()); t1.setText(R.string.reservations_none); llRes.addView(t1); tvResHeader.setText(getActivity().getString(R.string.reservations_head) + " (0)"); } else { tvResHeader.setText(getActivity().getString(R.string.reservations_head) + " (" + result.getReservations().size() + ")"); resManager = new ExpandingCardListManager(getActivity(), llRes) { @Override public View getView(final int position, ViewGroup container) { final View v = getLayoutInflater(null).inflate(R.layout.listitem_account_reservation, llRes, false); ReservationViewHolder holder = new ReservationViewHolder(); holder.findViews(v); final ReservedItem item = result.getReservations().get(position); // Expanding and closing details v.setClickable(true); v.setFocusable(true); v.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (getExpandedPosition() != position) { expand(position); } else { collapse(); } } }); if (item.getId() != null) { // Connection to detail view holder.ivDetails.setOnClickListener(new OnClickListener() { @Override public void onClick(View clicked) { Intent intent = new Intent(getActivity(), SearchResultDetailActivity.class); intent.putExtra(SearchResultDetailFragment.ARG_ITEM_ID, item.getId()); ActivityOptionsCompat options = ActivityOptionsCompat.makeScaleUpAnimation(v, v.getLeft(), v.getTop(), v.getWidth(), v.getHeight()); ActivityCompat.startActivity(getActivity(), intent, options.toBundle()); } }); holder.hasDetailLink = true; } // Overview (Title/Author, Ready/Expire) if (item.getTitle() != null && item.getAuthor() != null) { holder.tvTitleAndAuthor.setText(item.getTitle() + ", " + item.getAuthor()); } else if (item.getTitle() != null) { holder.tvTitleAndAuthor.setText(item.getTitle()); } else { setTextOrHide(item.getAuthor(), holder.tvTitleAndAuthor); } DateTimeFormatter fmt = DateTimeFormat.shortDate(); StringBuilder status = new StringBuilder(); if (item.getStatus() != null) status.append(item.getStatus()); boolean needsBraces = item.getStatus() != null && (item.getReadyDate() != null || item.getExpirationDate() != null); if (needsBraces) status.append(" ("); if (item.getReadyDate() != null) { status.append(getString(R.string.reservation_expire_until)).append(" ") .append(fmt.print(item.getReadyDate())); } if (item.getExpirationDate() != null) { if (item.getReadyDate() != null) status.append(", "); status.append(fmt.print(item.getExpirationDate())); } if (needsBraces) status.append(")"); if (status.length() > 0) { holder.tvStatus.setText(Html.fromHtml(status.toString())); } else { holder.tvStatus.setVisibility(View.GONE); } // Detail setTextOrHide(item.getAuthor(), holder.tvAuthorDetail); setHtmlTextOrHide(item.getFormat(), holder.tvFormatDetail); setHtmlTextOrHide(item.getBranch(), holder.tvBranchDetail); if (item.getBookingData() != null) { holder.ivBooking.setTag(item.getBookingData()); holder.ivBooking.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { bookingStart((String) arg0.getTag()); } }); holder.ivBooking.setVisibility(View.VISIBLE); holder.ivCancel.setVisibility(View.GONE); } else if (item.getCancelData() != null) { holder.ivCancel.setTag(item.getCancelData()); holder.ivCancel.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { cancel((String) arg0.getTag()); } }); holder.ivCancel.setVisibility(View.VISIBLE); holder.ivBooking.setVisibility(View.GONE); } else { holder.ivCancel.setVisibility(View.INVISIBLE); holder.ivBooking.setVisibility(View.GONE); } v.setTag(holder); return v; } @Override public void expandView(int position, View view) { ReservationViewHolder holder = (ReservationViewHolder) view.getTag(); ReservedItem item = result.getReservations().get(position); holder.llDetails.setVisibility(View.VISIBLE); setTextOrHide(item.getTitle(), holder.tvTitleAndAuthor); if (holder.hasDetailLink) holder.ivDetails.setVisibility(View.VISIBLE); } @Override public void collapseView(int position, View view) { ReservationViewHolder holder = (ReservationViewHolder) view.getTag(); ReservedItem item = result.getReservations().get(position); holder.llDetails.setVisibility(View.GONE); if (item.getTitle() != null && item.getAuthor() != null) { holder.tvTitleAndAuthor.setText(item.getTitle() + ", " + item.getAuthor()); } else if (item.getTitle() != null) { holder.tvTitleAndAuthor.setText(item.getAuthor()); holder.tvTitleAndAuthor.setVisibility(View.VISIBLE); } holder.ivDetails.setVisibility(View.GONE); } @Override public int getCount() { return result.getReservations().size(); } }; resManager.setAnimationInterceptor(new ExpandingCardListManager.AnimationInterceptor() { private float llDataY; private float llDataTranslationY = 0; @Override public void beforeExpand(View unexpandedView) { ReservationViewHolder holder = (ReservationViewHolder) unexpandedView.getTag(); llDataY = ViewHelper.getY(holder.llData); } @Override public Collection<Animator> getExpandAnimations(int heightDifference, View expandedView) { ReservationViewHolder holder = (ReservationViewHolder) expandedView.getTag(); Collection<Animator> anims = getAnimations(-heightDifference, 0); // Animate buttons to the side int difference = 2 * (getResources().getDimensionPixelSize(R.dimen.card_side_margin_selected) - getResources().getDimensionPixelSize(R.dimen.card_side_margin_default)); anims.add(ObjectAnimator.ofFloat(holder.llButtons, "translationX", difference, 0)); // Animate llData to the bottom if required if (ViewHelper.getY(holder.llData) != llDataY) { ViewHelper.setY(holder.llData, llDataY); llDataTranslationY = ViewHelper.getTranslationY(holder.llData); anims.add(ObjectAnimator.ofFloat(holder.llData, "translationY", 0)); } else { llDataTranslationY = 0; } return anims; } @Override public Collection<Animator> getCollapseAnimations(int heightDifference, View expandedView) { ReservationViewHolder holder = (ReservationViewHolder) expandedView.getTag(); Collection<Animator> anims = getAnimations(0, heightDifference); // Animate buttons back int difference = 2 * (getResources().getDimensionPixelSize(R.dimen.card_side_margin_selected) - getResources().getDimensionPixelSize(R.dimen.card_side_margin_default)); anims.add(ObjectAnimator.ofFloat(holder.llButtons, "translationX", 0, difference)); // Animate llData back anims.add(ObjectAnimator.ofFloat(holder.llData, "translationY", llDataTranslationY)); return anims; } @Override public void onCollapseAnimationEnd() { if (view.findViewById(R.id.rlMeta) != null) { // tablet ViewHelper.setTranslationY(view.findViewById(R.id.rlMeta), 0); } else { // phone ViewHelper.setTranslationY(tvAge, 0); ViewHelper.setTranslationY(view.findViewById(R.id.tvNoWarranty), 0); } } private Collection<Animator> getAnimations(float from, float to) { List<Animator> animators = new ArrayList<>(); if (view.findViewById(R.id.rlMeta) != null) { // tablet if (result.getReservations().size() >= result.getLent().size()) { animators.add(ObjectAnimator.ofFloat(view.findViewById(R.id.rlMeta), "translationY", from, to)); } } else { // phone animators.add(ObjectAnimator.ofFloat(tvAge, "translationY", from, to)); animators.add(ObjectAnimator.ofFloat(view.findViewById(R.id.tvNoWarranty), "translationY", from, to)); } return animators; } }); } if (result.getPendingFees() != null) { tvPendingFeesLabel.setVisibility(View.VISIBLE); tvPendingFees.setVisibility(View.VISIBLE); tvPendingFees.setText(result.getPendingFees()); } else { tvPendingFeesLabel.setVisibility(View.GONE); tvPendingFees.setVisibility(View.GONE); } if (result.getValidUntil() != null) { tvValidUntilLabel.setVisibility(View.VISIBLE); tvValidUntil.setVisibility(View.VISIBLE); tvValidUntil.setText(result.getValidUntil()); } else { tvValidUntilLabel.setVisibility(View.GONE); tvValidUntil.setVisibility(View.GONE); } refreshage(); } private void setHtmlTextOrHide(String value, TextView tv) { if (!TextUtils.isEmpty(value)) { tv.setText(Html.fromHtml(value)); } else { tv.setVisibility(View.GONE); } } private void setTextOrHide(String value, TextView tv) { if (!TextUtils.isEmpty(value)) { tv.setText(value); } else { tv.setVisibility(View.GONE); } } public void refreshage() { try { if (tvAge == null) { return; } long age = System.currentTimeMillis() - refreshtime; if (age < 60 * 1000) { tvAge.setText(getResources().getString(R.string.account_up_to_date)); } else if (age < (3600 * 1000)) { tvAge.setText(getResources().getQuantityString(R.plurals.account_age_minutes, (int) (age / (60 * 1000)), (int) (age / (60 * 1000)))); } else if (age < 24 * 3600 * 1000) { tvAge.setText(getResources().getQuantityString(R.plurals.account_age_hours, (int) (age / (3600 * 1000)), (int) (age / (3600 * 1000)))); } else { tvAge.setText(getResources().getQuantityString(R.plurals.account_age_days, (int) (age / (24 * 3600 * 1000)), (int) (age / (24 * 3600 * 1000)))); } } catch (java.lang.IllegalStateException e) { // as this is called from a handler it may be called // without an activity attached to this fragment // we do nothing about it } } public void bookingStart(String booking_info) { long age = System.currentTimeMillis() - refreshtime; if (refreshing || fromcache || age > MAX_CACHE_AGE) { Toast.makeText(getActivity(), R.string.account_no_concurrent, Toast.LENGTH_LONG).show(); if (!refreshing) { refresh(); } return; } DetailledItem item = new DetailledItem(); item.setBookable(true); item.setBooking_info(booking_info); MultiStepResultHelper<DetailledItem> msrhBooking = new MultiStepResultHelper<>(getActivity(), item, R.string.doing_booking); msrhBooking.setCallback(new Callback<DetailledItem>() { @Override public void onSuccess(MultiStepResult result) { invalidateData(); } @Override public void onError(MultiStepResult result) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setMessage(result.getMessage()).setCancelable(true) .setNegativeButton(R.string.close, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface d, int id) { d.cancel(); } }).setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface d) { if (d != null) { d.cancel(); } } }); AlertDialog alert = builder.create(); alert.show(); } @Override public void onUnhandledResult(MultiStepResult result) { } @Override public void onUserCancel() { } @Override public StepTask<?> newTask(MultiStepResultHelper helper, int useraction, String selection, DetailledItem argument) { return new BookingTask(helper, useraction, selection, argument); } }); msrhBooking.start(); } public void prolongAllStart() { if (refreshing) { Toast.makeText(getActivity(), R.string.account_no_concurrent, Toast.LENGTH_LONG).show(); if (!refreshing) { refresh(); } return; } AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setMessage(R.string.prolong_all_confirm).setCancelable(true) .setNegativeButton(R.string.no, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface d, int id) { d.cancel(); } }).setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface d, int id) { prolongAllDo(); } }); AlertDialog alert = builder.create(); alert.show(); } public void prolongAllDo() { MultiStepResultHelper<Void> msrhProlong = new MultiStepResultHelper<>(getActivity(), null, R.string.doing_prolong_all); msrhProlong.setCallback(new Callback<Void>() { @Override public void onSuccess(MultiStepResult result) { if (getActivity() == null) { return; } ProlongAllResult res = (ProlongAllResult) result; AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); LayoutInflater inflater = getLayoutInflater(null); View view = inflater.inflate(R.layout.dialog_simple_list, null, false); ListView lv = (ListView) view.findViewById(R.id.lvBibs); lv.setAdapter(new ProlongAllResultAdapter(getActivity(), res.getResults())); switch (result.getActionIdentifier()) { case ReservationResult.ACTION_BRANCH: builder.setTitle(R.string.branch); } builder.setView(view).setNeutralButton(R.string.close, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { adialog.cancel(); invalidateData(); } }); adialog = builder.create(); adialog.show(); } @Override public void onError(MultiStepResult result) { if (getActivity() == null) { return; } AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setMessage(result.getMessage()).setCancelable(true) .setNegativeButton(R.string.close, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface d, int id) { d.cancel(); } }).setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface d) { if (d != null) { d.cancel(); } } }); AlertDialog alert = builder.create(); alert.show(); } @Override public void onUnhandledResult(MultiStepResult result) { } @Override public void onUserCancel() { } @Override public StepTask<?> newTask(MultiStepResultHelper helper, int useraction, String selection, Void argument) { return new ProlongAllTask(helper, useraction, selection); } }); msrhProlong.start(); } @Override public void onStop() { super.onStop(); if (dialog != null) { if (dialog.isShowing()) { dialog.cancel(); } } try { if (lt != null) { if (!lt.isCancelled()) { lt.cancel(true); } } if (ct != null) { if (!ct.isCancelled()) { ct.cancel(true); } } if (dt != null) { if (!dt.isCancelled()) { dt.cancel(true); } } } catch (Exception e) { e.printStackTrace(); } } private class LentViewHolder { public TextView tvTitleAndAuthor; public TextView tvStatus; public TextView tvAuthorDetail; public TextView tvBranchDetail; public TextView tvFormatDetail; public ImageView ivProlong; public ImageView ivDownload; public ImageView ivDetails; public View vStatusColor; public LinearLayout llData; public LinearLayout llDetails; public LinearLayout llButtons; public boolean hasDetailLink; public void findViews(View v) { tvTitleAndAuthor = (TextView) v.findViewById(R.id.tvTitleAndAuthor); tvStatus = (TextView) v.findViewById(R.id.tvStatus); tvAuthorDetail = (TextView) v.findViewById(R.id.tvAuthorDetail); tvBranchDetail = (TextView) v.findViewById(R.id.tvBranchDetail); tvFormatDetail = (TextView) v.findViewById(R.id.tvFormatDetail); ivProlong = (ImageView) v.findViewById(R.id.ivProlong); ivDownload = (ImageView) v.findViewById(R.id.ivDownload); ivDetails = (ImageView) v.findViewById(R.id.ivDetails); vStatusColor = v.findViewById(R.id.vStatusColor); llData = (LinearLayout) v.findViewById(R.id.llData); llDetails = (LinearLayout) v.findViewById(R.id.llDetails); llButtons = (LinearLayout) v.findViewById(R.id.llButtons); } } private class ReservationViewHolder { public TextView tvTitleAndAuthor; public TextView tvStatus; public TextView tvAuthorDetail; public TextView tvBranchDetail; public TextView tvFormatDetail; public ImageView ivCancel; public ImageView ivBooking; public ImageView ivDetails; public LinearLayout llData; public LinearLayout llDetails; public LinearLayout llButtons; public boolean hasDetailLink; public void findViews(View v) { tvTitleAndAuthor = (TextView) v.findViewById(R.id.tvTitleAndAuthor); tvStatus = (TextView) v.findViewById(R.id.tvStatus); tvAuthorDetail = (TextView) v.findViewById(R.id.tvAuthorDetail); tvBranchDetail = (TextView) v.findViewById(R.id.tvBranchDetail); tvFormatDetail = (TextView) v.findViewById(R.id.tvFormatDetail); ivCancel = (ImageView) v.findViewById(R.id.ivCancel); ivBooking = (ImageView) v.findViewById(R.id.ivBooking); ivDetails = (ImageView) v.findViewById(R.id.ivDetails); llData = (LinearLayout) v.findViewById(R.id.llData); llDetails = (LinearLayout) v.findViewById(R.id.llDetails); llButtons = (LinearLayout) v.findViewById(R.id.llButtons); } } public class LoadTask extends AsyncTask<Void, Void, AccountData> { private Exception exception; @Override protected AccountData doInBackground(Void... voids) { try { AccountData data = app.getApi().account(account); if (data == null) { return null; } // save data AccountDataSource adatasource; if (getActivity() == null && OpacClient.getEmergencyContext() != null) { adatasource = new AccountDataSource(OpacClient.getEmergencyContext()); } else { adatasource = new AccountDataSource(getActivity()); } adatasource.open(); account.setPasswordKnownValid(true); adatasource.update(account); adatasource.storeCachedAccountData(adatasource.getAccount(data.getAccount()), data); adatasource.close(); new ReminderHelper(app).generateAlarms(); return data; } catch (IOException | OpacErrorException e) { exception = e; } catch (Exception e) { ErrorReporter.handleException(e); exception = e; } return null; } @Override protected void onPostExecute(AccountData result) { if (exception == null && result != null) { loaded(result); } else { setRefreshing(false); show_connectivity_error(exception); } } } public class CancelTask extends StepTask<CancelResult> { private String itemId; public CancelTask(MultiStepResultHelper helper, int useraction, String selection, String itemId) { super(helper, useraction, selection); this.itemId = itemId; } @Override protected CancelResult doInBackground(Void... voids) { try { return app.getApi().cancel(itemId, account, useraction, selection); } catch (java.net.UnknownHostException | NoHttpResponseException | java.net.SocketException e) { e.printStackTrace(); } catch (Exception e) { ErrorReporter.handleException(e); } return null; } @Override protected void onPostExecute(CancelResult result) { if (getActivity() == null) { return; } if (result == null) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setMessage(R.string.error).setCancelable(true).setNegativeButton(R.string.close, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); AlertDialog alert = builder.create(); alert.show(); } super.onPostExecute(result); } } public class DownloadTask extends AsyncTask<Void, Void, String> { private String itemId; public DownloadTask(String itemId) { this.itemId = itemId; } @Override protected String doInBackground(Void... voids) { return ((EbookServiceApi) app.getApi()).downloadItem(account, itemId); } @Override protected void onPostExecute(final String result) { dialog.dismiss(); if (getActivity() == null) { return; } if (result.contains("acsm")) { String[] download_clients = new String[] { "com.android.aldiko", "com.aldiko.android", "com.bluefirereader", "com.mantano.reader.android.lite", "com.datalogics.dlreader", "com.mantano.reader.android.normal", "com.mantano.reader.android", "com.neosoar" }; boolean found = false; PackageManager pm = getActivity().getPackageManager(); for (String id : download_clients) { try { pm.getPackageInfo(id, 0); found = true; } catch (NameNotFoundException e) { } } final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getActivity()); if (!found && !sp.contains("reader_needed_ignore")) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setMessage(R.string.reader_needed).setCancelable(true) .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }) .setNeutralButton(R.string.reader_needed_ignore, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { Intent i = new Intent(Intent.ACTION_VIEW); i.setData(Uri.parse(result)); sp.edit().putBoolean("reader_needed_ignore", true).commit(); startActivity(i); } }).setPositiveButton(R.string.download, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { dialog.cancel(); Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=de" + ".bluefirereader")); startActivity(i); } }); AlertDialog alert = builder.create(); alert.show(); return; } } Intent i = new Intent(Intent.ACTION_VIEW); i.setData(Uri.parse(result)); startActivity(i); } } public class ProlongTask extends MultiStepResultHelper.StepTask<ProlongResult> { private boolean success = true; private String itemId; public ProlongTask(MultiStepResultHelper helper, int useraction, String selection, String itemId) { super(helper, useraction, selection); this.itemId = itemId; } @Override protected ProlongResult doInBackground(Void... voids) { try { ProlongResult res = app.getApi().prolong(itemId, account, useraction, selection); success = true; return res; } catch (java.net.UnknownHostException | NoHttpResponseException e) { publishProgress(e, "ioerror"); } catch (IOException e) { success = false; e.printStackTrace(); } catch (Exception e) { ErrorReporter.handleException(e); success = false; } return null; } @Override protected void onPostExecute(ProlongResult res) { if (getActivity() == null) { return; } if (!success || res == null) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setMessage(R.string.error).setCancelable(true).setNegativeButton(R.string.close, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); AlertDialog alert = builder.create(); alert.show(); return; } super.onPostExecute(res); } } public class ProlongAllTask extends MultiStepResultHelper.StepTask<ProlongAllResult> { public ProlongAllTask(MultiStepResultHelper helper, int useraction, String selection) { super(helper, useraction, selection); } @Override protected ProlongAllResult doInBackground(Void... voids) { try { return app.getApi().prolongAll(account, useraction, selection); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { ErrorReporter.handleException(e); } return null; } @Override protected void onPostExecute(ProlongAllResult result) { if (getActivity() == null) { return; } if (result == null) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setMessage(R.string.error).setCancelable(true).setNegativeButton(R.string.close, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); AlertDialog alert = builder.create(); alert.show(); } super.onPostExecute(result); } } public class ProlongAllResultAdapter extends ArrayAdapter<Map<String, String>> { private List<Map<String, String>> objects; public ProlongAllResultAdapter(Context context, List<Map<String, String>> objects) { super(context, R.layout.simple_spinner_item, objects); this.objects = objects; } @Override public View getView(int position, View contentView, ViewGroup viewGroup) { View view; if (objects.get(position) == null) { LayoutInflater layoutInflater = (LayoutInflater) getContext() .getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = layoutInflater.inflate(R.layout.listitem_prolongall_result, viewGroup, false); return view; } Map<String, String> item = objects.get(position); if (contentView == null) { LayoutInflater layoutInflater = (LayoutInflater) getContext() .getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = layoutInflater.inflate(R.layout.listitem_prolongall_result, viewGroup, false); } else { view = contentView; } TextView tvAuthor = (TextView) view.findViewById(R.id.tvAuthor); TextView tvTitle = (TextView) view.findViewById(R.id.tvTitle); TextView tvOld = (TextView) view.findViewById(R.id.tvOld); TextView tvNew = (TextView) view.findViewById(R.id.tvNew); TextView tvMsg = (TextView) view.findViewById(R.id.tvMsg); tvAuthor.setVisibility(item.containsKey(ProlongAllResult.KEY_LINE_AUTHOR) ? View.VISIBLE : View.GONE); tvAuthor.setText(item.get(ProlongAllResult.KEY_LINE_AUTHOR)); tvTitle.setText(item.get(ProlongAllResult.KEY_LINE_TITLE)); tvOld.setText(item.get(ProlongAllResult.KEY_LINE_OLD_RETURNDATE)); tvNew.setText(item.get(ProlongAllResult.KEY_LINE_NEW_RETURNDATE)); tvMsg.setText(item.get(ProlongAllResult.KEY_LINE_MESSAGE)); return view; } } public class BookingTask extends StepTask<BookingResult> { private DetailledItem item; public BookingTask(MultiStepResultHelper helper, int useraction, String selection, DetailledItem item) { super(helper, useraction, selection); this.item = item; } @Override protected BookingResult doInBackground(Void... voids) { try { return ((EbookServiceApi) app.getApi()).booking(item, app.getAccount(), useraction, selection); } catch (IOException e) { publishProgress(e, "ioerror"); } catch (Exception e) { ErrorReporter.handleException(e); } return null; } @Override protected void onPostExecute(BookingResult res) { if (getActivity() == null) { return; } if (res == null) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setMessage(R.string.error).setCancelable(true).setNegativeButton(R.string.close, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); AlertDialog alert = builder.create(); alert.show(); return; } super.onPostExecute(res); } } }