diff --git a/app/build.gradle b/app/build.gradle
index f24121309..688f072b1 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -7,8 +7,8 @@ android {
applicationId 'com.seafile.seadroid2'
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
- versionCode 134
- versionName "2.3.3"
+ versionCode 137
+ versionName "2.3.4"
multiDexEnabled true
resValue "string", "authorities", applicationId + '.cameraupload.provider'
resValue "string", "account_type", "com.seafile.seadroid2.account.api2"
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 85a42d4fb..31d0b8652 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -26,7 +26,7 @@
-
+
diff --git a/app/src/main/java/com/seafile/seadroid2/SeadroidApplication.java b/app/src/main/java/com/seafile/seadroid2/SeadroidApplication.java
index 70a841e15..62289cc2a 100644
--- a/app/src/main/java/com/seafile/seadroid2/SeadroidApplication.java
+++ b/app/src/main/java/com/seafile/seadroid2/SeadroidApplication.java
@@ -10,6 +10,8 @@
import com.seafile.seadroid2.gesturelock.AppLockManager;
import com.seafile.seadroid2.ui.CustomNotificationBuilder;
import com.seafile.seadroid2.util.CrashHandler;
+import com.seafile.seadroid2.util.DeviceIdManager;
+import com.seafile.seadroid2.util.SeafileLog;
import com.seafile.seadroid2.util.Utils;
public class SeadroidApplication extends Application {
diff --git a/app/src/main/java/com/seafile/seadroid2/account/ui/SingleSignOnAuthorizeActivity.java b/app/src/main/java/com/seafile/seadroid2/account/ui/SingleSignOnAuthorizeActivity.java
index b76e9f8ae..3183e672c 100644
--- a/app/src/main/java/com/seafile/seadroid2/account/ui/SingleSignOnAuthorizeActivity.java
+++ b/app/src/main/java/com/seafile/seadroid2/account/ui/SingleSignOnAuthorizeActivity.java
@@ -32,6 +32,7 @@
import com.seafile.seadroid2.ui.activity.BaseActivity;
import com.seafile.seadroid2.ui.dialog.SslConfirmDialog;
import com.seafile.seadroid2.util.ConcurrentAsyncTask;
+import com.seafile.seadroid2.util.DeviceIdManager;
import com.seafile.seadroid2.util.Utils;
import org.json.JSONException;
@@ -89,8 +90,6 @@ private void openAuthorizePage(String url) {
return;
}
- String deviceId = Settings.Secure.getString(this.getContentResolver(), Settings.Secure.ANDROID_ID);
-
String appVersion = "";
Context context = SeadroidApplication.getAppContext();
try {
@@ -105,18 +104,20 @@ private void openAuthorizePage(String url) {
} else
url += "shib-login";
+ //local device id
+ String deviceId = DeviceIdManager.getInstance().getOrSet();
+
try {
url += String.format("?shib_platform_version=%s&shib_device_name=%s&shib_platform=%s&shib_device_id=%s&shib_client_version=%s",
URLEncoder.encode(Build.VERSION.RELEASE, "UTF-8"),
URLEncoder.encode(Build.MODEL, "UTF-8"),
"android",
- URLEncoder.encode(deviceId, "UTF-8"),
+ deviceId,
appVersion);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
-
Log.d(DEBUG_TAG, "url " + url);
mWebview.loadUrl(url);
diff --git a/app/src/main/java/com/seafile/seadroid2/ui/WidgetUtils.java b/app/src/main/java/com/seafile/seadroid2/ui/WidgetUtils.java
index 0492a8a77..9b91b414f 100644
--- a/app/src/main/java/com/seafile/seadroid2/ui/WidgetUtils.java
+++ b/app/src/main/java/com/seafile/seadroid2/ui/WidgetUtils.java
@@ -1,11 +1,24 @@
package com.seafile.seadroid2.ui;
+import static android.app.PendingIntent.FLAG_IMMUTABLE;
+import static android.content.Context.NOTIFICATION_SERVICE;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+
import android.app.Activity;
+import android.app.DownloadManager;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.net.Uri;
+import android.os.Build;
+import android.os.Environment;
+import android.support.v4.app.NotificationCompat;
import android.support.v4.content.FileProvider;
import android.text.ClipboardManager;
import android.webkit.MimeTypeMap;
@@ -23,16 +36,21 @@
import com.seafile.seadroid2.ui.dialog.GetShareLinkDialog;
import com.seafile.seadroid2.ui.dialog.GetShareLinkEncryptDialog;
import com.seafile.seadroid2.ui.dialog.TaskDialog;
+import com.seafile.seadroid2.util.FileExports;
import com.seafile.seadroid2.util.Utils;
import java.io.File;
+import java.io.IOException;
import java.net.HttpURLConnection;
+import java.security.SecureRandom;
import java.util.List;
+import java.util.Random;
/**
* Activity Utils
*/
public class WidgetUtils {
+ public static final String MIME_ANDROID = "application/vnd.android.package-archive";
public static void chooseShareApp(final BaseActivity activity,
final String repoID,
@@ -226,17 +244,23 @@ public static void showFile(final BaseActivity activity, File file, boolean isOp
} else if (mime == null) {
mime = "*/*"; // forces app chooser dialog on unknown type//
}
+
+ if (MIME_ANDROID.equals(mime)) {
+// showFileForAndroid(activity,file,name);
+ return;
+ }
+
Intent open = new Intent(Intent.ACTION_VIEW);
- open.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ open.addFlags(FLAG_ACTIVITY_NEW_TASK);
- if (android.os.Build.VERSION.SDK_INT > 23) {
+ if (Build.VERSION.SDK_INT > 23) {
Uri photoURI = FileProvider.getUriForFile(activity, activity.getApplicationContext().getPackageName(), file);
open.setDataAndType(photoURI, mime);
open.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
} else {
open.setDataAndType((Uri.fromFile(file)), mime);
}
- if (android.os.Build.VERSION.SDK_INT < 30) {
+ if (Build.VERSION.SDK_INT < 30) {
if (activity.getPackageManager().resolveActivity(open, 0) == null) {
String message = String.format(activity.getString(R.string.op_exception_suitable_app_not_found), mime);
activity.showShortToast(activity, message);
@@ -252,6 +276,39 @@ public static void showFile(final BaseActivity activity, File file, boolean isOp
}
}
+ private static void showFileForAndroid(final BaseActivity activity, File file, String fileName) {
+ try {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+ ContentResolver contentResolver = activity.getContentResolver();
+ FileExports.exportFileAndroid10AndAbove(fileName, MIME_ANDROID, contentResolver, file);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ int nId = new Random(10000).nextInt();
+ String channelName = "seadroid-downloader";
+
+ NotificationManager manager = (NotificationManager) activity.getSystemService(NOTIFICATION_SERVICE);
+ NotificationChannel channel = new NotificationChannel(channelName, channelName, NotificationManager.IMPORTANCE_HIGH);
+ manager.createNotificationChannel(channel);
+
+
+ Intent intent = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS);
+ intent.addFlags(FLAG_ACTIVITY_NEW_TASK);
+
+ PendingIntent pendingIntent = PendingIntent.getActivity(activity, nId, intent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
+
+ Notification notification = new NotificationCompat.Builder(activity, channelName)
+ .setContentTitle(fileName + " " + activity.getString(R.string.download_finished))
+ .setContentText(activity.getString(R.string.open))
+ .setSmallIcon(R.drawable.icon)
+ .setContentIntent(pendingIntent)
+ .setAutoCancel(true)
+ .build();
+ manager.notify(nId, notification);
+ }
+
public static void showRepo(Context context, String repoID, String repoName, String path, String dirID) {
Intent intent = new Intent(context, BrowserActivity.class);
intent.putExtra("repoID", repoID);
diff --git a/app/src/main/java/com/seafile/seadroid2/util/DeviceIdManager.java b/app/src/main/java/com/seafile/seadroid2/util/DeviceIdManager.java
new file mode 100644
index 000000000..ae8339dba
--- /dev/null
+++ b/app/src/main/java/com/seafile/seadroid2/util/DeviceIdManager.java
@@ -0,0 +1,71 @@
+package com.seafile.seadroid2.util;
+
+import android.bluetooth.le.AdvertiseData;
+import android.bluetooth.le.AdvertiseSettings;
+
+import com.blankj.utilcode.util.FileUtils;
+import com.seafile.seadroid2.SeadroidApplication;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.UUID;
+
+public class DeviceIdManager {
+ private static volatile DeviceIdManager mSingleton = null;
+ public static final String PREFIX = ".sd-";
+ public final File LOCAL_FOLDER = SeadroidApplication.getAppContext().getExternalCacheDir();
+
+ private DeviceIdManager() {
+
+ }
+
+ public static DeviceIdManager getInstance() {
+ if (mSingleton == null) {
+ synchronized (DeviceIdManager.class) {
+ if (mSingleton == null) {
+ mSingleton = new DeviceIdManager();
+ }
+ }
+ }
+ return mSingleton;
+ }
+
+ public String getOrSet() {
+ File stFile = checkLocalDeviceIdFileExistsState();
+ if (stFile != null) {
+ String name = stFile.getName().replace(PREFIX, "");
+ return name.substring(0, 16);
+ }
+
+ String uid = UUID.randomUUID().toString().replace("-", "");
+ File file = new File(LOCAL_FOLDER.getAbsolutePath() + "/" + PREFIX + uid);
+ FileUtils.createOrExistsFile(file);
+ return uid.substring(0, 16);
+ }
+
+ public File checkLocalDeviceIdFileExistsState() {
+ if (LOCAL_FOLDER == null) {
+ return null;
+ }
+
+ File[] temp = LOCAL_FOLDER.listFiles(new FilenameFilter() {
+ @Override
+ public boolean accept(File dir, String name) {
+ return name.startsWith(PREFIX);
+ }
+ });
+
+ if (temp == null) {
+ return null;
+ }
+
+ if (temp.length == 1) {
+ return temp[0];
+ }
+
+ for (File file : temp) {
+ file.delete();
+ }
+ return null;
+ }
+}
diff --git a/app/src/main/java/com/seafile/seadroid2/util/FileExports.java b/app/src/main/java/com/seafile/seadroid2/util/FileExports.java
new file mode 100644
index 000000000..b1f2818bc
--- /dev/null
+++ b/app/src/main/java/com/seafile/seadroid2/util/FileExports.java
@@ -0,0 +1,54 @@
+package com.seafile.seadroid2.util;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Environment;
+import android.os.ParcelFileDescriptor;
+import android.provider.MediaStore;
+import android.support.annotation.RequiresApi;
+
+import com.blankj.utilcode.util.FileUtils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class FileExports {
+ @RequiresApi(api = Build.VERSION_CODES.Q)
+ public static void exportFileAndroid10AndAbove(String fileName, String mimeType, ContentResolver contentResolver, File file) throws IOException {
+ ContentValues cv = new ContentValues();
+ cv.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName);
+ cv.put(MediaStore.MediaColumns.MIME_TYPE, mimeType);
+ cv.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS);
+
+ Uri uri = contentResolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, cv);
+ if (uri != null) {
+ ParcelFileDescriptor descriptor = contentResolver.openFileDescriptor(uri, "w");
+ if (descriptor != null) {
+ FileOutputStream fos = new FileOutputStream(descriptor.getFileDescriptor());
+ FileInputStream fis = new FileInputStream(file);
+ copyStream(fis, fos);
+ }
+ } else {
+ File downloadFolder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
+ //
+ File dest = new File(downloadFolder.getPath() + "/" + fileName);
+ if (!dest.exists()) {
+ FileUtils.copy(file, dest);
+ }
+ }
+ }
+
+ private static void copyStream(InputStream inputStream, FileOutputStream outputStream) throws IOException {
+ byte[] buffer = new byte[1024];
+ int len;
+ while ((len = inputStream.read(buffer)) != -1) {
+ outputStream.write(buffer, 0, len);
+ }
+ }
+
+}