Datei Download für Ankündigung und Aufgaben

This commit is contained in:
Joshua
2018-10-30 20:10:15 +01:00
parent e95b1ecf74
commit a7ff15142f
9 changed files with 430 additions and 217 deletions

View File

@@ -1,5 +1,6 @@
package de.sebse.fuplanner.fragments.moddetails; package de.sebse.fuplanner.fragments.moddetails;
import android.content.res.Resources;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@@ -15,6 +16,7 @@ import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import de.sebse.fuplanner.R; 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.Announcement;
import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.services.KVV.types.Modules;
import de.sebse.fuplanner.tools.Regex; import de.sebse.fuplanner.tools.Regex;
@@ -27,6 +29,11 @@ class ModDetailAnnounceAdapter extends RecyclerView.Adapter<CustomViewHolder> {
@Nullable private Modules.Module mModule = null; @Nullable private Modules.Module mModule = null;
private Logger log = new Logger(this); 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) { public void setModule(Modules.Module module) {
this.mModule = module; this.mModule = module;
@@ -64,16 +71,7 @@ class ModDetailAnnounceAdapter extends RecyclerView.Adapter<CustomViewHolder> {
if (!notes.isEmpty()) { if (!notes.isEmpty()) {
holder.mTagGroup.setVisibility(View.VISIBLE); holder.mTagGroup.setVisibility(View.VISIBLE);
for (int i = 0, notesSize = notes.size(); i < notesSize; i++) { for (int i = 0, notesSize = notes.size(); i < notesSize; i++) {
String name; String name = urlToName(notes.get(i), i, holder.mView.getResources());
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);
}
Tag tag = new Tag(name); Tag tag = new Tag(name);
tag.id = i; tag.id = i;
tag.layoutColor = ContextCompat.getColor(holder.mView.getContext(), R.color.colorFUBlue); tag.layoutColor = ContextCompat.getColor(holder.mView.getContext(), R.color.colorFUBlue);
@@ -84,6 +82,8 @@ class ModDetailAnnounceAdapter extends RecyclerView.Adapter<CustomViewHolder> {
String s = notes.get(i); String s = notes.get(i);
if (s != null) { if (s != null) {
log.d("Download", s); log.d("Download", s);
String name = urlToName(s, i, holder.mView.getResources());
requestInterface.request(name, s);
} }
}); });
} else { } else {
@@ -93,6 +93,19 @@ class ModDetailAnnounceAdapter extends RecyclerView.Adapter<CustomViewHolder> {
} }
} }
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 @Override
public int getItemCount() { public int getItemCount() {
if (mModule != null && mModule.announcements != null) if (mModule != null && mModule.announcements != null)

View File

@@ -1,6 +1,7 @@
package de.sebse.fuplanner.fragments.moddetails; package de.sebse.fuplanner.fragments.moddetails;
import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@@ -13,8 +14,10 @@ import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.MainActivity;
import de.sebse.fuplanner.R; 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.KVV;
import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.services.KVV.types.Modules;
import de.sebse.fuplanner.tools.MainActivityListener;
import de.sebse.fuplanner.tools.logging.Logger; 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 * Use the {@link ModDetailAnnounceFragment#newInstance} factory method to
* create an instance of this fragment. * 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 static final String ARG_POSITION = "itemPosition";
private String mItemPos; private String mItemPos;
private final Logger log = new Logger(this); private final Logger log = new Logger(this);
private ModDetailAnnounceAdapter adapter; private ModDetailAnnounceAdapter adapter;
private SwipeRefreshLayout swipeLayout; private SwipeRefreshLayout swipeLayout;
private Download download;
private MainActivityListener context;
public ModDetailAnnounceFragment() { public ModDetailAnnounceFragment() {
@@ -65,7 +70,7 @@ public class ModDetailAnnounceFragment extends Fragment {
View view = inflater.inflate(R.layout.fragment_recycler_view, container, false); View view = inflater.inflate(R.layout.fragment_recycler_view, container, false);
// Set the adapter // Set the adapter
RecyclerView expandableListView = view.findViewById(R.id.list); RecyclerView expandableListView = view.findViewById(R.id.list);
adapter = new ModDetailAnnounceAdapter(); adapter = new ModDetailAnnounceAdapter(this);
expandableListView.setAdapter(adapter); expandableListView.setAdapter(adapter);
// Getting SwipeContainerLayout // Getting SwipeContainerLayout
@@ -95,4 +100,37 @@ public class ModDetailAnnounceFragment extends Fragment {
}, forceRefresh); }, 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;
}
} }

View File

@@ -1,5 +1,6 @@
package de.sebse.fuplanner.fragments.moddetails; package de.sebse.fuplanner.fragments.moddetails;
import android.content.res.Resources;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@@ -15,6 +16,7 @@ import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import de.sebse.fuplanner.R; 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.Assignment;
import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.services.KVV.types.Modules;
import de.sebse.fuplanner.tools.Regex; import de.sebse.fuplanner.tools.Regex;
@@ -27,6 +29,11 @@ class ModDetailAssignmentAdapter extends RecyclerView.Adapter<CustomViewHolder>
@Nullable private Modules.Module mModule = null; @Nullable private Modules.Module mModule = null;
private Logger log = new Logger(this); 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) { public void setModule(Modules.Module module) {
this.mModule = module; this.mModule = module;
@@ -64,16 +71,7 @@ class ModDetailAssignmentAdapter extends RecyclerView.Adapter<CustomViewHolder>
if (!notes.isEmpty()) { if (!notes.isEmpty()) {
holder.mTagGroup.setVisibility(View.VISIBLE); holder.mTagGroup.setVisibility(View.VISIBLE);
for (int i = 0, notesSize = notes.size(); i < notesSize; i++) { for (int i = 0, notesSize = notes.size(); i < notesSize; i++) {
String name; String name = urlToName(notes.get(i), i, holder.mView.getResources());
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);
}
Tag tag = new Tag(name); Tag tag = new Tag(name);
tag.id = i; tag.id = i;
tag.layoutColor = ContextCompat.getColor(holder.mView.getContext(), R.color.colorFUBlue); tag.layoutColor = ContextCompat.getColor(holder.mView.getContext(), R.color.colorFUBlue);
@@ -84,6 +82,8 @@ class ModDetailAssignmentAdapter extends RecyclerView.Adapter<CustomViewHolder>
String s = notes.get(i); String s = notes.get(i);
if (s != null) { if (s != null) {
log.d("Download", s); log.d("Download", s);
String name = urlToName(s, i, holder.mView.getResources());
requestInterface.request(name, s);
} }
}); });
} else { } else {
@@ -93,6 +93,19 @@ class ModDetailAssignmentAdapter extends RecyclerView.Adapter<CustomViewHolder>
} }
} }
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 @Override
public int getItemCount() { public int getItemCount() {
if (mModule != null && mModule.assignments != null) if (mModule != null && mModule.assignments != null)

View File

@@ -1,6 +1,7 @@
package de.sebse.fuplanner.fragments.moddetails; package de.sebse.fuplanner.fragments.moddetails;
import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@@ -13,8 +14,10 @@ import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.MainActivity;
import de.sebse.fuplanner.R; 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.KVV;
import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.services.KVV.types.Modules;
import de.sebse.fuplanner.tools.MainActivityListener;
import de.sebse.fuplanner.tools.logging.Logger; 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 * Use the {@link ModDetailAssignmentFragment#newInstance} factory method to
* create an instance of this fragment. * 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 static final String ARG_POSITION = "itemPosition";
private String mItemPos; private String mItemPos;
private final Logger log = new Logger(this); private final Logger log = new Logger(this);
private ModDetailAssignmentAdapter adapter; private ModDetailAssignmentAdapter adapter;
private SwipeRefreshLayout swipeLayout; private SwipeRefreshLayout swipeLayout;
private Download download;
private MainActivityListener context;
public ModDetailAssignmentFragment() { public ModDetailAssignmentFragment() {
@@ -65,7 +70,7 @@ public class ModDetailAssignmentFragment extends Fragment {
View view = inflater.inflate(R.layout.fragment_recycler_view, container, false); View view = inflater.inflate(R.layout.fragment_recycler_view, container, false);
// Set the adapter // Set the adapter
RecyclerView expandableListView = view.findViewById(R.id.list); RecyclerView expandableListView = view.findViewById(R.id.list);
adapter = new ModDetailAssignmentAdapter(); adapter = new ModDetailAssignmentAdapter(this);
expandableListView.setAdapter(adapter); expandableListView.setAdapter(adapter);
// Getting SwipeContainerLayout // Getting SwipeContainerLayout
@@ -95,4 +100,37 @@ public class ModDetailAssignmentFragment extends Fragment {
}, forceRefresh); }, 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;
}
} }

View File

@@ -1,5 +1,6 @@
package de.sebse.fuplanner.fragments.moddetails; package de.sebse.fuplanner.fragments.moddetails;
import android.content.res.Resources;
import android.util.Pair; import android.util.Pair;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@@ -124,8 +125,29 @@ class ModDetailEventAdapter extends RecyclerView.Adapter<CustomViewHolder> {
ListViewHolder h; ListViewHolder h;
ModDetailEventAdapterInner adapter; ModDetailEventAdapterInner adapter;
h = (ListViewHolder) holder; h = (ListViewHolder) holder;
Resources resources = h.mView.getResources();
adapter = new ModDetailEventAdapterInner(); 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) { switch (data.first) {
case TYPE_GROUPED: case TYPE_GROUPED:
adapter.setData((GroupedEvents) data.third, h.mView.getContext()); adapter.setData((GroupedEvents) data.third, h.mView.getContext());

View File

@@ -1,45 +1,33 @@
package de.sebse.fuplanner.fragments.moddetails; package de.sebse.fuplanner.fragments.moddetails;
import android.Manifest;
import android.app.AlertDialog;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.MainActivity;
import de.sebse.fuplanner.R; 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.KVV;
import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.services.KVV.types.Modules;
import de.sebse.fuplanner.services.KVV.types.Resource; import de.sebse.fuplanner.services.KVV.types.Resource;
import de.sebse.fuplanner.tools.MainActivityListener; 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.logging.Logger;
import de.sebse.fuplanner.tools.ui.treeview.DirectoryNodeBinder; import de.sebse.fuplanner.tools.ui.treeview.DirectoryNodeBinder;
import de.sebse.fuplanner.tools.ui.treeview.FileNodeBinder; import de.sebse.fuplanner.tools.ui.treeview.FileNodeBinder;
import de.sebse.fuplanner.tools.ui.treeview.TreeNode; import de.sebse.fuplanner.tools.ui.treeview.TreeNode;
import de.sebse.fuplanner.tools.ui.treeview.TreeViewAdapter; import de.sebse.fuplanner.tools.ui.treeview.TreeViewAdapter;
import static androidx.core.content.ContextCompat.checkSelfPermission;
/** /**
* A simple {@link Fragment} subclass. * A simple {@link Fragment} subclass.
* Use the {@link ModDetailResourceFragment#newInstance} factory method to * Use the {@link ModDetailResourceFragment#newInstance} factory method to
@@ -53,7 +41,7 @@ public class ModDetailResourceFragment extends Fragment {
private ModDetailResourceAdapter adapter; private ModDetailResourceAdapter adapter;
private SwipeRefreshLayout swipeLayout; private SwipeRefreshLayout swipeLayout;
private MainActivityListener context; private MainActivityListener context;
private RequestedDownload requestedDownload; private Download download;
public ModDetailResourceFragment() { public ModDetailResourceFragment() {
@@ -81,7 +69,7 @@ public class ModDetailResourceFragment extends Fragment {
if (getArguments() != null) { if (getArguments() != null) {
mItemPos = getArguments().getString(ARG_POSITION); mItemPos = getArguments().getString(ARG_POSITION);
} }
} }
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, 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 } else if(node.getContent() instanceof Resource.File) { // if leaf is file
KVV kvv = ModDetailResourceFragment.this.context.getKVV(); KVV kvv = ModDetailResourceFragment.this.context.getKVV();
kvv.getModule(mItemPos, (Modules.Module module) -> { 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); }, log::e);
} }
return false; return false;
@@ -152,87 +120,14 @@ public class ModDetailResourceFragment extends Fragment {
return view; 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 @Override
public void onAttach(Context context) { public void onAttach(Context context) {
super.onAttach(context); super.onAttach(context);
if (context instanceof MainActivityListener) { if (context instanceof MainActivityListener) {
this.context = ((MainActivityListener) context); this.context = ((MainActivityListener) context);
this.context.addRequestPermissionsResultListener((requestCode, permissions, grantResults) -> { this.context.addRequestPermissionsResultListener(getDownload().getRequestPermissionsResultListener(), "ModDetailResourceFragment");
if (requestedDownload == null) {
log.d("No request");
return;
}
if (getActivity() == null) {
showDownloadError();
return;
}
ArrayList<Integer> 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");
} else } else
throw new RuntimeException(context.toString() + " must implement MainActivityListener"); throw new RuntimeException(context.toString() + " must implement MainActivityListener");
} }
@@ -243,70 +138,6 @@ public class ModDetailResourceFragment extends Fragment {
this.context.removeRequestPermissionsResultListener("ModDetailResourceFragment"); 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) { private void refresh(boolean forceRefresh) {
if (getActivity() != null) { if (getActivity() != null) {
KVV kvv = ((MainActivity) getActivity()).getKVV(); KVV kvv = ((MainActivity) getActivity()).getKVV();
@@ -326,19 +157,15 @@ public class ModDetailResourceFragment extends Fragment {
} }
} }
Download getDownload() {
if (download == null)
download = new Download(this::getContext, () -> (MainActivity) getActivity());
return download;
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;
}
} }
} }

View File

@@ -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<Integer> 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);
}
}

View File

@@ -56,7 +56,7 @@
<string name="resources">Ressourcen</string> <string name="resources">Ressourcen</string>
<string name="creator_name">Erstellt von: %1$s</string> <string name="creator_name">Erstellt von: %1$s</string>
<string name="last_modified_on">Letzte Änderung: %1$s</string> <string name="last_modified_on">Letzte Änderung: %1$s</string>
<string name="download">Download</string> <string name="download">Herunterladen</string>
<string name="openFile">Datei Öffnen</string> <string name="openFile">Datei Öffnen</string>
<string name="ErrorFileDownload">Download-Fehler</string> <string name="ErrorFileDownload">Download-Fehler</string>
<string name="ErrorFileDownloadText">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.</string> <string name="ErrorFileDownloadText">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.</string>
@@ -70,4 +70,10 @@
<string name="attachment_nr">%1$d. Anhang</string> <string name="attachment_nr">%1$d. Anhang</string>
<string name="event_scale">%1$s, %2$s - %3$s</string> <string name="event_scale">%1$s, %2$s - %3$s</string>
<string name="except_list">Entfällt: %1$s</string> <string name="except_list">Entfällt: %1$s</string>
<string name="download_again">Erneut Herunterladen</string>
<string name="lecture">Vorlesung</string>
<string name="tutorial">Tutorium</string>
<string name="exam">Klausur</string>
<string name="other">Andere</string>
<string name="deadline">Abgabe</string>
</resources> </resources>

View File

@@ -59,7 +59,7 @@
<string name="salads">Salads</string> <string name="salads">Salads</string>
<string name="soups">Soups</string> <string name="soups">Soups</string>
<string name="starters">Starters</string> <string name="starters">Starters</string>
<string name="others">Others</string> <string name="others">Other</string>
<string name="resources">Resources</string> <string name="resources">Resources</string>
<string name="creator_name">Created by: %1$s</string> <string name="creator_name">Created by: %1$s</string>
<string name="last_modified_on">Last Modified: %1$s</string> <string name="last_modified_on">Last Modified: %1$s</string>
@@ -78,4 +78,10 @@
<string name="attachment_nr">Attachment #%1$d</string> <string name="attachment_nr">Attachment #%1$d</string>
<string name="event_scale">%1$s, %2$s - %3$s</string> <string name="event_scale">%1$s, %2$s - %3$s</string>
<string name="except_list">Except: %1$s</string> <string name="except_list">Except: %1$s</string>
<string name="download_again">Download Again</string>
<string name="lecture">Lecture</string>
<string name="tutorial">Tutorial</string>
<string name="exam">Exam</string>
<string name="other">Other</string>
<string name="deadline">Deadline</string>
</resources> </resources>