diff --git a/app/build.gradle b/app/build.gradle
index d8a01d0d..3b463434 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -4,7 +4,6 @@ apply plugin: 'io.fabric'
android {
compileSdkVersion 27
- buildToolsVersion "27.0.3"
defaultConfig {
vectorDrawables.useSupportLibrary = true
@@ -35,9 +34,9 @@ dependencies {
implementation 'com.android.support:support-v4:27.1.1'
implementation 'com.android.support:cardview-v7:27.1.1'
implementation 'com.android.support:recyclerview-v7:27.1.1'
- implementation 'com.google.firebase:firebase-core:16.0.0'
+ implementation 'com.google.firebase:firebase-core:16.0.1'
implementation 'com.google.firebase:firebase-messaging:17.0.0'
- implementation 'com.crashlytics.sdk.android:crashlytics:2.9.3'
+ implementation 'com.crashlytics.sdk.android:crashlytics:2.9.4'
implementation 'com.squareup.okhttp3:okhttp:3.10.0'
implementation 'com.squareup.picasso:picasso:2.5.2'
implementation 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index bca9ca45..c9bfa2af 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -116,9 +116,6 @@
android:resource="@xml/provider_paths" />
-
@@ -126,16 +123,6 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardActivity.java
index c6620218..251c7c2b 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardActivity.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/board/BoardActivity.java
@@ -25,8 +25,8 @@ import gr.thmmy.mthmmy.model.Board;
import gr.thmmy.mthmmy.model.Bookmark;
import gr.thmmy.mthmmy.model.ThmmyPage;
import gr.thmmy.mthmmy.model.Topic;
-import gr.thmmy.mthmmy.utils.parsing.ParseTask;
import gr.thmmy.mthmmy.utils.parsing.ParseException;
+import gr.thmmy.mthmmy.utils.parsing.ParseTask;
import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
import timber.log.Timber;
@@ -298,7 +298,7 @@ public class BoardActivity extends BaseActivity implements BoardAdapter.OnLoadMo
}
@Override
- protected void postParsing(ResultCode result) {
+ protected void postExecution(ResultCode result) {
//TODO if (result == ResultCode.SUCCESS)...
if (boardTitle == null || Objects.equals(boardTitle, "")
|| !Objects.equals(boardTitle, parsedTitle)) {
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsActivity.java
index 6d899d23..93d92f1a 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsActivity.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsActivity.java
@@ -20,11 +20,15 @@ import java.util.Objects;
import gr.thmmy.mthmmy.R;
import gr.thmmy.mthmmy.base.BaseActivity;
+import gr.thmmy.mthmmy.base.BaseApplication;
import gr.thmmy.mthmmy.model.Download;
import gr.thmmy.mthmmy.model.ThmmyPage;
-import gr.thmmy.mthmmy.utils.parsing.ParseTask;
import gr.thmmy.mthmmy.utils.parsing.ParseException;
+import gr.thmmy.mthmmy.utils.parsing.ParseTask;
import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
import timber.log.Timber;
public class DownloadsActivity extends BaseActivity implements DownloadsAdapter.OnLoadMoreListener {
@@ -158,13 +162,16 @@ public class DownloadsActivity extends BaseActivity implements DownloadsAdapter.
/**
* An {@link ParseTask} that handles asynchronous fetching of a downloads page and parsing it's
- * data. {@link ParseTask#postParsing(ResultCode) postParsing} method calls {@link RecyclerView#swapAdapter}
+ * data. {@link ParseTask#postExecution(ResultCode) postExecution} method calls {@link RecyclerView#swapAdapter}
* to build graphics.
*
*
Calling TopicTask's {@link ParseTask#execute execute} method needs to have profile's url
* as String parameter!
*/
private class ParseDownloadPageTask extends ParseTask {
+ private Download.DownloadItemType type;
+ private Download download;
+
@Override
protected void onPreExecute() {
if (!isLoadingMore) progressBar.setVisibility(ProgressBar.VISIBLE);
@@ -173,69 +180,89 @@ public class DownloadsActivity extends BaseActivity implements DownloadsAdapter.
@Override
protected void parse(Document downloadPage) throws ParseException {
- if (downloadsTitle == null || Objects.equals(downloadsTitle, ""))
- downloadsTitle = downloadPage.select("div.nav>b>a.nav").last().text();
+ try{
+ if (downloadsTitle == null || Objects.equals(downloadsTitle, ""))
+ downloadsTitle = downloadPage.select("div.nav>b>a.nav").last().text();
- //Removes loading item
- if (isLoadingMore) {
- if (parsedDownloads.size() > 0) parsedDownloads.remove(parsedDownloads.size() - 1);
- }
-
- Download.DownloadItemType type;
- if (ThmmyPage.resolvePageCategory(Uri.parse(url)).is(ThmmyPage.
- PageCategory.DOWNLOADS_CATEGORY))
- type = Download.DownloadItemType.DOWNLOADS_CATEGORY;
- else type = Download.DownloadItemType.DOWNLOADS_FILE;
-
- Elements pages = downloadPage.select("a.navPages");
- if (pages != null) {
- for (Element page : pages) {
- int pageNumber = Integer.parseInt(page.text());
- if (pageNumber > numberOfPages) numberOfPages = pageNumber;
+ //Removes loading item
+ if (isLoadingMore) {
+ if (parsedDownloads.size() > 0) parsedDownloads.remove(parsedDownloads.size() - 1);
}
- } else numberOfPages = 1;
-
- Elements rows = downloadPage.select("table.tborder>tbody>tr");
- if (type == Download.DownloadItemType.DOWNLOADS_CATEGORY) {
- Elements navigationLinks = downloadPage.select("div.nav>b");
- for (Element row : rows) {
- if (row.select("td").size() == 1) continue;
-
- String url = row.select("b>a").first().attr("href"),
- title = row.select("b>a").first().text(),
- subtitle = row.select("div.smalltext:not(:has(a))").text();
- if (!row.select("td").last().hasClass("windowbg2")) {
- if (navigationLinks.size() < 4) {
-
- parsedDownloads.add(new Download(type, url, title, subtitle, null,
- true, null));
+
+ if (ThmmyPage.resolvePageCategory(Uri.parse(url)).is(ThmmyPage.PageCategory.DOWNLOADS_CATEGORY))
+ type = Download.DownloadItemType.DOWNLOADS_CATEGORY;
+ else
+ type = Download.DownloadItemType.DOWNLOADS_FILE;
+
+ Elements pages = downloadPage.select("a.navPages");
+ if (pages != null) {
+ for (Element page : pages) {
+ int pageNumber = Integer.parseInt(page.text());
+ if (pageNumber > numberOfPages) numberOfPages = pageNumber;
+ }
+ } else numberOfPages = 1;
+
+ Elements rows = downloadPage.select("table.tborder>tbody>tr");
+ if (type == Download.DownloadItemType.DOWNLOADS_CATEGORY) {
+ Elements navigationLinks = downloadPage.select("div.nav>b");
+ for (Element row : rows) {
+ if (row.select("td").size() == 1) continue;
+
+ String url = row.select("b>a").first().attr("href"),
+ title = row.select("b>a").first().text(),
+ subtitle = row.select("div.smalltext:not(:has(a))").text();
+ if (!row.select("td").last().hasClass("windowbg2")) {
+ if (navigationLinks.size() < 4) {
+
+ parsedDownloads.add(new Download(type, url, title, subtitle, null,
+ true, null));
+ } else {
+ String stats = row.text();
+ stats = stats.replace(title, "").replace(subtitle, "").trim();
+ parsedDownloads.add(new Download(type, url, title, subtitle, stats,
+ false, null));
+ }
} else {
String stats = row.text();
stats = stats.replace(title, "").replace(subtitle, "").trim();
parsedDownloads.add(new Download(type, url, title, subtitle, stats,
false, null));
}
- } else {
- String stats = row.text();
- stats = stats.replace(title, "").replace(subtitle, "").trim();
- parsedDownloads.add(new Download(type, url, title, subtitle, stats,
- false, null));
}
+ } else {
+ download = new Download(type,
+ rows.select("b>a").first().attr("href"),
+ rows.select("b>a").first().text(),
+ rows.select("div.smalltext:not(:has(a))").text(),
+ rows.select("span:not(:has(a))").first().text(),
+ false,
+ rows.select("span:has(a)").first().text());
+ parsedDownloads.add(download);
}
- } else {
- parsedDownloads.add(new Download(type,
- rows.select("b>a").first().attr("href"),
- rows.select("b>a").first().text(),
- rows.select("div.smalltext:not(:has(a))").text(),
- rows.select("span:not(:has(a))").first().text(),
- false,
- rows.select("span:has(a)").first().text()));
+ }catch(Exception e){
+ throw new ParseException("Parsing failed (DownloadsActivity)");
}
}
+ @Override
+ protected void postParsing() {
+ if (type == Download.DownloadItemType.DOWNLOADS_FILE) {
+ OkHttpClient client = BaseApplication.getInstance().getClient();
+ String fileName = null;
+ try {
+ Response response = client.newCall(new Request.Builder().url(download.getUrl()).build()).execute();
+ String contentDisposition = response.headers("Content-Disposition").toString(); //check if link provides an attachment
+ if (contentDisposition.contains("attachment"))
+ fileName = contentDisposition.split("\"")[1];
+ download.setFileName(fileName);
+ } catch (Exception e) {
+ Timber.e(e, "Couldn't extract fileName.");
+ }
+ }
+ }
@Override
- protected void postParsing(ResultCode result) {
+ protected void postExecution(ResultCode result) {
if (downloadsTitle != null && !downloadsTitle.equals("")
&& !downloadsTitle.equals("Αρχεία για λήψη")
&& toolbar.getTitle() != downloadsTitle)
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsAdapter.java b/app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsAdapter.java
index 7a7bf17f..5395b447 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsAdapter.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsAdapter.java
@@ -127,8 +127,8 @@ class DownloadsAdapter extends RecyclerView.Adapter {
@Override
public void onClick(View view) {
try {
- ((BaseActivity) context).launchDownloadService(new ThmmyFile(
- new URL(download.getUrl()), null, null));
+ ((BaseActivity) context).downloadFile(new ThmmyFile(
+ new URL(download.getUrl()), download.getFileName(), null));
} catch (MalformedURLException e) {
e.printStackTrace();
}
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/main/forum/ForumFragment.java b/app/src/main/java/gr/thmmy/mthmmy/activities/main/forum/ForumFragment.java
index 02da2734..3b6366b4 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/activities/main/forum/ForumFragment.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/main/forum/ForumFragment.java
@@ -27,8 +27,8 @@ import gr.thmmy.mthmmy.model.Board;
import gr.thmmy.mthmmy.model.Category;
import gr.thmmy.mthmmy.session.SessionManager;
import gr.thmmy.mthmmy.utils.CustomRecyclerView;
-import gr.thmmy.mthmmy.utils.parsing.ParseTask;
import gr.thmmy.mthmmy.utils.parsing.ParseException;
+import gr.thmmy.mthmmy.utils.parsing.ParseTask;
import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
import okhttp3.HttpUrl;
import okhttp3.Request;
@@ -215,7 +215,7 @@ public class ForumFragment extends BaseFragment {
}
@Override
- protected void postParsing(ParseTask.ResultCode result) {
+ protected void postExecution(ParseTask.ResultCode result) {
if (result == ResultCode.SUCCESS)
forumAdapter.notifyParentDataSetChanged(false);
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/main/recent/RecentFragment.java b/app/src/main/java/gr/thmmy/mthmmy/activities/main/recent/RecentFragment.java
index 5dab8c1e..aee35e37 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/activities/main/recent/RecentFragment.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/main/recent/RecentFragment.java
@@ -24,8 +24,8 @@ import gr.thmmy.mthmmy.base.BaseFragment;
import gr.thmmy.mthmmy.model.TopicSummary;
import gr.thmmy.mthmmy.session.SessionManager;
import gr.thmmy.mthmmy.utils.CustomRecyclerView;
-import gr.thmmy.mthmmy.utils.parsing.ParseTask;
import gr.thmmy.mthmmy.utils.parsing.ParseException;
+import gr.thmmy.mthmmy.utils.parsing.ParseTask;
import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
import timber.log.Timber;
@@ -190,7 +190,7 @@ public class RecentFragment extends BaseFragment {
}
@Override
- protected void postParsing(ParseTask.ResultCode result) {
+ protected void postExecution(ParseTask.ResultCode result) {
if (result == ResultCode.SUCCESS)
{
topicSummaries.clear();
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/main/unread/UnreadFragment.java b/app/src/main/java/gr/thmmy/mthmmy/activities/main/unread/UnreadFragment.java
index 7b42fb20..98be97e2 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/activities/main/unread/UnreadFragment.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/main/unread/UnreadFragment.java
@@ -25,8 +25,8 @@ import gr.thmmy.mthmmy.base.BaseFragment;
import gr.thmmy.mthmmy.model.TopicSummary;
import gr.thmmy.mthmmy.session.SessionManager;
import gr.thmmy.mthmmy.utils.CustomRecyclerView;
-import gr.thmmy.mthmmy.utils.parsing.ParseTask;
import gr.thmmy.mthmmy.utils.parsing.ParseException;
+import gr.thmmy.mthmmy.utils.parsing.ParseTask;
import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
import okhttp3.Request;
import timber.log.Timber;
@@ -204,7 +204,7 @@ public class UnreadFragment extends BaseFragment {
}
@Override
- protected void postParsing(ParseTask.ResultCode result) {
+ protected void postExecution(ParseTask.ResultCode result) {
if (result == ResultCode.SUCCESS)
unreadAdapter.notifyDataSetChanged();
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java
index 40bb41f1..54560b58 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java
@@ -238,7 +238,7 @@ class TopicAdapter extends RecyclerView.Adapter {
attached.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
- ((BaseActivity) context).launchDownloadService(attachedFile);
+ ((BaseActivity) context).downloadFile(attachedFile);
}
});
diff --git a/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java b/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java
index 833f7028..d5cb13ec 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java
@@ -7,16 +7,21 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
+import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
+import android.support.design.widget.BottomSheetDialog;
import android.support.v4.content.ContextCompat;
+import android.support.v4.content.FileProvider;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.view.View;
+import android.widget.Button;
import android.widget.ImageButton;
+import android.widget.TextView;
import android.widget.Toast;
import com.google.firebase.messaging.FirebaseMessaging;
@@ -32,6 +37,7 @@ import com.mikepenz.materialdrawer.model.ProfileDrawerItem;
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem;
import com.mikepenz.materialdrawer.model.interfaces.IProfile;
+import java.io.File;
import java.util.ArrayList;
import gr.thmmy.mthmmy.R;
@@ -43,9 +49,11 @@ import gr.thmmy.mthmmy.activities.main.MainActivity;
import gr.thmmy.mthmmy.activities.profile.ProfileActivity;
import gr.thmmy.mthmmy.model.Bookmark;
import gr.thmmy.mthmmy.model.ThmmyFile;
-import gr.thmmy.mthmmy.services.downloads.DownloadsService;
+import gr.thmmy.mthmmy.services.DownloadHelper;
import gr.thmmy.mthmmy.session.SessionManager;
+import gr.thmmy.mthmmy.utils.FileUtils;
import okhttp3.OkHttpClient;
+import timber.log.Timber;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static gr.thmmy.mthmmy.activities.downloads.DownloadsActivity.BUNDLE_DOWNLOADS_TITLE;
@@ -53,6 +61,8 @@ import static gr.thmmy.mthmmy.activities.downloads.DownloadsActivity.BUNDLE_DOWN
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_THUMBNAIL_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_USERNAME;
+import static gr.thmmy.mthmmy.services.DownloadHelper.SAVE_DIR;
+import static gr.thmmy.mthmmy.utils.FileUtils.getMimeType;
public abstract class BaseActivity extends AppCompatActivity {
// Client & Cookies
@@ -600,7 +610,7 @@ public abstract class BaseActivity extends AppCompatActivity {
, @NonNull int[] grantResults) {
switch (permsRequestCode) {
case PERMISSIONS_REQUEST_CODE:
- launchDownloadService();
+ downloadFile();
break;
}
}
@@ -609,9 +619,9 @@ public abstract class BaseActivity extends AppCompatActivity {
//----------------------------------DOWNLOAD----------------------
private ThmmyFile tempThmmyFile;
- public void launchDownloadService(ThmmyFile thmmyFile) {
+ public void downloadFile(ThmmyFile thmmyFile) {
if (checkPerms())
- DownloadsService.startActionDownload(this, thmmyFile.getFileUrl().toString());
+ prepareDownload(thmmyFile);
else {
tempThmmyFile = thmmyFile;
requestPerms();
@@ -619,15 +629,64 @@ public abstract class BaseActivity extends AppCompatActivity {
}
//Uses temp file - called after permission grant
- private void launchDownloadService() {
+ private void downloadFile() {
if (checkPerms())
- DownloadsService.startActionDownload(this, tempThmmyFile.getFileUrl().toString());
+ prepareDownload(tempThmmyFile);
+ }
+
+ private void prepareDownload(ThmmyFile thmmyFile){
+ String fileName = thmmyFile.getFilename();
+ if(FileUtils.fileNameExists(fileName))
+ openDownloadPrompt(thmmyFile);
+ else
+ DownloadHelper.enqueueDownload(thmmyFile);
+ }
+
+ private void openDownloadPrompt(final ThmmyFile thmmyFile) {
+ View view = getLayoutInflater().inflate(R.layout.download_prompt_dialog, null);
+ final BottomSheetDialog dialog = new BottomSheetDialog(this);
+ dialog.setContentView(view);
+ TextView downloadPromptTextView = view.findViewById(R.id.downloadPromptTextView);
+ downloadPromptTextView.setText(getString(R.string.downloadPromptText,thmmyFile.getFilename()));
+ Button cancelButton = view.findViewById(R.id.cancel);
+ Button openButton = view.findViewById(R.id.open);
+ Button downloadButton = view.findViewById(R.id.download);
+ cancelButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ dialog.dismiss();
+ }
+ });
+ openButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ dialog.dismiss();
+ try{
+ String fileName = thmmyFile.getFilename();
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ Uri fileUri = FileProvider.getUriForFile(getApplicationContext(), getPackageName() + ".provider", new File(SAVE_DIR, fileName));
+ intent.setDataAndType(fileUri, getMimeType(fileName));
+ BaseActivity.this.startActivity(intent);
+ }catch (Exception e){
+ Timber.e(e,"Couldn't open downloaded file...");
+ Toast.makeText(BaseActivity.this, "Couldn't open file...", Toast.LENGTH_SHORT).show();
+ }
+ }
+ });
+ downloadButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ dialog.dismiss();
+ DownloadHelper.enqueueDownload(thmmyFile);
+ }
+ });
+ dialog.show();
}
//----------------------------------MISC----------------------
protected void setMainActivity(MainActivity mainActivity) {
this.mainActivity = mainActivity;
}
-
}
diff --git a/app/src/main/java/gr/thmmy/mthmmy/model/Download.java b/app/src/main/java/gr/thmmy/mthmmy/model/Download.java
index 5216fea4..045129b8 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/model/Download.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/model/Download.java
@@ -6,6 +6,7 @@ public class Download {
private final String url, title, subTitle, statNumbers, extraInfo;
private final boolean hasSubCategory;
private final DownloadItemType type;
+ private String fileName;
public Download() {
type = null;
@@ -55,4 +56,12 @@ public class Download {
public boolean hasSubCategory() {
return hasSubCategory;
}
+
+ public String getFileName(){
+ return fileName;
+ }
+
+ public void setFileName(String fileName){
+ this.fileName = fileName;
+ }
}
diff --git a/app/src/main/java/gr/thmmy/mthmmy/model/ThmmyPage.java b/app/src/main/java/gr/thmmy/mthmmy/model/ThmmyPage.java
index aff0a38a..bc451fd1 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/model/ThmmyPage.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/model/ThmmyPage.java
@@ -3,8 +3,6 @@ package gr.thmmy.mthmmy.model;
import android.net.Uri;
import java.util.Objects;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
import timber.log.Timber;
diff --git a/app/src/main/java/gr/thmmy/mthmmy/services/DownloadHelper.java b/app/src/main/java/gr/thmmy/mthmmy/services/DownloadHelper.java
new file mode 100644
index 00000000..1e1a5c31
--- /dev/null
+++ b/app/src/main/java/gr/thmmy/mthmmy/services/DownloadHelper.java
@@ -0,0 +1,73 @@
+package gr.thmmy.mthmmy.services;
+
+import android.app.DownloadManager;
+import android.content.Context;
+import android.net.Uri;
+import android.os.Environment;
+import android.widget.Toast;
+
+import java.io.File;
+
+import gr.thmmy.mthmmy.base.BaseApplication;
+import gr.thmmy.mthmmy.model.ThmmyFile;
+import okhttp3.Cookie;
+import timber.log.Timber;
+
+import static gr.thmmy.mthmmy.utils.FileUtils.getMimeType;
+
+/**
+ * Not an actual service, but simply a helper class that adds a download to the queue of Android's
+ * DownloadManager system service.
+ */
+public class DownloadHelper {
+ public static final File SAVE_DIR = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
+
+ public static void enqueueDownload(ThmmyFile thmmyFile){
+ Context applicationContext = BaseApplication.getInstance().getApplicationContext();
+ Toast.makeText(applicationContext, "Download started!", Toast.LENGTH_SHORT).show();
+
+ try {
+ String fileName = renameFileIfExists(thmmyFile.getFilename());
+ Uri downloadURI = Uri.parse(thmmyFile.getFileUrl().toString());
+
+ DownloadManager downloadManager = (DownloadManager)applicationContext.getSystemService(Context.DOWNLOAD_SERVICE);
+ DownloadManager.Request request = new DownloadManager.Request(downloadURI);
+
+ Cookie thmmyCookie = BaseApplication.getInstance().getSessionManager().getThmmyCookie();
+ request.addRequestHeader("Cookie", thmmyCookie.name() + "=" + thmmyCookie.value());
+ request.setTitle(fileName);
+ request.setMimeType(getMimeType(fileName));
+ request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
+ request.setDestinationInExternalPublicDir(SAVE_DIR.getName(), fileName);
+ request.allowScanningByMediaScanner();
+
+ downloadManager.enqueue(request);
+ } catch (Exception e) {
+ Toast.makeText(applicationContext, "Download failed...", Toast.LENGTH_SHORT).show();
+ Timber.e(e, "Exception while enqueuing download.");
+ }
+ }
+
+ private static String renameFileIfExists(String originalFileName) {
+ final String dirPath = SAVE_DIR.getAbsolutePath();
+ File file = new File(dirPath, originalFileName);
+
+ String nameFormat;
+ String[] tokens = originalFileName.split("\\.(?=[^.]+$)");
+
+ if (tokens.length != 2) {
+ Timber.w("Couldn't get file extension...");
+ nameFormat = originalFileName + "(%d)";
+ } else
+ nameFormat = tokens[0] + "-%d." + tokens[1];
+
+ for (int i = 1; ; i++) {
+ if (!file.isFile())
+ break;
+
+ file = new File(dirPath, String.format(nameFormat, i));
+ }
+
+ return file.getName();
+ }
+}
diff --git a/app/src/main/java/gr/thmmy/mthmmy/services/downloads/DownloadsReceiver.java b/app/src/main/java/gr/thmmy/mthmmy/services/downloads/DownloadsReceiver.java
deleted file mode 100644
index 535372a4..00000000
--- a/app/src/main/java/gr/thmmy/mthmmy/services/downloads/DownloadsReceiver.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package gr.thmmy.mthmmy.services.downloads;
-
-import android.app.NotificationChannel;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Bundle;
-import android.support.v4.app.NotificationCompat;
-import android.webkit.MimeTypeMap;
-
-import java.io.File;
-
-import timber.log.Timber;
-
-import static gr.thmmy.mthmmy.services.downloads.DownloadsService.ACTION_DOWNLOAD;
-import static gr.thmmy.mthmmy.services.downloads.DownloadsService.COMPLETED;
-import static gr.thmmy.mthmmy.services.downloads.DownloadsService.EXTRA_DOWNLOAD_ID;
-import static gr.thmmy.mthmmy.services.downloads.DownloadsService.EXTRA_DOWNLOAD_STATE;
-import static gr.thmmy.mthmmy.services.downloads.DownloadsService.EXTRA_FILE_NAME;
-import static gr.thmmy.mthmmy.services.downloads.DownloadsService.EXTRA_NOTIFICATION_TEXT;
-import static gr.thmmy.mthmmy.services.downloads.DownloadsService.EXTRA_NOTIFICATION_TICKER;
-import static gr.thmmy.mthmmy.services.downloads.DownloadsService.EXTRA_NOTIFICATION_TITLE;
-import static gr.thmmy.mthmmy.services.downloads.DownloadsService.SAVE_DIR;
-import static gr.thmmy.mthmmy.services.downloads.DownloadsService.STARTED;
-
-public class DownloadsReceiver extends BroadcastReceiver {
- private static final String NOTIFICATION_TAG = "DOWNLOADS";
- private static final String DOWNLOADS_CHANNEL_ID = "Downloads";
- private static final String DOWNLOADS_CHANNEL_NAME = "Downloads";
-
- public DownloadsReceiver() {}
-
- @Override
- public void onReceive(Context context, Intent intent) {
- NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, DOWNLOADS_CHANNEL_ID);
- NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
-
- if (intent.getAction().equals(ACTION_DOWNLOAD)) {
- Bundle extras = intent.getExtras();
- int id = extras.getInt(EXTRA_DOWNLOAD_ID);
- String state = extras.getString(EXTRA_DOWNLOAD_STATE, "NONE");
- String title = extras.getString(EXTRA_NOTIFICATION_TITLE);
- String text = extras.getString(EXTRA_NOTIFICATION_TEXT);
- String ticker = extras.getString(EXTRA_NOTIFICATION_TICKER);
-
- notificationBuilder.setContentTitle(title)
- .setContentText(text)
- .setTicker(ticker)
- .setAutoCancel(true);
-
- if (state.equals(STARTED))
- notificationBuilder.setOngoing(true)
- .setSmallIcon(android.R.drawable.stat_sys_download);
- else if (state.equals(COMPLETED)) {
- String fileName = extras.getString(EXTRA_FILE_NAME, "NONE");
-
- File file = new File(SAVE_DIR, fileName);
- if (file.exists()) {
- String type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
- MimeTypeMap.getFileExtensionFromUrl(file.getAbsolutePath()));
-
-
- Intent chooserIntent = new Intent(Intent.ACTION_VIEW);
- chooserIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- chooserIntent.setDataAndType(Uri.fromFile(file), type);
- Intent chooser = Intent.createChooser(chooserIntent, "Open With...");
-
- PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, chooser, PendingIntent.FLAG_CANCEL_CURRENT);
- notificationBuilder.setContentIntent(pendingIntent)
- .setSmallIcon(android.R.drawable.stat_sys_download_done);
-
- } else
- Timber.w("File doesn't exist.");
- }
-
- // Since Android Oreo notification channel is needed.
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
- notificationManager.createNotificationChannel(new NotificationChannel(DOWNLOADS_CHANNEL_ID, DOWNLOADS_CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH));
-
- notificationManager.notify(NOTIFICATION_TAG, id, notificationBuilder.build());
- }
- }
-
-}
diff --git a/app/src/main/java/gr/thmmy/mthmmy/services/downloads/DownloadsService.java b/app/src/main/java/gr/thmmy/mthmmy/services/downloads/DownloadsService.java
deleted file mode 100644
index 9692f5ea..00000000
--- a/app/src/main/java/gr/thmmy/mthmmy/services/downloads/DownloadsService.java
+++ /dev/null
@@ -1,225 +0,0 @@
-package gr.thmmy.mthmmy.services.downloads;
-
-import android.app.DownloadManager;
-import android.app.IntentService;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Environment;
-import android.support.annotation.NonNull;
-import android.webkit.MimeTypeMap;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-
-import gr.thmmy.mthmmy.base.BaseApplication;
-import okhttp3.OkHttpClient;
-import okhttp3.Request;
-import okhttp3.Response;
-import okio.BufferedSink;
-import okio.Okio;
-import timber.log.Timber;
-
-/**
- * An {@link IntentService} subclass for handling asynchronous task requests in
- * a service on a separate handler thread.
- */
-public class DownloadsService extends IntentService {
- private static final String TAG = "DownloadsService";
- private static int sDownloadId = 0;
-
- private DownloadsReceiver receiver;
-
- public static final String SAVE_DIR = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "mthmmy";
-
- public static final String ACTION_DOWNLOAD = "gr.thmmy.mthmmy.services.action.DOWNLOAD";
- public static final String EXTRA_DOWNLOAD_URL = "gr.thmmy.mthmmy.services.extra.DOWNLOAD_URL";
-
- public static final String EXTRA_DOWNLOAD_ID = "gr.thmmy.mthmmy.services.extra.DOWNLOAD_ID";
- public static final String EXTRA_DOWNLOAD_STATE = "gr.thmmy.mthmmy.services.extra.DOWNLOAD_STATE";
- public static final String EXTRA_FILE_NAME = "gr.thmmy.mthmmy.services.extra.FILE_NAME";
- public static final String EXTRA_NOTIFICATION_TITLE = "gr.thmmy.mthmmy.services.extra.NOTIFICATION_TITLE";
- public static final String EXTRA_NOTIFICATION_TEXT = "gr.thmmy.mthmmy.services.extra.NOTIFICATION_TEXT";
- public static final String EXTRA_NOTIFICATION_TICKER = "gr.thmmy.mthmmy.services.extra.NOTIFICATION_TICKER";
-
- public static final String STARTED = "Started";
- public static final String COMPLETED = "Completed";
- public static final String FAILED = "Failed";
-
-
- public DownloadsService() {
- super("DownloadsService");
- }
-
- @Override
- public void onCreate() {
- super.onCreate();
- final IntentFilter filter = new IntentFilter(DownloadsService.ACTION_DOWNLOAD);
- receiver = new DownloadsReceiver();
- registerReceiver(receiver, filter);
-
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- this.unregisterReceiver(receiver);
- }
-
- /**
- * Starts this service to perform action Download with the given parameters. If
- * the service is already performing a task this action will be queued.
- *
- * @see IntentService
- */
- public static void startActionDownload(Context context, String downloadUrl) {
- Intent intent = new Intent(context, DownloadsService.class);
- intent.setAction(ACTION_DOWNLOAD);
- intent.putExtra(EXTRA_DOWNLOAD_URL, downloadUrl);
- context.startService(intent);
- }
-
- @Override
- protected void onHandleIntent(Intent intent) {
- if (intent != null) {
- final String action = intent.getAction();
- if (ACTION_DOWNLOAD.equals(action)) {
- final String downloadLink = intent.getStringExtra(EXTRA_DOWNLOAD_URL);
- handleActionDownload(downloadLink);
- }
- }
- }
-
- /**
- * Handle action Foo in the provided background thread with the provided
- * parameters.
- */
- private void handleActionDownload(String downloadLink) {
- OkHttpClient client = BaseApplication.getInstance().getClient();
- BufferedSink sink = null;
- String fileName = "file";
-
- int downloadId = sDownloadId;
- sDownloadId++;
-
- try {
- Request request = new Request.Builder().url(downloadLink).build();
- Response response = client.newCall(request).execute();
-
- String contentDisposition = response.headers("Content-Disposition").toString(); //check if link provides an attachment
- if (contentDisposition.contains("attachment")) {
- fileName = contentDisposition.split("\"")[1];
-
- File dirPath = new File(SAVE_DIR);
- if (!dirPath.isDirectory()) {
- if (dirPath.mkdirs())
- Timber.i("mTHMMY's directory created successfully!");
- else
- Timber.e("Couldn't create mTHMMY's directory...");
- }
-
-
- String nameFormat;
- String[] tokens = fileName.split("\\.(?=[^\\.]+$)");
-
- if (tokens.length != 2) {
- Timber.w("Couldn't get file extension...");
- nameFormat = fileName + "(%d)";
- } else
- nameFormat = tokens[0] + "(%d)." + tokens[1];
-
-
- File file = new File(dirPath, fileName);
-
- for (int i = 1; ; i++) {
- if (!file.exists())
- break;
-
- file = new File(dirPath, String.format(nameFormat, i));
- }
-
- fileName = file.getName();
-
- Timber.v("Started saving file %s", fileName);
- sendNotification(downloadId, STARTED, fileName);
-
- sink = Okio.buffer(Okio.sink(file));
- sink.writeAll(response.body().source());
- sink.flush();
- Timber.i("Download OK!");
- sendNotification(downloadId, COMPLETED, fileName);
-
- // Register download
- DownloadManager mManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
- long length = file.length();
- mManager.addCompletedDownload(fileName, fileName, false, getMimeType(file), SAVE_DIR +File.separator+ fileName, length, false);
-
- } else
- Timber.e("No attachment in response!");
- } catch (FileNotFoundException e) {
- Timber.i("Download failed...");
- Timber.e(e, "FileNotFound");
- sendNotification(downloadId, FAILED, fileName);
- } catch (IOException e) {
- Timber.i("Download failed...");
- Timber.e(e, "IOException");
- sendNotification(downloadId, FAILED, fileName);
- } finally {
- if (sink != null) {
- try {
- sink.close();
- } catch (IOException e) {
- // Ignore - Significant errors should already have been reported
- }
- }
- }
- }
-
- private void sendNotification(int downloadId, String type, @NonNull String fileName) {
- Intent intent = new Intent(ACTION_DOWNLOAD);
- switch (type) {
- case STARTED: {
- intent.putExtra(EXTRA_NOTIFICATION_TITLE, "\"" + fileName + "\"");
- intent.putExtra(EXTRA_NOTIFICATION_TEXT, "Download Started");
- intent.putExtra(EXTRA_NOTIFICATION_TICKER, "Downloading...");
- break;
- }
- case COMPLETED: {
- intent.putExtra(EXTRA_NOTIFICATION_TITLE, "\"" + fileName + "\"");
- intent.putExtra(EXTRA_NOTIFICATION_TEXT, "Download Completed");
- intent.putExtra(EXTRA_NOTIFICATION_TICKER, "Download Completed");
- break;
- }
- case FAILED: {
- intent.putExtra(EXTRA_NOTIFICATION_TITLE, "\"" + fileName + "\"");
- intent.putExtra(EXTRA_NOTIFICATION_TEXT, "Download Failed");
- intent.putExtra(EXTRA_NOTIFICATION_TICKER, "Download Failed");
- break;
- }
- default: {
- Timber.e("Invalid notification case!");
- return;
- }
- }
- intent.putExtra(EXTRA_DOWNLOAD_ID, downloadId);
- intent.putExtra(EXTRA_DOWNLOAD_STATE, type);
- intent.putExtra(EXTRA_FILE_NAME, fileName);
- sendBroadcast(intent);
-
- }
-
- @NonNull
- static String getMimeType(@NonNull File file) {
- String type = null;
- final String url = file.toString();
- final String extension = MimeTypeMap.getFileExtensionFromUrl(url);
- if (extension != null)
- type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.toLowerCase());
- if (type == null)
- type = "*/*";
-
- return type;
- }
-
-}
diff --git a/app/src/main/java/gr/thmmy/mthmmy/session/SessionManager.java b/app/src/main/java/gr/thmmy/mthmmy/session/SessionManager.java
index 94f8a284..9168ebf3 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/session/SessionManager.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/session/SessionManager.java
@@ -254,6 +254,16 @@ public class SessionManager {
return sharedPrefs.getString(AVATAR_LINK, AVATAR_LINK);
}
+ public Cookie getThmmyCookie() {
+ List cookieList = cookieJar.loadForRequest(indexUrl);
+ for(Cookie cookie: cookieList)
+ {
+ if(cookie.name().equals("THMMYgrC00ki3"))
+ return cookie;
+ }
+ return null;
+ }
+
public boolean hasAvatar() {
return sharedPrefs.getBoolean(HAS_AVATAR, false);
}
diff --git a/app/src/main/java/gr/thmmy/mthmmy/utils/FileUtils.java b/app/src/main/java/gr/thmmy/mthmmy/utils/FileUtils.java
new file mode 100644
index 00000000..9f2d4757
--- /dev/null
+++ b/app/src/main/java/gr/thmmy/mthmmy/utils/FileUtils.java
@@ -0,0 +1,26 @@
+package gr.thmmy.mthmmy.utils;
+
+import android.support.annotation.NonNull;
+import android.webkit.MimeTypeMap;
+
+import java.io.File;
+
+import static gr.thmmy.mthmmy.services.DownloadHelper.SAVE_DIR;
+
+public class FileUtils {
+ @NonNull
+ public static String getMimeType(@NonNull String fileName) {
+ String type = null;
+ final String extension = MimeTypeMap.getFileExtensionFromUrl(fileName);
+ if (extension != null)
+ type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.toLowerCase());
+ if (type == null)
+ type = "*/*";
+
+ return type;
+ }
+
+ public static boolean fileNameExists (String fileName) {
+ return fileName != null && (new File(SAVE_DIR.getAbsolutePath(), fileName)).isFile();
+ }
+}
diff --git a/app/src/main/java/gr/thmmy/mthmmy/utils/parsing/ParseTask.java b/app/src/main/java/gr/thmmy/mthmmy/utils/parsing/ParseTask.java
index 16b21583..4f335025 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/utils/parsing/ParseTask.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/utils/parsing/ParseTask.java
@@ -26,7 +26,9 @@ public abstract class ParseTask extends AsyncTask
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ 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 1d63348c..a4543e86 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -75,7 +75,7 @@
Boards
Topics
-
+
@@ -90,5 +90,14 @@
+
+
Toggle Notification
+
+
+ File \"%1$s\" already exists. Download again?"
+ Download Symbol
+ Cancel
+ Open
+ Download
diff --git a/app/src/main/res/xml/provider_paths.xml b/app/src/main/res/xml/provider_paths.xml
index a0b81b43..42b53275 100644
--- a/app/src/main/res/xml/provider_paths.xml
+++ b/app/src/main/res/xml/provider_paths.xml
@@ -1,10 +1,4 @@
-
-
-
+
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 3a61f691..42582a20 100644
--- a/build.gradle
+++ b/build.gradle
@@ -4,7 +4,6 @@ buildscript {
repositories {
jcenter()
maven { url "https://jitpack.io" }
- maven { url "https://maven.google.com" }
maven { url "https://maven.fabric.io/public" }
google()
}