mirror of
https://github.com/fankes/termux-app.git
synced 2025-09-06 10:45:23 +08:00
Remove support for ACTION_GET_CONTENT
As we have a document provider now we can remove ACTION_GET_CONTENT. "The ACTION_OPEN_DOCUMENT intent is only available on devices running Android 4.4 and higher. If you want your application to support ACTION_GET_CONTENT to accommodate devices that are running Android 4.3 and lower, you should disable the ACTION_GET_CONTENT intent filter in your manifest for devices running Android 4.4 or higher. A document provider and ACTION_GET_CONTENT should be considered mutually exclusive. If you support both of them simultaneously, your app will appear twice in the system picker UI, offering two different ways of accessing your stored data. This would be confusing for users." - http://developer.android.com/guide/topics/providers/document-provider.html#43
This commit is contained in:
@@ -73,31 +73,6 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
|
||||||
android:name="com.termux.filepicker.TermuxFilePickerActivity"
|
|
||||||
android:label="@string/application_name"
|
|
||||||
android:theme="@android:style/Theme.Material.Light.DarkActionBar"
|
|
||||||
android:noHistory="true">
|
|
||||||
<intent-filter>
|
|
||||||
<!--
|
|
||||||
http://stackoverflow.com/questions/6486716/using-intent-action-pick-for-specific-path
|
|
||||||
"That said, you should consider ACTION_PICK deprecated. The modern action is ACTION_GET_CONTENT
|
|
||||||
which is much better supported; you will find support of ACTION_PICK spotty and inconsistent.
|
|
||||||
Unfortunately ACTION_GET_CONTENT also does not let you specify a directory."
|
|
||||||
-->
|
|
||||||
<action android:name="android.intent.action.GET_CONTENT" />
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<category android:name="android.intent.category.OPENABLE" />
|
|
||||||
<data android:mimeType="*/*" />
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
|
||||||
|
|
||||||
<provider android:authorities="com.termux.filepicker.provider"
|
|
||||||
android:readPermission="com.termux.filepicker.READ"
|
|
||||||
android:exported="true"
|
|
||||||
android:grantUriPermissions="true"
|
|
||||||
android:name="com.termux.filepicker.TermuxFilePickerProvider" />
|
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name=".filepicker.TermuxDocumentsProvider"
|
android:name=".filepicker.TermuxDocumentsProvider"
|
||||||
android:authorities="com.termux.documents"
|
android:authorities="com.termux.documents"
|
||||||
|
@@ -23,6 +23,13 @@ import java.util.LinkedList;
|
|||||||
/**
|
/**
|
||||||
* A document provider for the Storage Access Framework which exposes the files in the
|
* A document provider for the Storage Access Framework which exposes the files in the
|
||||||
* $HOME/ folder to other apps.
|
* $HOME/ folder to other apps.
|
||||||
|
* <p>
|
||||||
|
* Note that this replaces providing an activity matching the ACTION_GET_CONTENT intent:
|
||||||
|
* <p>
|
||||||
|
* "A document provider and ACTION_GET_CONTENT should be considered mutually exclusive. If you
|
||||||
|
* support both of them simultaneously, your app will appear twice in the system picker UI,
|
||||||
|
* offering two different ways of accessing your stored data. This would be confusing for users."
|
||||||
|
* - http://developer.android.com/guide/topics/providers/document-provider.html#43
|
||||||
*/
|
*/
|
||||||
public class TermuxDocumentsProvider extends DocumentsProvider {
|
public class TermuxDocumentsProvider extends DocumentsProvider {
|
||||||
|
|
||||||
@@ -173,7 +180,7 @@ public class TermuxDocumentsProvider extends DocumentsProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the file given a document id (the reverse of {@link #getFileForDocId(String)}).
|
* Get the file given a document id (the reverse of {@link #getDocIdForFile(File)}).
|
||||||
*/
|
*/
|
||||||
private static File getFileForDocId(String docId) throws FileNotFoundException {
|
private static File getFileForDocId(String docId) throws FileNotFoundException {
|
||||||
final File f = new File(docId);
|
final File f = new File(docId);
|
||||||
|
@@ -1,103 +0,0 @@
|
|||||||
package com.termux.filepicker;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.ListActivity;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.ArrayAdapter;
|
|
||||||
import android.widget.ListView;
|
|
||||||
|
|
||||||
import com.termux.R;
|
|
||||||
import com.termux.app.TermuxService;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/** Activity allowing picking files from the $HOME folder. */
|
|
||||||
public class TermuxFilePickerActivity extends ListActivity {
|
|
||||||
|
|
||||||
private File mCurrentDirectory;
|
|
||||||
private final List<File> mFiles = new ArrayList<>();
|
|
||||||
private final List<String> mFileNames = new ArrayList<>();
|
|
||||||
private ArrayAdapter mAdapter;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
setContentView(R.layout.file_picker);
|
|
||||||
|
|
||||||
mAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, mFileNames);
|
|
||||||
|
|
||||||
enterDirectory(new File(TermuxService.HOME_PATH));
|
|
||||||
setListAdapter(mAdapter);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
|
||||||
int id = item.getItemId();
|
|
||||||
if (id == android.R.id.home) {
|
|
||||||
enterDirectory(mCurrentDirectory.getParentFile());
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onListItemClick(ListView l, View v, int position, long id) {
|
|
||||||
super.onListItemClick(l, v, position, id);
|
|
||||||
File requestFile = mFiles.get(position);
|
|
||||||
if (requestFile.isDirectory()) {
|
|
||||||
enterDirectory(requestFile);
|
|
||||||
} else {
|
|
||||||
Uri returnUri = Uri.withAppendedPath(Uri.parse("content://com.termux.filepicker.provider/"), requestFile.getAbsolutePath());
|
|
||||||
Intent returnIntent = new Intent().setData(returnUri);
|
|
||||||
returnIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
|
||||||
setResult(Activity.RESULT_OK, returnIntent);
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void enterDirectory(File directory) {
|
|
||||||
getActionBar().setDisplayHomeAsUpEnabled(!directory.getAbsolutePath().equals(TermuxService.HOME_PATH));
|
|
||||||
|
|
||||||
String title = directory.getAbsolutePath() + "/";
|
|
||||||
if (title.startsWith(TermuxService.HOME_PATH)) {
|
|
||||||
title = "~" + title.substring(TermuxService.HOME_PATH.length(), title.length());
|
|
||||||
}
|
|
||||||
setTitle(title);
|
|
||||||
|
|
||||||
mCurrentDirectory = directory;
|
|
||||||
mFiles.clear();
|
|
||||||
mFileNames.clear();
|
|
||||||
mFiles.addAll(Arrays.asList(mCurrentDirectory.listFiles()));
|
|
||||||
|
|
||||||
Collections.sort(mFiles, new Comparator<File>() {
|
|
||||||
@Override
|
|
||||||
public int compare(File f1, File f2) {
|
|
||||||
final String n1 = f1.getName();
|
|
||||||
final String n2 = f2.getName();
|
|
||||||
// Display dot folders last:
|
|
||||||
if (n1.startsWith(".") && !n2.startsWith(".")) {
|
|
||||||
return 1;
|
|
||||||
} else if (n2.startsWith(".") && !n1.startsWith(".")) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return n1.compareToIgnoreCase(n2);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
for (File file : mFiles) {
|
|
||||||
mFileNames.add(file.getName() + (file.isDirectory() ? "/" : ""));
|
|
||||||
}
|
|
||||||
mAdapter.notifyDataSetChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,65 +0,0 @@
|
|||||||
package com.termux.filepicker;
|
|
||||||
|
|
||||||
|
|
||||||
import android.content.ContentProvider;
|
|
||||||
import android.content.ContentValues;
|
|
||||||
import android.database.Cursor;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.ParcelFileDescriptor;
|
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.webkit.MimeTypeMap;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
|
|
||||||
/** Provider of files content uris picked from {@link com.termux.filepicker.TermuxFilePickerActivity}. */
|
|
||||||
public class TermuxFilePickerProvider extends ContentProvider {
|
|
||||||
@Override
|
|
||||||
public boolean onCreate() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getType(@NonNull Uri uri) {
|
|
||||||
String contentType = null;
|
|
||||||
String path = uri.getPath();
|
|
||||||
int lastDotIndex = path.lastIndexOf('.');
|
|
||||||
String possibleFileExtension = path.substring(lastDotIndex + 1, path.length());
|
|
||||||
if (possibleFileExtension.contains("/")) {
|
|
||||||
// The dot was in the path, so not a file extension.
|
|
||||||
} else {
|
|
||||||
MimeTypeMap mimeTypes = MimeTypeMap.getSingleton();
|
|
||||||
// Lower casing makes it work with e.g. "JPG":
|
|
||||||
contentType = mimeTypes.getMimeTypeFromExtension(possibleFileExtension.toLowerCase());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (contentType == null) contentType = "application/octet-stream";
|
|
||||||
return contentType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Uri insert(@NonNull Uri uri, ContentValues values) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int delete(@NonNull Uri uri, String selection, String[] selectionArgs) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int update(@NonNull Uri uri, ContentValues values, String selection, String[] selectionArgs) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode) throws FileNotFoundException {
|
|
||||||
File file = new File(uri.getPath());
|
|
||||||
return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,21 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:paddingLeft="8dp"
|
|
||||||
android:paddingRight="8dp">
|
|
||||||
|
|
||||||
<ListView android:id="@android:id/list"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:drawSelectorOnTop="false"/>
|
|
||||||
|
|
||||||
<TextView android:id="@android:id/empty"
|
|
||||||
android:gravity="center"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:text="@string/empty_folder"/>
|
|
||||||
</LinearLayout>
|
|
@@ -53,8 +53,6 @@
|
|||||||
<string name="notification_action_wakelock">Wake</string>
|
<string name="notification_action_wakelock">Wake</string>
|
||||||
<string name="notification_action_wifilock">Wifi</string>
|
<string name="notification_action_wifilock">Wifi</string>
|
||||||
|
|
||||||
<string name="empty_folder">Empty folder.</string>
|
|
||||||
|
|
||||||
<string name="file_received_title">Save file in ~/downloads/</string>
|
<string name="file_received_title">Save file in ~/downloads/</string>
|
||||||
<string name="file_received_edit_button">Edit</string>
|
<string name="file_received_edit_button">Edit</string>
|
||||||
<string name="file_received_open_folder_button">Open folder</string>
|
<string name="file_received_open_folder_button">Open folder</string>
|
||||||
|
Reference in New Issue
Block a user