mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-08-23 12:53:07 +09:00
pt 1 in reviving the android build (copied from pm 28a1, wish me luck)
This commit is contained in:
parent
efa9662725
commit
d7788a6d6d
4249 changed files with 468189 additions and 0 deletions
|
|
@ -0,0 +1,235 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.annotation.WrapForJNI;
|
||||
import org.mozilla.gecko.AppConstants.Versions;
|
||||
import org.mozilla.gecko.permissions.Permissions;
|
||||
import org.mozilla.gecko.util.NativeEventListener;
|
||||
import org.mozilla.gecko.util.NativeJSObject;
|
||||
import org.mozilla.gecko.util.EventCallback;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.IllegalArgumentException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import android.app.DownloadManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.database.Cursor;
|
||||
import android.media.MediaScannerConnection;
|
||||
import android.media.MediaScannerConnection.MediaScannerConnectionClient;
|
||||
import android.net.Uri;
|
||||
import android.os.Environment;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
public class DownloadsIntegration implements NativeEventListener
|
||||
{
|
||||
private static final String LOGTAG = "GeckoDownloadsIntegration";
|
||||
|
||||
private static final List<String> UNKNOWN_MIME_TYPES;
|
||||
static {
|
||||
final ArrayList<String> tempTypes = new ArrayList<>(3);
|
||||
tempTypes.add("unknown/unknown"); // This will be used as a default mime type for unknown files
|
||||
tempTypes.add("application/unknown");
|
||||
tempTypes.add("application/octet-stream"); // Github uses this for APK files
|
||||
UNKNOWN_MIME_TYPES = Collections.unmodifiableList(tempTypes);
|
||||
}
|
||||
|
||||
private static final String DOWNLOAD_REMOVE = "Download:Remove";
|
||||
|
||||
private DownloadsIntegration() {
|
||||
EventDispatcher.getInstance().registerGeckoThreadListener((NativeEventListener)this, DOWNLOAD_REMOVE);
|
||||
}
|
||||
|
||||
private static DownloadsIntegration sInstance;
|
||||
|
||||
private static class Download {
|
||||
final File file;
|
||||
final long id;
|
||||
|
||||
final private static int UNKNOWN_ID = -1;
|
||||
|
||||
public Download(final String path) {
|
||||
this(path, UNKNOWN_ID);
|
||||
}
|
||||
|
||||
public Download(final String path, final long id) {
|
||||
file = new File(path);
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public static Download fromJSON(final NativeJSObject obj) {
|
||||
final String path = obj.getString("path");
|
||||
return new Download(path);
|
||||
}
|
||||
|
||||
public static Download fromCursor(final Cursor c) {
|
||||
final String path = c.getString(c.getColumnIndexOrThrow(DownloadManager.COLUMN_LOCAL_FILENAME));
|
||||
final long id = c.getLong(c.getColumnIndexOrThrow(DownloadManager.COLUMN_ID));
|
||||
return new Download(path, id);
|
||||
}
|
||||
|
||||
public boolean equals(final Download download) {
|
||||
return file.equals(download.file);
|
||||
}
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
if (sInstance == null) {
|
||||
sInstance = new DownloadsIntegration();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(final String event, final NativeJSObject message,
|
||||
final EventCallback callback) {
|
||||
if (DOWNLOAD_REMOVE.equals(event)) {
|
||||
final Download d = Download.fromJSON(message);
|
||||
removeDownload(d);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean useSystemDownloadManager() {
|
||||
if (!AppConstants.ANDROID_DOWNLOADS_INTEGRATION) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int state = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
|
||||
try {
|
||||
state = GeckoAppShell.getContext().getPackageManager().getApplicationEnabledSetting("com.android.providers.downloads");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Download Manager package does not exist
|
||||
return false;
|
||||
}
|
||||
|
||||
return (PackageManager.COMPONENT_ENABLED_STATE_ENABLED == state ||
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT == state);
|
||||
}
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
public static String getTemporaryDownloadDirectory() {
|
||||
Context context = GeckoAppShell.getApplicationContext();
|
||||
|
||||
if (Permissions.has(context, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
|
||||
// We do have the STORAGE permission, so we can save the file directly to the public
|
||||
// downloads directory.
|
||||
return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
|
||||
.getAbsolutePath();
|
||||
} else {
|
||||
// Without the permission we are going to start to download the file to the cache
|
||||
// directory. Later in the process we will ask for the permission and the download
|
||||
// process will move the file to the actual downloads directory. If we do not get the
|
||||
// permission then the download will be cancelled.
|
||||
return context.getCacheDir().getAbsolutePath();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
public static void scanMedia(final String aFile, String aMimeType) {
|
||||
String mimeType = aMimeType;
|
||||
if (UNKNOWN_MIME_TYPES.contains(mimeType)) {
|
||||
// If this is a generic undefined mimetype, erase it so that we can try to determine
|
||||
// one from the file extension below.
|
||||
mimeType = "";
|
||||
}
|
||||
|
||||
// If the platform didn't give us a mimetype, try to guess one from the filename
|
||||
if (TextUtils.isEmpty(mimeType)) {
|
||||
final int extPosition = aFile.lastIndexOf(".");
|
||||
if (extPosition > 0 && extPosition < aFile.length() - 1) {
|
||||
mimeType = GeckoAppShell.getMimeTypeFromExtension(aFile.substring(extPosition + 1));
|
||||
}
|
||||
}
|
||||
|
||||
// addCompletedDownload will throw if it received any null parameters. Use aMimeType or a default
|
||||
// if we still don't have one.
|
||||
if (TextUtils.isEmpty(mimeType)) {
|
||||
if (TextUtils.isEmpty(aMimeType)) {
|
||||
mimeType = UNKNOWN_MIME_TYPES.get(0);
|
||||
} else {
|
||||
mimeType = aMimeType;
|
||||
}
|
||||
}
|
||||
|
||||
if (useSystemDownloadManager()) {
|
||||
final File f = new File(aFile);
|
||||
final DownloadManager dm = (DownloadManager) GeckoAppShell.getContext().getSystemService(Context.DOWNLOAD_SERVICE);
|
||||
dm.addCompletedDownload(f.getName(),
|
||||
f.getName(),
|
||||
true, // Media scanner should scan this
|
||||
mimeType,
|
||||
f.getAbsolutePath(),
|
||||
Math.max(1, f.length()), // Some versions of Android require downloads to be at least length 1
|
||||
false); // Don't show a notification.
|
||||
} else {
|
||||
final Context context = GeckoAppShell.getContext();
|
||||
final GeckoMediaScannerClient client = new GeckoMediaScannerClient(context, aFile, mimeType);
|
||||
client.connect();
|
||||
}
|
||||
}
|
||||
|
||||
public static void removeDownload(final Download download) {
|
||||
if (!useSystemDownloadManager()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final DownloadManager dm = (DownloadManager) GeckoAppShell.getContext().getSystemService(Context.DOWNLOAD_SERVICE);
|
||||
|
||||
Cursor c = null;
|
||||
try {
|
||||
c = dm.query((new DownloadManager.Query()).setFilterByStatus(DownloadManager.STATUS_SUCCESSFUL));
|
||||
if (c == null || !c.moveToFirst()) {
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
final Download d = Download.fromCursor(c);
|
||||
// Try hard as we can to verify this download is the one we think it is
|
||||
if (download.equals(d)) {
|
||||
dm.remove(d.id);
|
||||
}
|
||||
} while (c.moveToNext());
|
||||
} finally {
|
||||
if (c != null) {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final class GeckoMediaScannerClient implements MediaScannerConnectionClient {
|
||||
private final String mFile;
|
||||
private final String mMimeType;
|
||||
private MediaScannerConnection mScanner;
|
||||
|
||||
public GeckoMediaScannerClient(Context context, String file, String mimeType) {
|
||||
mFile = file;
|
||||
mMimeType = mimeType;
|
||||
mScanner = new MediaScannerConnection(context, this);
|
||||
}
|
||||
|
||||
public void connect() {
|
||||
mScanner.connect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMediaScannerConnected() {
|
||||
mScanner.scanFile(mFile, mMimeType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScanCompleted(String path, Uri uri) {
|
||||
if (path.equals(mFile)) {
|
||||
mScanner.disconnect();
|
||||
mScanner = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue