From a7ff15142fe8152870a0140728677170415ed556 Mon Sep 17 00:00:00 2001 From: Joshua <8Joshua@web.de> Date: Tue, 30 Oct 2018 20:10:15 +0100 Subject: [PATCH] =?UTF-8?q?Datei=20Download=20f=C3=BCr=20Ank=C3=BCndigung?= =?UTF-8?q?=20und=20Aufgaben?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../moddetails/ModDetailAnnounceAdapter.java | 33 ++- .../moddetails/ModDetailAnnounceFragment.java | 42 ++- .../ModDetailAssignmentAdapter.java | 33 ++- .../ModDetailAssignmentFragment.java | 42 ++- .../moddetails/ModDetailEventAdapter.java | 24 +- .../moddetails/ModDetailResourceFragment.java | 207 ++------------- .../fuplanner/services/KVV/Download.java | 250 ++++++++++++++++++ app/src/main/res/values-de/strings.xml | 8 +- app/src/main/res/values/strings.xml | 8 +- 9 files changed, 430 insertions(+), 217 deletions(-) create mode 100644 app/src/main/java/de/sebse/fuplanner/services/KVV/Download.java diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAnnounceAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAnnounceAdapter.java index 8b675b1..d35f26f 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAnnounceAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAnnounceAdapter.java @@ -1,5 +1,6 @@ package de.sebse.fuplanner.fragments.moddetails; +import android.content.res.Resources; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -15,6 +16,7 @@ import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.RecyclerView; import de.sebse.fuplanner.R; +import de.sebse.fuplanner.services.KVV.Download; import de.sebse.fuplanner.services.KVV.types.Announcement; import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.tools.Regex; @@ -27,6 +29,11 @@ class ModDetailAnnounceAdapter extends RecyclerView.Adapter { @Nullable private Modules.Module mModule = null; private Logger log = new Logger(this); + @NonNull private Download.OnDownloadRequestInterface requestInterface; + + ModDetailAnnounceAdapter(@NonNull Download.OnDownloadRequestInterface requestInterface) { + this.requestInterface = requestInterface; + } public void setModule(Modules.Module module) { this.mModule = module; @@ -64,16 +71,7 @@ class ModDetailAnnounceAdapter extends RecyclerView.Adapter { if (!notes.isEmpty()) { holder.mTagGroup.setVisibility(View.VISIBLE); for (int i = 0, notesSize = notes.size(); i < notesSize; i++) { - String name; - try { - name = URLDecoder.decode(Regex.regex("/([^/]*)$", notes.get(i)), "UTF-8"); - } catch (NoSuchFieldException e) { - e.printStackTrace(); - name = holder.mView.getResources().getString(R.string.attachment_nr, i); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - name = holder.mView.getResources().getString(R.string.attachment_nr, i); - } + String name = urlToName(notes.get(i), i, holder.mView.getResources()); Tag tag = new Tag(name); tag.id = i; tag.layoutColor = ContextCompat.getColor(holder.mView.getContext(), R.color.colorFUBlue); @@ -84,6 +82,8 @@ class ModDetailAnnounceAdapter extends RecyclerView.Adapter { String s = notes.get(i); if (s != null) { log.d("Download", s); + String name = urlToName(s, i, holder.mView.getResources()); + requestInterface.request(name, s); } }); } else { @@ -93,6 +93,19 @@ class ModDetailAnnounceAdapter extends RecyclerView.Adapter { } } + private String urlToName(String url, int index, Resources res) { + + try { + return URLDecoder.decode(Regex.regex("/([^/]*)$", url), "UTF-8"); + } catch (NoSuchFieldException e) { + e.printStackTrace(); + return res.getString(R.string.attachment_nr, index); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + return res.getString(R.string.attachment_nr, index); + } + } + @Override public int getItemCount() { if (mModule != null && mModule.announcements != null) diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAnnounceFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAnnounceFragment.java index 9216d0d..66ea74e 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAnnounceFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAnnounceFragment.java @@ -1,6 +1,7 @@ package de.sebse.fuplanner.fragments.moddetails; +import android.content.Context; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; @@ -13,8 +14,10 @@ import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.R; +import de.sebse.fuplanner.services.KVV.Download; import de.sebse.fuplanner.services.KVV.KVV; import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.logging.Logger; /** @@ -22,13 +25,15 @@ import de.sebse.fuplanner.tools.logging.Logger; * Use the {@link ModDetailAnnounceFragment#newInstance} factory method to * create an instance of this fragment. */ -public class ModDetailAnnounceFragment extends Fragment { +public class ModDetailAnnounceFragment extends Fragment implements Download.OnDownloadRequestInterface { private static final String ARG_POSITION = "itemPosition"; private String mItemPos; private final Logger log = new Logger(this); private ModDetailAnnounceAdapter adapter; private SwipeRefreshLayout swipeLayout; + private Download download; + private MainActivityListener context; public ModDetailAnnounceFragment() { @@ -65,7 +70,7 @@ public class ModDetailAnnounceFragment extends Fragment { View view = inflater.inflate(R.layout.fragment_recycler_view, container, false); // Set the adapter RecyclerView expandableListView = view.findViewById(R.id.list); - adapter = new ModDetailAnnounceAdapter(); + adapter = new ModDetailAnnounceAdapter(this); expandableListView.setAdapter(adapter); // Getting SwipeContainerLayout @@ -95,4 +100,37 @@ public class ModDetailAnnounceFragment extends Fragment { }, forceRefresh); } } + + @Override + public void request(String title, String url) { + context.getKVV().getModule(mItemPos, (Modules.Module module) -> { + if (module == null) + return; + String folderName = "FU-"+module.title.replaceAll("[:*<>|/\"\\\\]", "-"); + folderName += "/Assignment"; + getDownload().openDownloadDialog(title, url, folderName); + }, log::e, false); + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + if (context instanceof MainActivityListener) { + this.context = ((MainActivityListener) context); + this.context.addRequestPermissionsResultListener(getDownload().getRequestPermissionsResultListener(), "ModDetailResourceFragment"); + } else + throw new RuntimeException(context.toString() + " must implement MainActivityListener"); + } + + @Override + public void onDetach() { + super.onDetach(); + this.context.removeRequestPermissionsResultListener("ModDetailResourceFragment"); + } + + Download getDownload() { + if (download == null) + download = new Download(this::getContext, () -> (MainActivity) getActivity()); + return download; + } } diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentAdapter.java index cf85afd..e695666 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentAdapter.java @@ -1,5 +1,6 @@ package de.sebse.fuplanner.fragments.moddetails; +import android.content.res.Resources; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -15,6 +16,7 @@ import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.RecyclerView; import de.sebse.fuplanner.R; +import de.sebse.fuplanner.services.KVV.Download; import de.sebse.fuplanner.services.KVV.types.Assignment; import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.tools.Regex; @@ -27,6 +29,11 @@ class ModDetailAssignmentAdapter extends RecyclerView.Adapter @Nullable private Modules.Module mModule = null; private Logger log = new Logger(this); + @NonNull private Download.OnDownloadRequestInterface requestInterface; + + ModDetailAssignmentAdapter(@NonNull Download.OnDownloadRequestInterface requestInterface) { + this.requestInterface = requestInterface; + } public void setModule(Modules.Module module) { this.mModule = module; @@ -64,16 +71,7 @@ class ModDetailAssignmentAdapter extends RecyclerView.Adapter if (!notes.isEmpty()) { holder.mTagGroup.setVisibility(View.VISIBLE); for (int i = 0, notesSize = notes.size(); i < notesSize; i++) { - String name; - try { - name = URLDecoder.decode(Regex.regex("/([^/]*)$", notes.get(i)), "UTF-8"); - } catch (NoSuchFieldException e) { - e.printStackTrace(); - name = holder.mView.getResources().getString(R.string.attachment_nr, i); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - name = holder.mView.getResources().getString(R.string.attachment_nr, i); - } + String name = urlToName(notes.get(i), i, holder.mView.getResources()); Tag tag = new Tag(name); tag.id = i; tag.layoutColor = ContextCompat.getColor(holder.mView.getContext(), R.color.colorFUBlue); @@ -84,6 +82,8 @@ class ModDetailAssignmentAdapter extends RecyclerView.Adapter String s = notes.get(i); if (s != null) { log.d("Download", s); + String name = urlToName(s, i, holder.mView.getResources()); + requestInterface.request(name, s); } }); } else { @@ -93,6 +93,19 @@ class ModDetailAssignmentAdapter extends RecyclerView.Adapter } } + private String urlToName(String url, int index, Resources res) { + + try { + return URLDecoder.decode(Regex.regex("/([^/]*)$", url), "UTF-8"); + } catch (NoSuchFieldException e) { + e.printStackTrace(); + return res.getString(R.string.attachment_nr, index); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + return res.getString(R.string.attachment_nr, index); + } + } + @Override public int getItemCount() { if (mModule != null && mModule.assignments != null) diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentFragment.java index 9c7f4c8..48e6f52 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentFragment.java @@ -1,6 +1,7 @@ package de.sebse.fuplanner.fragments.moddetails; +import android.content.Context; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; @@ -13,8 +14,10 @@ import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.R; +import de.sebse.fuplanner.services.KVV.Download; import de.sebse.fuplanner.services.KVV.KVV; import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.logging.Logger; /** @@ -22,13 +25,15 @@ import de.sebse.fuplanner.tools.logging.Logger; * Use the {@link ModDetailAssignmentFragment#newInstance} factory method to * create an instance of this fragment. */ -public class ModDetailAssignmentFragment extends Fragment { +public class ModDetailAssignmentFragment extends Fragment implements Download.OnDownloadRequestInterface { private static final String ARG_POSITION = "itemPosition"; private String mItemPos; private final Logger log = new Logger(this); private ModDetailAssignmentAdapter adapter; private SwipeRefreshLayout swipeLayout; + private Download download; + private MainActivityListener context; public ModDetailAssignmentFragment() { @@ -65,7 +70,7 @@ public class ModDetailAssignmentFragment extends Fragment { View view = inflater.inflate(R.layout.fragment_recycler_view, container, false); // Set the adapter RecyclerView expandableListView = view.findViewById(R.id.list); - adapter = new ModDetailAssignmentAdapter(); + adapter = new ModDetailAssignmentAdapter(this); expandableListView.setAdapter(adapter); // Getting SwipeContainerLayout @@ -95,4 +100,37 @@ public class ModDetailAssignmentFragment extends Fragment { }, forceRefresh); } } + + @Override + public void request(String title, String url) { + context.getKVV().getModule(mItemPos, (Modules.Module module) -> { + if (module == null) + return; + String folderName = "FU-"+module.title.replaceAll("[:*<>|/\"\\\\]", "-"); + folderName += "/Assignment"; + getDownload().openDownloadDialog(title, url, folderName); + }, log::e, false); + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + if (context instanceof MainActivityListener) { + this.context = ((MainActivityListener) context); + this.context.addRequestPermissionsResultListener(getDownload().getRequestPermissionsResultListener(), "ModDetailResourceFragment"); + } else + throw new RuntimeException(context.toString() + " must implement MainActivityListener"); + } + + @Override + public void onDetach() { + super.onDetach(); + this.context.removeRequestPermissionsResultListener("ModDetailResourceFragment"); + } + + Download getDownload() { + if (download == null) + download = new Download(this::getContext, () -> (MainActivity) getActivity()); + return download; + } } diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailEventAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailEventAdapter.java index c61c38b..a3ef881 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailEventAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailEventAdapter.java @@ -1,5 +1,6 @@ package de.sebse.fuplanner.fragments.moddetails; +import android.content.res.Resources; import android.util.Pair; import android.view.LayoutInflater; import android.view.View; @@ -124,8 +125,29 @@ class ModDetailEventAdapter extends RecyclerView.Adapter { ListViewHolder h; ModDetailEventAdapterInner adapter; h = (ListViewHolder) holder; + Resources resources = h.mView.getResources(); adapter = new ModDetailEventAdapterInner(); - h.mString.setText(data.second); + String title; + switch (data.second) { + case VALUE_LECTURE: + title = resources.getString(R.string.lecture); + break; + case VALUE_TUTORIAL: + title = resources.getString(R.string.tutorial); + break; + case VALUE_EXAM: + title = resources.getString(R.string.exam); + break; + case VALUE_DEADLINE: + title = resources.getString(R.string.deadline); + break; + case VALUE_OTHER: + title = resources.getString(R.string.others); + break; + default: + title = data.second; + } + h.mString.setText(title); switch (data.first) { case TYPE_GROUPED: adapter.setData((GroupedEvents) data.third, h.mView.getContext()); diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceFragment.java index fbbdaed..665ba28 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceFragment.java @@ -1,45 +1,33 @@ package de.sebse.fuplanner.fragments.moddetails; -import android.Manifest; -import android.app.AlertDialog; import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.net.Uri; import android.os.Bundle; -import android.os.Environment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; -import java.io.File; -import java.util.ArrayList; import java.util.Arrays; import androidx.annotation.NonNull; -import androidx.core.app.ActivityCompat; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.R; +import de.sebse.fuplanner.services.KVV.Download; import de.sebse.fuplanner.services.KVV.KVV; import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.services.KVV.types.Resource; import de.sebse.fuplanner.tools.MainActivityListener; -import de.sebse.fuplanner.tools.Regex; -import de.sebse.fuplanner.tools.UtilsDate; import de.sebse.fuplanner.tools.logging.Logger; import de.sebse.fuplanner.tools.ui.treeview.DirectoryNodeBinder; import de.sebse.fuplanner.tools.ui.treeview.FileNodeBinder; import de.sebse.fuplanner.tools.ui.treeview.TreeNode; import de.sebse.fuplanner.tools.ui.treeview.TreeViewAdapter; -import static androidx.core.content.ContextCompat.checkSelfPermission; - /** * A simple {@link Fragment} subclass. * Use the {@link ModDetailResourceFragment#newInstance} factory method to @@ -53,7 +41,7 @@ public class ModDetailResourceFragment extends Fragment { private ModDetailResourceAdapter adapter; private SwipeRefreshLayout swipeLayout; private MainActivityListener context; - private RequestedDownload requestedDownload; + private Download download; public ModDetailResourceFragment() { @@ -81,7 +69,7 @@ public class ModDetailResourceFragment extends Fragment { if (getArguments() != null) { mItemPos = getArguments().getString(ARG_POSITION); } - } +} @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, @@ -103,30 +91,10 @@ public class ModDetailResourceFragment extends Fragment { } else if(node.getContent() instanceof Resource.File) { // if leaf is file KVV kvv = ModDetailResourceFragment.this.context.getKVV(); kvv.getModule(mItemPos, (Modules.Module module) -> { - if (getContext() == null) - return; - AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext()); - Resource.File file = (Resource.File) node.getContent(); - String folderName = "FU-"+module.title.replaceAll("[:*<>|/\"\\\\]", "-"); - File f = new File(Environment.getExternalStoragePublicDirectory( - Environment.DIRECTORY_DOWNLOADS)+"/"+folderName+"/"+file.getTitle()); - alertDialogBuilder - .setTitle(file.getTitle()) - .setMessage( - getResources().getString(R.string.creator_name, file.getAuthor()) + "\n" + - getResources().getString(R.string.last_modified_on, UtilsDate.getModifiedDateTime(context, file.getModifiedDate())) - ) - .setCancelable(true) - .setNeutralButton(R.string.close, (dialog, id) -> dialog.cancel()) - .setPositiveButton(R.string.download, (dialog, id) -> download(file, folderName, true)); - // if already downloaded, show open button - if (f.exists()) { - alertDialogBuilder - .setNegativeButton(R.string.openFile, (dialog, id) -> download(file, folderName, false)); - } - AlertDialog alertDialog = alertDialogBuilder.create(); - alertDialog.show(); + String folderName = "FU-"+module.title.replaceAll("[:*<>|/\"\\\\]", "-"); + Resource.File file = (Resource.File) node.getContent(); + getDownload().openDownloadDialog(file, folderName); }, log::e); } return false; @@ -152,87 +120,14 @@ public class ModDetailResourceFragment extends Fragment { return view; } - private void download(Resource.File file, String folderName, boolean downloadNew){ - if (getActivity() == null) { - showDownloadError(); - return; - } - if (checkSelfPermission(getActivity(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { - // Access granted - downloadOrOpen(file, folderName, downloadNew); - } else { - this.requestedDownload = new RequestedDownload(file, folderName, downloadNew); - ActivityCompat.requestPermissions(ModDetailResourceFragment.super.getActivity(), - new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, - 1); - } - } - private void downloadOrOpen(Resource.File file, String folderName, boolean downloadNew) { - KVV kvv = this.context.getKVV(); - if(isExternalStorageWritable()){ - kvv.getResourceFile(success1 -> { - // Downloading file failed - if (success1.equals("")){ - showDownloadError(); - }else { - if (Regex.has("^http", success1)){ - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(success1)); - startActivity(intent); - } - else { - fileOpen(new File(success1)); - } - - } - }, log::e, file.getTitle(), file.getUrl(), folderName, downloadNew); - } - } - - private void showDownloadError() { - AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext()); - alertDialogBuilder - .setTitle(R.string.ErrorFileDownload) - .setMessage( - R.string.ErrorFileDownloadText - ) - .setCancelable(true) - .setNeutralButton(R.string.close, (dialog, id) -> dialog.cancel()); - AlertDialog alertDialog = alertDialogBuilder.create(); - alertDialog.show(); - } @Override public void onAttach(Context context) { super.onAttach(context); if (context instanceof MainActivityListener) { this.context = ((MainActivityListener) context); - this.context.addRequestPermissionsResultListener((requestCode, permissions, grantResults) -> { - if (requestedDownload == null) { - log.d("No request"); - return; - } - if (getActivity() == null) { - showDownloadError(); - return; - } - ArrayList intList = new ArrayList<>(); - for (int i : grantResults) - { - intList.add(i); - } - log.d(requestCode, Arrays.asList(permissions), intList); - int pos = Arrays.asList(permissions).indexOf("android.permission.WRITE_EXTERNAL_STORAGE"); - if (pos != -1) { - if (grantResults[pos] != -1) { - downloadOrOpen(requestedDownload.file, requestedDownload.folderName, requestedDownload.downloadNew); - } else { - log.d(requestedDownload, pos, grantResults[pos]); - showDownloadError(); - } - requestedDownload = null; - } - }, "ModDetailResourceFragment"); + this.context.addRequestPermissionsResultListener(getDownload().getRequestPermissionsResultListener(), "ModDetailResourceFragment"); } else throw new RuntimeException(context.toString() + " must implement MainActivityListener"); } @@ -243,70 +138,6 @@ public class ModDetailResourceFragment extends Fragment { this.context.removeRequestPermissionsResultListener("ModDetailResourceFragment"); } - /* Checks if external storage is available for read and write */ - private boolean isExternalStorageWritable() { - String state = Environment.getExternalStorageState(); - if (Environment.MEDIA_MOUNTED.equals(state)) { - return true; - } - log.e("File system: Writing not possible"); - return false; - } - - private void fileOpen(File url){ - Uri uri = Uri.fromFile(url); - - Intent intent = new Intent();//Intent.ACTION_VIEW - // Check what kind of file you are trying to open, by comparing the url with extensions. - // When the if condition is matched, plugin sets the correct intent (mime) type, - // so Android knew what application to use to open the file - if (url.toString().contains(".doc") || url.toString().contains(".docx")) { - // Word document - intent.setDataAndType(uri, "application/msword"); - } else if(url.toString().contains(".pdf")) { - // PDF file - intent.setDataAndType(uri, "application/pdf"); - } else if(url.toString().contains(".ppt") || url.toString().contains(".pptx")) { - // Powerpoint file - intent.setDataAndType(uri, "application/vnd.ms-powerpoint"); - } else if(url.toString().contains(".xls") || url.toString().contains(".xlsx")) { - // Excel file - intent.setDataAndType(uri, "application/vnd.ms-excel"); - } else if(url.toString().contains(".zip") || url.toString().contains(".rar")) { - // ZIP file - intent.setDataAndType(uri, "application/zip"); - } else if(url.toString().contains(".rtf")) { - // RTF file - intent.setDataAndType(uri, "application/rtf"); - } else if(url.toString().contains(".wav") || url.toString().contains(".mp3")) { - // WAV audio file - intent.setDataAndType(uri, "audio/x-wav"); - } else if(url.toString().contains(".gif")) { - // GIF file - intent.setDataAndType(uri, "image/gif"); - } else if(url.toString().contains(".jpg") || url.toString().contains(".jpeg") || url.toString().contains(".png")) { - // JPG file - intent.setDataAndType(uri, "image/jpeg"); - } else if(url.toString().contains(".txt")) { - // Text file - intent.setDataAndType(uri, "text/plain"); - } else if(url.toString().contains(".3gp") || url.toString().contains(".mpg") || url.toString().contains(".mpeg") || url.toString().contains(".mpe") || url.toString().contains(".mp4") || url.toString().contains(".avi")) { - // Video files - intent.setDataAndType(uri, "video/*"); - } else { - //if you want you can also define the intent type for any other file - - //additionally use else clause below, to manage other unknown extensions - //in this case, Android will show all applications installed on the device - //so you can choose which application to use - intent.setDataAndType(uri, "*/*"); - } - - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - startActivity(intent); - - } - private void refresh(boolean forceRefresh) { if (getActivity() != null) { KVV kvv = ((MainActivity) getActivity()).getKVV(); @@ -326,19 +157,15 @@ public class ModDetailResourceFragment extends Fragment { } } - - - - - private class RequestedDownload { - Resource.File file; - String folderName; - boolean downloadNew; - - RequestedDownload(Resource.File file, String folderName, boolean downloadNew) { - this.file = file; - this.folderName = folderName; - this.downloadNew = downloadNew; - } + Download getDownload() { + if (download == null) + download = new Download(this::getContext, () -> (MainActivity) getActivity()); + return download; } + + + + + + } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/Download.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/Download.java new file mode 100644 index 0000000..8fcfb83 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/Download.java @@ -0,0 +1,250 @@ +package de.sebse.fuplanner.services.KVV; + +import android.Manifest; +import android.app.AlertDialog; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.res.Resources; +import android.net.Uri; +import android.os.Environment; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; + +import androidx.annotation.Nullable; +import androidx.core.app.ActivityCompat; +import de.sebse.fuplanner.MainActivity; +import de.sebse.fuplanner.R; +import de.sebse.fuplanner.services.KVV.types.Resource; +import de.sebse.fuplanner.tools.Regex; +import de.sebse.fuplanner.tools.RequestPermissionsResultListener; +import de.sebse.fuplanner.tools.UtilsDate; +import de.sebse.fuplanner.tools.logging.Logger; + +import static androidx.core.content.ContextCompat.checkSelfPermission; + +public class Download { + + private final ContextInterface contextInterface; + private final ActivityInterface activityInterface; + private RequestedDownload requestedDownload; + private Logger log = new Logger(this); + + + public Download(ContextInterface contextInterface, ActivityInterface activityInterface) { + this.contextInterface = contextInterface; + this.activityInterface = activityInterface; + } + + public void openDownloadDialog(String title, String url, String folderName) { + openDownloadDialog(new Resource.File("", title, 0, url, true, "", ""), folderName); + } + + public void openDownloadDialog(Resource.File file, String folderName) { + if (contextInterface.get() == null) + return; + AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(contextInterface.get()); + File f = new File(Environment.getExternalStoragePublicDirectory( + Environment.DIRECTORY_DOWNLOADS)+"/"+folderName+"/"+file.getTitle()); + Resources resources = contextInterface.get().getResources(); + String message = ""; + if (file.getAuthor() != null && !file.getAuthor().isEmpty()) + message += resources.getString(R.string.creator_name, file.getAuthor()); + if (file.getModifiedDate() != 0) { + if (!message.isEmpty()) + message += "\n"; + resources.getString(R.string.last_modified_on, UtilsDate.getModifiedDateTime(contextInterface.get(), file.getModifiedDate())); + } + + alertDialogBuilder + .setTitle(file.getTitle()) + .setMessage(message) + .setCancelable(true) + .setNeutralButton(R.string.close, (dialog, id) -> dialog.cancel()); + // if already downloaded, show open button + if (f.exists()) { + alertDialogBuilder + .setPositiveButton(R.string.download_again, (dialog, id) -> download(file, folderName, true)) + .setNegativeButton(R.string.openFile, (dialog, id) -> download(file, folderName, false)); + } else { + alertDialogBuilder + .setPositiveButton(R.string.download, (dialog, id) -> download(file, folderName, true)); + } + AlertDialog alertDialog = alertDialogBuilder.create(); + alertDialog.show(); + } + + private void download(Resource.File file, String folderName, boolean downloadNew){ + if (activityInterface.get() == null) { + showDownloadError(); + return; + } + if (checkSelfPermission(activityInterface.get(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + // Access granted + downloadOrOpen(file, folderName, downloadNew); + } else { + this.requestedDownload = new RequestedDownload(file, folderName, downloadNew); + ActivityCompat.requestPermissions(activityInterface.get(), + new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + 1); + } + } + + private void downloadOrOpen(Resource.File file, String folderName, boolean downloadNew) { + KVV kvv = activityInterface.get().getKVV(); + if(isExternalStorageWritable()){ + kvv.getResourceFile(success1 -> { + // Downloading file failed + if (success1.equals("")){ + showDownloadError(); + }else { + if (Regex.has("^http", success1)){ + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(success1)); + contextInterface.get().startActivity(intent); + } + else { + fileOpen(new File(success1)); + } + + } + }, log::e, file.getTitle(), file.getUrl(), folderName, downloadNew); + } + } + + private void showDownloadError() { + Context context = contextInterface.get(); + if (context == null) + return; + AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context); + alertDialogBuilder + .setTitle(R.string.ErrorFileDownload) + .setMessage( + R.string.ErrorFileDownloadText + ) + .setCancelable(true) + .setNeutralButton(R.string.close, (dialog, id) -> dialog.cancel()); + AlertDialog alertDialog = alertDialogBuilder.create(); + alertDialog.show(); + } + + public RequestPermissionsResultListener getRequestPermissionsResultListener() { + return (requestCode, permissions, grantResults) -> { + if (requestedDownload == null) { + log.d("No request"); + return; + } + if (activityInterface.get() == null) { + showDownloadError(); + return; + } + ArrayList intList = new ArrayList<>(); + for (int i : grantResults) + { + intList.add(i); + } + log.d(requestCode, Arrays.asList(permissions), intList); + int pos = Arrays.asList(permissions).indexOf("android.permission.WRITE_EXTERNAL_STORAGE"); + if (pos != -1) { + if (grantResults[pos] != -1) { + downloadOrOpen(requestedDownload.file, requestedDownload.folderName, requestedDownload.downloadNew); + } else { + log.d(requestedDownload, pos, grantResults[pos]); + showDownloadError(); + } + requestedDownload = null; + } + }; + } + + private class RequestedDownload { + Resource.File file; + String folderName; + boolean downloadNew; + + RequestedDownload(Resource.File file, String folderName, boolean downloadNew) { + this.file = file; + this.folderName = folderName; + this.downloadNew = downloadNew; + } + } + + /* Checks if external storage is available for read and write */ + private boolean isExternalStorageWritable() { + String state = Environment.getExternalStorageState(); + if (Environment.MEDIA_MOUNTED.equals(state)) { + return true; + } + log.e("File system: Writing not possible"); + return false; + } + + private void fileOpen(File url){ + Uri uri = Uri.fromFile(url); + + Intent intent = new Intent();//Intent.ACTION_VIEW + // Check what kind of file you are trying to open, by comparing the url with extensions. + // When the if condition is matched, plugin sets the correct intent (mime) type, + // so Android knew what application to use to open the file + if (url.toString().contains(".doc") || url.toString().contains(".docx")) { + // Word document + intent.setDataAndType(uri, "application/msword"); + } else if(url.toString().contains(".pdf")) { + // PDF file + intent.setDataAndType(uri, "application/pdf"); + } else if(url.toString().contains(".ppt") || url.toString().contains(".pptx")) { + // Powerpoint file + intent.setDataAndType(uri, "application/vnd.ms-powerpoint"); + } else if(url.toString().contains(".xls") || url.toString().contains(".xlsx")) { + // Excel file + intent.setDataAndType(uri, "application/vnd.ms-excel"); + } else if(url.toString().contains(".zip") || url.toString().contains(".rar")) { + // ZIP file + intent.setDataAndType(uri, "application/zip"); + } else if(url.toString().contains(".rtf")) { + // RTF file + intent.setDataAndType(uri, "application/rtf"); + } else if(url.toString().contains(".wav") || url.toString().contains(".mp3")) { + // WAV audio file + intent.setDataAndType(uri, "audio/x-wav"); + } else if(url.toString().contains(".gif")) { + // GIF file + intent.setDataAndType(uri, "image/gif"); + } else if(url.toString().contains(".jpg") || url.toString().contains(".jpeg") || url.toString().contains(".png")) { + // JPG file + intent.setDataAndType(uri, "image/jpeg"); + } else if(url.toString().contains(".txt")) { + // Text file + intent.setDataAndType(uri, "text/plain"); + } else if(url.toString().contains(".3gp") || url.toString().contains(".mpg") || url.toString().contains(".mpeg") || url.toString().contains(".mpe") || url.toString().contains(".mp4") || url.toString().contains(".avi")) { + // Video files + intent.setDataAndType(uri, "video/*"); + } else { + //if you want you can also define the intent type for any other file + + //additionally use else clause below, to manage other unknown extensions + //in this case, Android will show all applications installed on the device + //so you can choose which application to use + intent.setDataAndType(uri, "*/*"); + } + + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + contextInterface.get().startActivity(intent); + + } + + @FunctionalInterface + public interface ContextInterface { + @Nullable Context get(); + } + + @FunctionalInterface + public interface ActivityInterface { + @Nullable MainActivity get(); + } + + public interface OnDownloadRequestInterface { + void request(String title, String url); + } +} diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 2aa098c..4221c85 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -56,7 +56,7 @@ Ressourcen Erstellt von: %1$s Letzte Änderung: %1$s - Download + Herunterladen Datei Öffnen Download-Fehler Beim Herunterladen der Datei ist ein Fehler aufgetreten. Prüfe, ob Du mit dem Internet verbunden bist und der App Zugriff auf den Speicher gewährt hast. @@ -70,4 +70,10 @@ %1$d. Anhang %1$s, %2$s - %3$s Entfällt: %1$s + Erneut Herunterladen + Vorlesung + Tutorium + Klausur + Andere + Abgabe \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d120b73..5500875 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -59,7 +59,7 @@ Salads Soups Starters - Others + Other Resources Created by: %1$s Last Modified: %1$s @@ -78,4 +78,10 @@ Attachment #%1$d %1$s, %2$s - %3$s Except: %1$s + Download Again + Lecture + Tutorial + Exam + Other + Deadline