am af927234: Merge changes I7b3f4c68,I9f022a08 into klp-dev
* commit 'af9272349fb9eed1653d5af0768c9517e36070a6': Rename offer() to add(), remove/hide some APIs. Sort order is sticky for session, back leaves.
This commit is contained in:
@@ -289,14 +289,14 @@ package android {
|
|||||||
field public static final deprecated int animationResolution = 16843546; // 0x101031a
|
field public static final deprecated int animationResolution = 16843546; // 0x101031a
|
||||||
field public static final int antialias = 16843034; // 0x101011a
|
field public static final int antialias = 16843034; // 0x101011a
|
||||||
field public static final int anyDensity = 16843372; // 0x101026c
|
field public static final int anyDensity = 16843372; // 0x101026c
|
||||||
field public static final int apduServiceBanner = 16843758; // 0x10103ee
|
field public static final int apduServiceBanner = 16843757; // 0x10103ed
|
||||||
field public static final int apiKey = 16843281; // 0x1010211
|
field public static final int apiKey = 16843281; // 0x1010211
|
||||||
field public static final int author = 16843444; // 0x10102b4
|
field public static final int author = 16843444; // 0x10102b4
|
||||||
field public static final int authorities = 16842776; // 0x1010018
|
field public static final int authorities = 16842776; // 0x1010018
|
||||||
field public static final int autoAdvanceViewId = 16843535; // 0x101030f
|
field public static final int autoAdvanceViewId = 16843535; // 0x101030f
|
||||||
field public static final int autoCompleteTextViewStyle = 16842859; // 0x101006b
|
field public static final int autoCompleteTextViewStyle = 16842859; // 0x101006b
|
||||||
field public static final int autoLink = 16842928; // 0x10100b0
|
field public static final int autoLink = 16842928; // 0x10100b0
|
||||||
field public static final int autoMirrored = 16843755; // 0x10103eb
|
field public static final int autoMirrored = 16843754; // 0x10103ea
|
||||||
field public static final int autoStart = 16843445; // 0x10102b5
|
field public static final int autoStart = 16843445; // 0x10102b5
|
||||||
field public static final deprecated int autoText = 16843114; // 0x101016a
|
field public static final deprecated int autoText = 16843114; // 0x101016a
|
||||||
field public static final int autoUrlDetect = 16843404; // 0x101028c
|
field public static final int autoUrlDetect = 16843404; // 0x101028c
|
||||||
@@ -393,7 +393,6 @@ package android {
|
|||||||
field public static final int cropToPadding = 16843043; // 0x1010123
|
field public static final int cropToPadding = 16843043; // 0x1010123
|
||||||
field public static final int cursorVisible = 16843090; // 0x1010152
|
field public static final int cursorVisible = 16843090; // 0x1010152
|
||||||
field public static final int customNavigationLayout = 16843474; // 0x10102d2
|
field public static final int customNavigationLayout = 16843474; // 0x10102d2
|
||||||
field public static final int customRoots = 16843754; // 0x10103ea
|
|
||||||
field public static final int customTokens = 16843579; // 0x101033b
|
field public static final int customTokens = 16843579; // 0x101033b
|
||||||
field public static final int cycles = 16843220; // 0x10101d4
|
field public static final int cycles = 16843220; // 0x10101d4
|
||||||
field public static final int dashGap = 16843175; // 0x10101a7
|
field public static final int dashGap = 16843175; // 0x10101a7
|
||||||
@@ -846,7 +845,7 @@ package android {
|
|||||||
field public static final int prompt = 16843131; // 0x101017b
|
field public static final int prompt = 16843131; // 0x101017b
|
||||||
field public static final int propertyName = 16843489; // 0x10102e1
|
field public static final int propertyName = 16843489; // 0x10102e1
|
||||||
field public static final int protectionLevel = 16842761; // 0x1010009
|
field public static final int protectionLevel = 16842761; // 0x1010009
|
||||||
field public static final int provideAssistData = 16843759; // 0x10103ef
|
field public static final int provideAssistData = 16843758; // 0x10103ee
|
||||||
field public static final int publicKey = 16843686; // 0x10103a6
|
field public static final int publicKey = 16843686; // 0x10103a6
|
||||||
field public static final int queryActionMsg = 16843227; // 0x10101db
|
field public static final int queryActionMsg = 16843227; // 0x10101db
|
||||||
field public static final int queryAfterZeroResults = 16843394; // 0x1010282
|
field public static final int queryAfterZeroResults = 16843394; // 0x1010282
|
||||||
@@ -871,7 +870,7 @@ package android {
|
|||||||
field public static final int reqKeyboardType = 16843304; // 0x1010228
|
field public static final int reqKeyboardType = 16843304; // 0x1010228
|
||||||
field public static final int reqNavigation = 16843306; // 0x101022a
|
field public static final int reqNavigation = 16843306; // 0x101022a
|
||||||
field public static final int reqTouchScreen = 16843303; // 0x1010227
|
field public static final int reqTouchScreen = 16843303; // 0x1010227
|
||||||
field public static final int requireDeviceUnlock = 16843757; // 0x10103ed
|
field public static final int requireDeviceUnlock = 16843756; // 0x10103ec
|
||||||
field public static final int required = 16843406; // 0x101028e
|
field public static final int required = 16843406; // 0x101028e
|
||||||
field public static final int requiredAccountType = 16843734; // 0x10103d6
|
field public static final int requiredAccountType = 16843734; // 0x10103d6
|
||||||
field public static final int requiredForAllUsers = 16843728; // 0x10103d0
|
field public static final int requiredForAllUsers = 16843728; // 0x10103d0
|
||||||
@@ -1020,7 +1019,7 @@ package android {
|
|||||||
field public static final int summaryOff = 16843248; // 0x10101f0
|
field public static final int summaryOff = 16843248; // 0x10101f0
|
||||||
field public static final int summaryOn = 16843247; // 0x10101ef
|
field public static final int summaryOn = 16843247; // 0x10101ef
|
||||||
field public static final int supportsRtl = 16843695; // 0x10103af
|
field public static final int supportsRtl = 16843695; // 0x10103af
|
||||||
field public static final int supportsSwitchingToNextInputMethod = 16843756; // 0x10103ec
|
field public static final int supportsSwitchingToNextInputMethod = 16843755; // 0x10103eb
|
||||||
field public static final int supportsUploading = 16843419; // 0x101029b
|
field public static final int supportsUploading = 16843419; // 0x101029b
|
||||||
field public static final int switchMinWidth = 16843632; // 0x1010370
|
field public static final int switchMinWidth = 16843632; // 0x1010370
|
||||||
field public static final int switchPadding = 16843633; // 0x1010371
|
field public static final int switchPadding = 16843633; // 0x1010371
|
||||||
@@ -8140,7 +8139,7 @@ package android.database {
|
|||||||
|
|
||||||
public class MatrixCursor.RowBuilder {
|
public class MatrixCursor.RowBuilder {
|
||||||
method public android.database.MatrixCursor.RowBuilder add(java.lang.Object);
|
method public android.database.MatrixCursor.RowBuilder add(java.lang.Object);
|
||||||
method public android.database.MatrixCursor.RowBuilder offer(java.lang.String, java.lang.Object);
|
method public android.database.MatrixCursor.RowBuilder add(java.lang.String, java.lang.Object);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MergeCursor extends android.database.AbstractCursor {
|
public class MergeCursor extends android.database.AbstractCursor {
|
||||||
@@ -20774,7 +20773,6 @@ package android.provider {
|
|||||||
method public static android.net.Uri buildRootUri(java.lang.String, java.lang.String);
|
method public static android.net.Uri buildRootUri(java.lang.String, java.lang.String);
|
||||||
method public static android.net.Uri buildRootsUri(java.lang.String);
|
method public static android.net.Uri buildRootsUri(java.lang.String);
|
||||||
method public static android.net.Uri buildSearchDocumentsUri(java.lang.String, java.lang.String, java.lang.String);
|
method public static android.net.Uri buildSearchDocumentsUri(java.lang.String, java.lang.String, java.lang.String);
|
||||||
method public static android.net.Uri createDocument(android.content.ContentResolver, android.net.Uri, java.lang.String, java.lang.String);
|
|
||||||
method public static boolean deleteDocument(android.content.ContentResolver, android.net.Uri);
|
method public static boolean deleteDocument(android.content.ContentResolver, android.net.Uri);
|
||||||
method public static java.lang.String getDocumentId(android.net.Uri);
|
method public static java.lang.String getDocumentId(android.net.Uri);
|
||||||
method public static android.graphics.Bitmap getDocumentThumbnail(android.content.ContentResolver, android.net.Uri, android.graphics.Point, android.os.CancellationSignal);
|
method public static android.graphics.Bitmap getDocumentThumbnail(android.content.ContentResolver, android.net.Uri, android.graphics.Point, android.os.CancellationSignal);
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ public class MatrixCursor extends AbstractCursor {
|
|||||||
* column value at a time. This follows the same ordering as the column
|
* column value at a time. This follows the same ordering as the column
|
||||||
* names specified at cursor construction time.
|
* names specified at cursor construction time.
|
||||||
* <li>Column and value pairs can be offered for possible inclusion using
|
* <li>Column and value pairs can be offered for possible inclusion using
|
||||||
* {@link #offer(String, Object)}. If the cursor includes the given column,
|
* {@link #add(String, Object)}. If the cursor includes the given column,
|
||||||
* the value will be set for that column, otherwise the value is ignored.
|
* the value will be set for that column, otherwise the value is ignored.
|
||||||
* This approach is useful when matching data to a custom projection.
|
* This approach is useful when matching data to a custom projection.
|
||||||
* </ul>
|
* </ul>
|
||||||
@@ -227,7 +227,7 @@ public class MatrixCursor extends AbstractCursor {
|
|||||||
*
|
*
|
||||||
* @return this builder to support chaining
|
* @return this builder to support chaining
|
||||||
*/
|
*/
|
||||||
public RowBuilder offer(String columnName, Object value) {
|
public RowBuilder add(String columnName, Object value) {
|
||||||
for (int i = 0; i < columnNames.length; i++) {
|
for (int i = 0; i < columnNames.length; i++) {
|
||||||
if (columnName.equals(columnNames[i])) {
|
if (columnName.equals(columnNames[i])) {
|
||||||
data[(row * columnCount) + i] = value;
|
data[(row * columnCount) + i] = value;
|
||||||
|
|||||||
@@ -694,6 +694,7 @@ public final class DocumentsContract {
|
|||||||
* @param mimeType MIME type of new document
|
* @param mimeType MIME type of new document
|
||||||
* @param displayName name of new document
|
* @param displayName name of new document
|
||||||
* @return newly created document, or {@code null} if failed
|
* @return newly created document, or {@code null} if failed
|
||||||
|
* @hide
|
||||||
*/
|
*/
|
||||||
public static Uri createDocument(ContentResolver resolver, Uri parentDocumentUri,
|
public static Uri createDocument(ContentResolver resolver, Uri parentDocumentUri,
|
||||||
String mimeType, String displayName) {
|
String mimeType, String displayName) {
|
||||||
|
|||||||
@@ -6128,8 +6128,4 @@
|
|||||||
<attr name="textView" format="reference" />
|
<attr name="textView" format="reference" />
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
|
||||||
<declare-styleable name="DocumentsProviderInfo">
|
|
||||||
<attr name="customRoots" format="boolean" />
|
|
||||||
</declare-styleable>
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -2073,7 +2073,6 @@
|
|||||||
<public type="attr" name="vendor" />
|
<public type="attr" name="vendor" />
|
||||||
<public type="attr" name="category" />
|
<public type="attr" name="category" />
|
||||||
<public type="attr" name="isAsciiCapable" />
|
<public type="attr" name="isAsciiCapable" />
|
||||||
<public type="attr" name="customRoots" />
|
|
||||||
<public type="attr" name="autoMirrored" />
|
<public type="attr" name="autoMirrored" />
|
||||||
<public type="attr" name="supportsSwitchingToNextInputMethod" />
|
<public type="attr" name="supportsSwitchingToNextInputMethod" />
|
||||||
<public type="attr" name="requireDeviceUnlock" />
|
<public type="attr" name="requireDeviceUnlock" />
|
||||||
|
|||||||
@@ -132,18 +132,18 @@ public class MatrixCursorTest extends TestCase {
|
|||||||
MatrixCursor cursor = newMatrixCursor();
|
MatrixCursor cursor = newMatrixCursor();
|
||||||
|
|
||||||
cursor.newRow()
|
cursor.newRow()
|
||||||
.offer("float", 4.2f)
|
.add("float", 4.2f)
|
||||||
.offer("string", "foobar")
|
.add("string", "foobar")
|
||||||
.offer("blob", new byte[] {(byte) 0xaa, (byte) 0x55})
|
.add("blob", new byte[] {(byte) 0xaa, (byte) 0x55})
|
||||||
.offer("lolwat", "kittens");
|
.add("lolwat", "kittens");
|
||||||
|
|
||||||
cursor.newRow();
|
cursor.newRow();
|
||||||
|
|
||||||
cursor.newRow()
|
cursor.newRow()
|
||||||
.offer("string", "zero")
|
.add("string", "zero")
|
||||||
.offer("string", "one")
|
.add("string", "one")
|
||||||
.offer("string", "two")
|
.add("string", "two")
|
||||||
.offer("lolwat", "kittens");
|
.add("lolwat", "kittens");
|
||||||
|
|
||||||
assertTrue(cursor.moveToFirst());
|
assertTrue(cursor.moveToFirst());
|
||||||
assertEquals("foobar", cursor.getString(0));
|
assertEquals("foobar", cursor.getString(0));
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import android.app.FragmentManager;
|
|||||||
import android.app.FragmentTransaction;
|
import android.app.FragmentTransaction;
|
||||||
import android.app.LoaderManager.LoaderCallbacks;
|
import android.app.LoaderManager.LoaderCallbacks;
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.Loader;
|
import android.content.Loader;
|
||||||
@@ -65,6 +66,7 @@ import android.widget.TextView;
|
|||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.android.documentsui.DocumentsActivity.State;
|
import com.android.documentsui.DocumentsActivity.State;
|
||||||
|
import com.android.documentsui.RecentsProvider.StateColumns;
|
||||||
import com.android.documentsui.model.DocumentInfo;
|
import com.android.documentsui.model.DocumentInfo;
|
||||||
import com.android.documentsui.model.RootInfo;
|
import com.android.documentsui.model.RootInfo;
|
||||||
import com.android.internal.util.Predicate;
|
import com.android.internal.util.Predicate;
|
||||||
@@ -190,11 +192,13 @@ public class DirectoryFragment extends Fragment {
|
|||||||
case TYPE_NORMAL:
|
case TYPE_NORMAL:
|
||||||
contentsUri = DocumentsContract.buildChildDocumentsUri(
|
contentsUri = DocumentsContract.buildChildDocumentsUri(
|
||||||
doc.authority, doc.documentId);
|
doc.authority, doc.documentId);
|
||||||
return new DirectoryLoader(context, root, doc, contentsUri);
|
return new DirectoryLoader(
|
||||||
|
context, root, doc, contentsUri, state.userSortOrder);
|
||||||
case TYPE_SEARCH:
|
case TYPE_SEARCH:
|
||||||
contentsUri = DocumentsContract.buildSearchDocumentsUri(
|
contentsUri = DocumentsContract.buildSearchDocumentsUri(
|
||||||
doc.authority, doc.documentId, query);
|
doc.authority, doc.documentId, query);
|
||||||
return new DirectoryLoader(context, root, doc, contentsUri);
|
return new DirectoryLoader(
|
||||||
|
context, root, doc, contentsUri, state.userSortOrder);
|
||||||
case TYPE_RECENT_OPEN:
|
case TYPE_RECENT_OPEN:
|
||||||
final RootsCache roots = DocumentsApplication.getRootsCache(context);
|
final RootsCache roots = DocumentsApplication.getRootsCache(context);
|
||||||
final List<RootInfo> matchingRoots = roots.getMatchingRoots(state);
|
final List<RootInfo> matchingRoots = roots.getMatchingRoots(state);
|
||||||
@@ -212,14 +216,14 @@ public class DirectoryFragment extends Fragment {
|
|||||||
|
|
||||||
// Push latest state up to UI
|
// Push latest state up to UI
|
||||||
// TODO: if mode change was racing with us, don't overwrite it
|
// TODO: if mode change was racing with us, don't overwrite it
|
||||||
state.mode = result.mode;
|
state.derivedMode = result.mode;
|
||||||
state.sortOrder = result.sortOrder;
|
state.derivedSortOrder = result.sortOrder;
|
||||||
((DocumentsActivity) context).onStateChanged();
|
((DocumentsActivity) context).onStateChanged();
|
||||||
|
|
||||||
updateDisplayState();
|
updateDisplayState();
|
||||||
|
|
||||||
if (mLastSortOrder != result.sortOrder) {
|
if (mLastSortOrder != state.derivedSortOrder) {
|
||||||
mLastSortOrder = result.sortOrder;
|
mLastSortOrder = state.derivedSortOrder;
|
||||||
mListView.smoothScrollToPosition(0);
|
mListView.smoothScrollToPosition(0);
|
||||||
mGridView.smoothScrollToPosition(0);
|
mGridView.smoothScrollToPosition(0);
|
||||||
}
|
}
|
||||||
@@ -244,12 +248,36 @@ public class DirectoryFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void onUserSortOrderChanged() {
|
public void onUserSortOrderChanged() {
|
||||||
// User change always triggers reload
|
// Sort order change always triggers reload; we'll trigger state change
|
||||||
|
// on the flip side.
|
||||||
getLoaderManager().restartLoader(mLoaderId, null, mCallbacks);
|
getLoaderManager().restartLoader(mLoaderId, null, mCallbacks);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onUserModeChanged() {
|
public void onUserModeChanged() {
|
||||||
// Mode change is just display; no need to reload
|
final ContentResolver resolver = getActivity().getContentResolver();
|
||||||
|
final State state = getDisplayState(this);
|
||||||
|
|
||||||
|
final RootInfo root = getArguments().getParcelable(EXTRA_ROOT);
|
||||||
|
final DocumentInfo doc = getArguments().getParcelable(EXTRA_DOC);
|
||||||
|
|
||||||
|
final Uri stateUri = RecentsProvider.buildState(
|
||||||
|
root.authority, root.rootId, doc.documentId);
|
||||||
|
final ContentValues values = new ContentValues();
|
||||||
|
values.put(StateColumns.MODE, state.userMode);
|
||||||
|
|
||||||
|
new AsyncTask<Void, Void, Void>() {
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Void... params) {
|
||||||
|
resolver.insert(stateUri, values);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}.execute();
|
||||||
|
|
||||||
|
// Mode change is just visual change; no need to kick loader, and
|
||||||
|
// deliver change event immediately.
|
||||||
|
state.derivedMode = state.userMode;
|
||||||
|
((DocumentsActivity) getActivity()).onStateChanged();
|
||||||
|
|
||||||
updateDisplayState();
|
updateDisplayState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,11 +286,11 @@ public class DirectoryFragment extends Fragment {
|
|||||||
|
|
||||||
mFilter = new MimePredicate(state.acceptMimes);
|
mFilter = new MimePredicate(state.acceptMimes);
|
||||||
|
|
||||||
if (mLastMode == state.mode) return;
|
if (mLastMode == state.derivedMode) return;
|
||||||
mLastMode = state.mode;
|
mLastMode = state.derivedMode;
|
||||||
|
|
||||||
mListView.setVisibility(state.mode == MODE_LIST ? View.VISIBLE : View.GONE);
|
mListView.setVisibility(state.derivedMode == MODE_LIST ? View.VISIBLE : View.GONE);
|
||||||
mGridView.setVisibility(state.mode == MODE_GRID ? View.VISIBLE : View.GONE);
|
mGridView.setVisibility(state.derivedMode == MODE_GRID ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
final int choiceMode;
|
final int choiceMode;
|
||||||
if (state.allowMultiple) {
|
if (state.allowMultiple) {
|
||||||
@@ -272,7 +300,7 @@ public class DirectoryFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final int thumbSize;
|
final int thumbSize;
|
||||||
if (state.mode == MODE_GRID) {
|
if (state.derivedMode == MODE_GRID) {
|
||||||
thumbSize = getResources().getDimensionPixelSize(R.dimen.grid_width);
|
thumbSize = getResources().getDimensionPixelSize(R.dimen.grid_width);
|
||||||
mListView.setAdapter(null);
|
mListView.setAdapter(null);
|
||||||
mListView.setChoiceMode(ListView.CHOICE_MODE_NONE);
|
mListView.setChoiceMode(ListView.CHOICE_MODE_NONE);
|
||||||
@@ -281,7 +309,7 @@ public class DirectoryFragment extends Fragment {
|
|||||||
mGridView.setNumColumns(GridView.AUTO_FIT);
|
mGridView.setNumColumns(GridView.AUTO_FIT);
|
||||||
mGridView.setChoiceMode(choiceMode);
|
mGridView.setChoiceMode(choiceMode);
|
||||||
mCurrentView = mGridView;
|
mCurrentView = mGridView;
|
||||||
} else if (state.mode == MODE_LIST) {
|
} else if (state.derivedMode == MODE_LIST) {
|
||||||
thumbSize = getResources().getDimensionPixelSize(R.dimen.icon_size);
|
thumbSize = getResources().getDimensionPixelSize(R.dimen.icon_size);
|
||||||
mGridView.setAdapter(null);
|
mGridView.setAdapter(null);
|
||||||
mGridView.setChoiceMode(ListView.CHOICE_MODE_NONE);
|
mGridView.setChoiceMode(ListView.CHOICE_MODE_NONE);
|
||||||
@@ -289,7 +317,7 @@ public class DirectoryFragment extends Fragment {
|
|||||||
mListView.setChoiceMode(choiceMode);
|
mListView.setChoiceMode(choiceMode);
|
||||||
mCurrentView = mListView;
|
mCurrentView = mListView;
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalStateException("Unknown state " + state.mode);
|
throw new IllegalStateException("Unknown state " + state.derivedMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
mThumbSize = new Point(thumbSize, thumbSize);
|
mThumbSize = new Point(thumbSize, thumbSize);
|
||||||
@@ -505,9 +533,9 @@ public class DirectoryFragment extends Fragment {
|
|||||||
|
|
||||||
if (convertView == null) {
|
if (convertView == null) {
|
||||||
final LayoutInflater inflater = LayoutInflater.from(context);
|
final LayoutInflater inflater = LayoutInflater.from(context);
|
||||||
if (state.mode == MODE_LIST) {
|
if (state.derivedMode == MODE_LIST) {
|
||||||
convertView = inflater.inflate(R.layout.item_message_list, parent, false);
|
convertView = inflater.inflate(R.layout.item_message_list, parent, false);
|
||||||
} else if (state.mode == MODE_GRID) {
|
} else if (state.derivedMode == MODE_GRID) {
|
||||||
convertView = inflater.inflate(R.layout.item_message_grid, parent, false);
|
convertView = inflater.inflate(R.layout.item_message_grid, parent, false);
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
@@ -582,9 +610,9 @@ public class DirectoryFragment extends Fragment {
|
|||||||
|
|
||||||
if (convertView == null) {
|
if (convertView == null) {
|
||||||
final LayoutInflater inflater = LayoutInflater.from(context);
|
final LayoutInflater inflater = LayoutInflater.from(context);
|
||||||
if (state.mode == MODE_LIST) {
|
if (state.derivedMode == MODE_LIST) {
|
||||||
convertView = inflater.inflate(R.layout.item_doc_list, parent, false);
|
convertView = inflater.inflate(R.layout.item_doc_list, parent, false);
|
||||||
} else if (state.mode == MODE_GRID) {
|
} else if (state.derivedMode == MODE_GRID) {
|
||||||
convertView = inflater.inflate(R.layout.item_doc_grid, parent, false);
|
convertView = inflater.inflate(R.layout.item_doc_grid, parent, false);
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
@@ -618,7 +646,7 @@ public class DirectoryFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final boolean supportsThumbnail = (docFlags & Document.FLAG_SUPPORTS_THUMBNAIL) != 0;
|
final boolean supportsThumbnail = (docFlags & Document.FLAG_SUPPORTS_THUMBNAIL) != 0;
|
||||||
final boolean allowThumbnail = (state.mode == MODE_GRID)
|
final boolean allowThumbnail = (state.derivedMode == MODE_GRID)
|
||||||
|| MimePredicate.mimeMatches(LIST_THUMBNAIL_MIMES, docMimeType);
|
|| MimePredicate.mimeMatches(LIST_THUMBNAIL_MIMES, docMimeType);
|
||||||
|
|
||||||
if (supportsThumbnail && allowThumbnail) {
|
if (supportsThumbnail && allowThumbnail) {
|
||||||
|
|||||||
@@ -65,15 +65,18 @@ public class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> {
|
|||||||
private final RootInfo mRoot;
|
private final RootInfo mRoot;
|
||||||
private final DocumentInfo mDoc;
|
private final DocumentInfo mDoc;
|
||||||
private final Uri mUri;
|
private final Uri mUri;
|
||||||
|
private final int mUserSortOrder;
|
||||||
|
|
||||||
private CancellationSignal mSignal;
|
private CancellationSignal mSignal;
|
||||||
private DirectoryResult mResult;
|
private DirectoryResult mResult;
|
||||||
|
|
||||||
public DirectoryLoader(Context context, RootInfo root, DocumentInfo doc, Uri uri) {
|
public DirectoryLoader(
|
||||||
|
Context context, RootInfo root, DocumentInfo doc, Uri uri, int userSortOrder) {
|
||||||
super(context);
|
super(context);
|
||||||
mRoot = root;
|
mRoot = root;
|
||||||
mDoc = doc;
|
mDoc = doc;
|
||||||
mUri = uri;
|
mUri = uri;
|
||||||
|
mUserSortOrder = userSortOrder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -91,7 +94,6 @@ public class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> {
|
|||||||
final DirectoryResult result = new DirectoryResult();
|
final DirectoryResult result = new DirectoryResult();
|
||||||
|
|
||||||
int userMode = State.MODE_UNKNOWN;
|
int userMode = State.MODE_UNKNOWN;
|
||||||
int userSortOrder = State.SORT_ORDER_UNKNOWN;
|
|
||||||
|
|
||||||
// Pick up any custom modes requested by user
|
// Pick up any custom modes requested by user
|
||||||
Cursor cursor = null;
|
Cursor cursor = null;
|
||||||
@@ -101,7 +103,6 @@ public class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> {
|
|||||||
cursor = resolver.query(stateUri, null, null, null, null);
|
cursor = resolver.query(stateUri, null, null, null, null);
|
||||||
if (cursor.moveToFirst()) {
|
if (cursor.moveToFirst()) {
|
||||||
userMode = getCursorInt(cursor, StateColumns.MODE);
|
userMode = getCursorInt(cursor, StateColumns.MODE);
|
||||||
userSortOrder = getCursorInt(cursor, StateColumns.SORT_ORDER);
|
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
IoUtils.closeQuietly(cursor);
|
IoUtils.closeQuietly(cursor);
|
||||||
@@ -117,8 +118,8 @@ public class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userSortOrder != State.SORT_ORDER_UNKNOWN) {
|
if (mUserSortOrder != State.SORT_ORDER_UNKNOWN) {
|
||||||
result.sortOrder = userSortOrder;
|
result.sortOrder = mUserSortOrder;
|
||||||
} else {
|
} else {
|
||||||
if ((mDoc.flags & Document.FLAG_DIR_PREFERS_LAST_MODIFIED) != 0) {
|
if ((mDoc.flags & Document.FLAG_DIR_PREFERS_LAST_MODIFIED) != 0) {
|
||||||
result.sortOrder = State.SORT_ORDER_LAST_MODIFIED;
|
result.sortOrder = State.SORT_ORDER_LAST_MODIFIED;
|
||||||
@@ -127,7 +128,7 @@ public class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.d(TAG, "userMode=" + userMode + ", userSortOrder=" + userSortOrder + " --> mode="
|
Log.d(TAG, "userMode=" + userMode + ", userSortOrder=" + mUserSortOrder + " --> mode="
|
||||||
+ result.mode + ", sortOrder=" + result.sortOrder);
|
+ result.mode + ", sortOrder=" + result.sortOrder);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -170,10 +170,6 @@ public class DocumentsActivity extends Activity {
|
|||||||
mState.localOnly = intent.getBooleanExtra(Intent.EXTRA_LOCAL_ONLY, false);
|
mState.localOnly = intent.getBooleanExtra(Intent.EXTRA_LOCAL_ONLY, false);
|
||||||
mState.showAdvanced = SettingsActivity.getDisplayAdvancedDevices(this);
|
mState.showAdvanced = SettingsActivity.getDisplayAdvancedDevices(this);
|
||||||
|
|
||||||
if (mState.action == ACTION_MANAGE) {
|
|
||||||
mState.sortOrder = SORT_ORDER_LAST_MODIFIED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mState.action == ACTION_MANAGE) {
|
if (mState.action == ACTION_MANAGE) {
|
||||||
final Uri uri = intent.getData();
|
final Uri uri = intent.getData();
|
||||||
final String rootId = DocumentsContract.getRootId(uri);
|
final String rootId = DocumentsContract.getRootId(uri);
|
||||||
@@ -348,8 +344,8 @@ public class DocumentsActivity extends Activity {
|
|||||||
|
|
||||||
if (cwd != null) {
|
if (cwd != null) {
|
||||||
sort.setVisible(true);
|
sort.setVisible(true);
|
||||||
grid.setVisible(mState.mode != MODE_GRID);
|
grid.setVisible(mState.derivedMode != MODE_GRID);
|
||||||
list.setVisible(mState.mode != MODE_LIST);
|
list.setVisible(mState.derivedMode != MODE_LIST);
|
||||||
} else {
|
} else {
|
||||||
sort.setVisible(false);
|
sort.setVisible(false);
|
||||||
grid.setVisible(false);
|
grid.setVisible(false);
|
||||||
@@ -433,42 +429,25 @@ public class DocumentsActivity extends Activity {
|
|||||||
* Set state sort order based on explicit user action.
|
* Set state sort order based on explicit user action.
|
||||||
*/
|
*/
|
||||||
private void setUserSortOrder(int sortOrder) {
|
private void setUserSortOrder(int sortOrder) {
|
||||||
final RootInfo root = getCurrentRoot();
|
mState.userSortOrder = sortOrder;
|
||||||
final DocumentInfo cwd = getCurrentDirectory();
|
|
||||||
|
|
||||||
// TODO: persist async, then trigger rebind
|
|
||||||
final Uri stateUri = RecentsProvider.buildState(
|
|
||||||
root.authority, root.rootId, cwd.documentId);
|
|
||||||
final ContentValues values = new ContentValues();
|
|
||||||
values.put(StateColumns.SORT_ORDER, sortOrder);
|
|
||||||
getContentResolver().insert(stateUri, values);
|
|
||||||
|
|
||||||
DirectoryFragment.get(getFragmentManager()).onUserSortOrderChanged();
|
DirectoryFragment.get(getFragmentManager()).onUserSortOrderChanged();
|
||||||
onStateChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set state mode based on explicit user action.
|
* Set state mode based on explicit user action.
|
||||||
*/
|
*/
|
||||||
private void setUserMode(int mode) {
|
private void setUserMode(int mode) {
|
||||||
final RootInfo root = getCurrentRoot();
|
mState.userMode = mode;
|
||||||
final DocumentInfo cwd = getCurrentDirectory();
|
|
||||||
|
|
||||||
// TODO: persist async, then trigger rebind
|
|
||||||
final Uri stateUri = RecentsProvider.buildState(
|
|
||||||
root.authority, root.rootId, cwd.documentId);
|
|
||||||
final ContentValues values = new ContentValues();
|
|
||||||
values.put(StateColumns.MODE, mode);
|
|
||||||
getContentResolver().insert(stateUri, values);
|
|
||||||
|
|
||||||
mState.mode = mode;
|
|
||||||
|
|
||||||
DirectoryFragment.get(getFragmentManager()).onUserModeChanged();
|
DirectoryFragment.get(getFragmentManager()).onUserModeChanged();
|
||||||
onStateChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBackPressed() {
|
public void onBackPressed() {
|
||||||
|
if (!mState.stackTouched) {
|
||||||
|
super.onBackPressed();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final int size = mState.stack.size();
|
final int size = mState.stack.size();
|
||||||
if (size > 1) {
|
if (size > 1) {
|
||||||
mState.stack.pop();
|
mState.stack.pop();
|
||||||
@@ -564,6 +543,7 @@ public class DocumentsActivity extends Activity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (mState.stack.size() > itemPosition + 1) {
|
while (mState.stack.size() > itemPosition + 1) {
|
||||||
|
mState.stackTouched = true;
|
||||||
mState.stack.pop();
|
mState.stack.pop();
|
||||||
}
|
}
|
||||||
onCurrentDirectoryChanged();
|
onCurrentDirectoryChanged();
|
||||||
@@ -629,6 +609,7 @@ public class DocumentsActivity extends Activity {
|
|||||||
|
|
||||||
public void onStackPicked(DocumentStack stack) {
|
public void onStackPicked(DocumentStack stack) {
|
||||||
mState.stack = stack;
|
mState.stack = stack;
|
||||||
|
mState.stackTouched = true;
|
||||||
onCurrentDirectoryChanged();
|
onCurrentDirectoryChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -636,6 +617,7 @@ public class DocumentsActivity extends Activity {
|
|||||||
// Clear entire backstack and start in new root
|
// Clear entire backstack and start in new root
|
||||||
mState.stack.root = root;
|
mState.stack.root = root;
|
||||||
mState.stack.clear();
|
mState.stack.clear();
|
||||||
|
mState.stackTouched = true;
|
||||||
|
|
||||||
if (!mRoots.isRecentsRoot(root)) {
|
if (!mRoots.isRecentsRoot(root)) {
|
||||||
try {
|
try {
|
||||||
@@ -664,13 +646,8 @@ public class DocumentsActivity extends Activity {
|
|||||||
public void onDocumentPicked(DocumentInfo doc) {
|
public void onDocumentPicked(DocumentInfo doc) {
|
||||||
final FragmentManager fm = getFragmentManager();
|
final FragmentManager fm = getFragmentManager();
|
||||||
if (doc.isDirectory()) {
|
if (doc.isDirectory()) {
|
||||||
// TODO: query display mode user preference for this dir
|
|
||||||
if (doc.isGridPreferred()) {
|
|
||||||
mState.mode = MODE_GRID;
|
|
||||||
} else {
|
|
||||||
mState.mode = MODE_LIST;
|
|
||||||
}
|
|
||||||
mState.stack.push(doc);
|
mState.stack.push(doc);
|
||||||
|
mState.stackTouched = true;
|
||||||
onCurrentDirectoryChanged();
|
onCurrentDirectoryChanged();
|
||||||
} else if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT) {
|
} else if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT) {
|
||||||
// Explicit file picked, return
|
// Explicit file picked, return
|
||||||
@@ -774,13 +751,23 @@ public class DocumentsActivity extends Activity {
|
|||||||
|
|
||||||
public static class State implements android.os.Parcelable {
|
public static class State implements android.os.Parcelable {
|
||||||
public int action;
|
public int action;
|
||||||
public int mode = MODE_LIST;
|
|
||||||
public String[] acceptMimes;
|
public String[] acceptMimes;
|
||||||
public int sortOrder = SORT_ORDER_DISPLAY_NAME;
|
|
||||||
|
/** Explicit user choice */
|
||||||
|
public int userMode = MODE_UNKNOWN;
|
||||||
|
/** Derived after loader */
|
||||||
|
public int derivedMode = MODE_LIST;
|
||||||
|
|
||||||
|
/** Explicit user choice */
|
||||||
|
public int userSortOrder = SORT_ORDER_UNKNOWN;
|
||||||
|
/** Derived after loader */
|
||||||
|
public int derivedSortOrder = SORT_ORDER_DISPLAY_NAME;
|
||||||
|
|
||||||
public boolean allowMultiple = false;
|
public boolean allowMultiple = false;
|
||||||
public boolean showSize = false;
|
public boolean showSize = false;
|
||||||
public boolean localOnly = false;
|
public boolean localOnly = false;
|
||||||
public boolean showAdvanced = false;
|
public boolean showAdvanced = false;
|
||||||
|
public boolean stackTouched = false;
|
||||||
|
|
||||||
/** Current user navigation stack; empty implies recents. */
|
/** Current user navigation stack; empty implies recents. */
|
||||||
public DocumentStack stack = new DocumentStack();
|
public DocumentStack stack = new DocumentStack();
|
||||||
@@ -809,13 +796,14 @@ public class DocumentsActivity extends Activity {
|
|||||||
@Override
|
@Override
|
||||||
public void writeToParcel(Parcel out, int flags) {
|
public void writeToParcel(Parcel out, int flags) {
|
||||||
out.writeInt(action);
|
out.writeInt(action);
|
||||||
out.writeInt(mode);
|
out.writeInt(userMode);
|
||||||
out.writeStringArray(acceptMimes);
|
out.writeStringArray(acceptMimes);
|
||||||
out.writeInt(sortOrder);
|
out.writeInt(userSortOrder);
|
||||||
out.writeInt(allowMultiple ? 1 : 0);
|
out.writeInt(allowMultiple ? 1 : 0);
|
||||||
out.writeInt(showSize ? 1 : 0);
|
out.writeInt(showSize ? 1 : 0);
|
||||||
out.writeInt(localOnly ? 1 : 0);
|
out.writeInt(localOnly ? 1 : 0);
|
||||||
out.writeInt(showAdvanced ? 1 : 0);
|
out.writeInt(showAdvanced ? 1 : 0);
|
||||||
|
out.writeInt(stackTouched ? 1 : 0);
|
||||||
DurableUtils.writeToParcel(out, stack);
|
DurableUtils.writeToParcel(out, stack);
|
||||||
out.writeString(currentSearch);
|
out.writeString(currentSearch);
|
||||||
}
|
}
|
||||||
@@ -825,13 +813,14 @@ public class DocumentsActivity extends Activity {
|
|||||||
public State createFromParcel(Parcel in) {
|
public State createFromParcel(Parcel in) {
|
||||||
final State state = new State();
|
final State state = new State();
|
||||||
state.action = in.readInt();
|
state.action = in.readInt();
|
||||||
state.mode = in.readInt();
|
state.userMode = in.readInt();
|
||||||
state.acceptMimes = in.readStringArray();
|
state.acceptMimes = in.readStringArray();
|
||||||
state.sortOrder = in.readInt();
|
state.userSortOrder = in.readInt();
|
||||||
state.allowMultiple = in.readInt() != 0;
|
state.allowMultiple = in.readInt() != 0;
|
||||||
state.showSize = in.readInt() != 0;
|
state.showSize = in.readInt() != 0;
|
||||||
state.localOnly = in.readInt() != 0;
|
state.localOnly = in.readInt() != 0;
|
||||||
state.showAdvanced = in.readInt() != 0;
|
state.showAdvanced = in.readInt() != 0;
|
||||||
|
state.stackTouched = in.readInt() != 0;
|
||||||
DurableUtils.readFromParcel(in, state.stack);
|
DurableUtils.readFromParcel(in, state.stack);
|
||||||
state.currentSearch = in.readString();
|
state.currentSearch = in.readString();
|
||||||
return state;
|
return state;
|
||||||
|
|||||||
@@ -90,7 +90,6 @@ public class RootsCache {
|
|||||||
if (info.metaData != null && info.metaData.containsKey(
|
if (info.metaData != null && info.metaData.containsKey(
|
||||||
DocumentsContract.META_DATA_DOCUMENT_PROVIDER)) {
|
DocumentsContract.META_DATA_DOCUMENT_PROVIDER)) {
|
||||||
|
|
||||||
// TODO: remove deprecated customRoots flag
|
|
||||||
// TODO: populate roots on background thread, and cache results
|
// TODO: populate roots on background thread, and cache results
|
||||||
final Uri rootsUri = DocumentsContract.buildRootsUri(info.authority);
|
final Uri rootsUri = DocumentsContract.buildRootsUri(info.authority);
|
||||||
final ContentProviderClient client = resolver
|
final ContentProviderClient client = resolver
|
||||||
|
|||||||
@@ -181,12 +181,12 @@ public class ExternalStorageProvider extends DocumentsProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final RowBuilder row = result.newRow();
|
final RowBuilder row = result.newRow();
|
||||||
row.offer(Document.COLUMN_DOCUMENT_ID, docId);
|
row.add(Document.COLUMN_DOCUMENT_ID, docId);
|
||||||
row.offer(Document.COLUMN_DISPLAY_NAME, displayName);
|
row.add(Document.COLUMN_DISPLAY_NAME, displayName);
|
||||||
row.offer(Document.COLUMN_SIZE, file.length());
|
row.add(Document.COLUMN_SIZE, file.length());
|
||||||
row.offer(Document.COLUMN_MIME_TYPE, mimeType);
|
row.add(Document.COLUMN_MIME_TYPE, mimeType);
|
||||||
row.offer(Document.COLUMN_LAST_MODIFIED, file.lastModified());
|
row.add(Document.COLUMN_LAST_MODIFIED, file.lastModified());
|
||||||
row.offer(Document.COLUMN_FLAGS, flags);
|
row.add(Document.COLUMN_FLAGS, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -197,13 +197,13 @@ public class ExternalStorageProvider extends DocumentsProvider {
|
|||||||
final File path = mIdToPath.get(rootId);
|
final File path = mIdToPath.get(rootId);
|
||||||
|
|
||||||
final RowBuilder row = result.newRow();
|
final RowBuilder row = result.newRow();
|
||||||
row.offer(Root.COLUMN_ROOT_ID, root.rootId);
|
row.add(Root.COLUMN_ROOT_ID, root.rootId);
|
||||||
row.offer(Root.COLUMN_ROOT_TYPE, root.rootType);
|
row.add(Root.COLUMN_ROOT_TYPE, root.rootType);
|
||||||
row.offer(Root.COLUMN_FLAGS, root.flags);
|
row.add(Root.COLUMN_FLAGS, root.flags);
|
||||||
row.offer(Root.COLUMN_ICON, root.icon);
|
row.add(Root.COLUMN_ICON, root.icon);
|
||||||
row.offer(Root.COLUMN_TITLE, root.title);
|
row.add(Root.COLUMN_TITLE, root.title);
|
||||||
row.offer(Root.COLUMN_DOCUMENT_ID, root.docId);
|
row.add(Root.COLUMN_DOCUMENT_ID, root.docId);
|
||||||
row.offer(Root.COLUMN_AVAILABLE_BYTES, path.getFreeSpace());
|
row.add(Root.COLUMN_AVAILABLE_BYTES, path.getFreeSpace());
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,13 +69,13 @@ public class TestDocumentsProvider extends DocumentsProvider {
|
|||||||
|
|
||||||
final MatrixCursor result = new MatrixCursor(resolveRootProjection(projection));
|
final MatrixCursor result = new MatrixCursor(resolveRootProjection(projection));
|
||||||
final RowBuilder row = result.newRow();
|
final RowBuilder row = result.newRow();
|
||||||
row.offer(Root.COLUMN_ROOT_ID, MY_ROOT_ID);
|
row.add(Root.COLUMN_ROOT_ID, MY_ROOT_ID);
|
||||||
row.offer(Root.COLUMN_ROOT_TYPE, Root.ROOT_TYPE_SERVICE);
|
row.add(Root.COLUMN_ROOT_TYPE, Root.ROOT_TYPE_SERVICE);
|
||||||
row.offer(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_RECENTS);
|
row.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_RECENTS);
|
||||||
row.offer(Root.COLUMN_TITLE, "_Test title which is really long");
|
row.add(Root.COLUMN_TITLE, "_Test title which is really long");
|
||||||
row.offer(Root.COLUMN_SUMMARY, "_Summary which is also super long text");
|
row.add(Root.COLUMN_SUMMARY, "_Summary which is also super long text");
|
||||||
row.offer(Root.COLUMN_DOCUMENT_ID, MY_DOC_ID);
|
row.add(Root.COLUMN_DOCUMENT_ID, MY_DOC_ID);
|
||||||
row.offer(Root.COLUMN_AVAILABLE_BYTES, 1024);
|
row.add(Root.COLUMN_AVAILABLE_BYTES, 1024);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,16 +234,16 @@ public class TestDocumentsProvider extends DocumentsProvider {
|
|||||||
|
|
||||||
private static void includeFile(MatrixCursor result, String docId) {
|
private static void includeFile(MatrixCursor result, String docId) {
|
||||||
final RowBuilder row = result.newRow();
|
final RowBuilder row = result.newRow();
|
||||||
row.offer(Document.COLUMN_DOCUMENT_ID, docId);
|
row.add(Document.COLUMN_DOCUMENT_ID, docId);
|
||||||
row.offer(Document.COLUMN_DISPLAY_NAME, docId);
|
row.add(Document.COLUMN_DISPLAY_NAME, docId);
|
||||||
row.offer(Document.COLUMN_LAST_MODIFIED, System.currentTimeMillis());
|
row.add(Document.COLUMN_LAST_MODIFIED, System.currentTimeMillis());
|
||||||
|
|
||||||
if (MY_DOC_ID.equals(docId)) {
|
if (MY_DOC_ID.equals(docId)) {
|
||||||
row.offer(Document.COLUMN_MIME_TYPE, Document.MIME_TYPE_DIR);
|
row.add(Document.COLUMN_MIME_TYPE, Document.MIME_TYPE_DIR);
|
||||||
} else if (MY_DOC_NULL.equals(docId)) {
|
} else if (MY_DOC_NULL.equals(docId)) {
|
||||||
// No MIME type
|
// No MIME type
|
||||||
} else {
|
} else {
|
||||||
row.offer(Document.COLUMN_MIME_TYPE, "application/octet-stream");
|
row.add(Document.COLUMN_MIME_TYPE, "application/octet-stream");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user