Java tutorial
/* * Copyright (C) 2017-2019 k3b * * This file is part of de.k3b.android.toGoZip (https://github.com/k3b/ToGoZip/) . * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see <http://www.gnu.org/licenses/> */ package de.k3b.android.toGoZip; import android.annotation.TargetApi; import android.content.Context; import android.net.Uri; import android.os.Build; import android.os.Environment; import android.provider.DocumentsContract; import android.support.v4.provider.DocumentFile; import java.io.File; import java.io.FileNotFoundException; import java.io.InputStream; import java.io.OutputStream; import de.k3b.zip.ZipStorage; /** * Encapsulates all storage related operations that relate to a Zipfile. * * This is a android.support.v4.provider.DocumentFile based implementation for android-5.0ff. * * The method-names are nearly the same as for java.io.File except * that there is an additional parameter {@link ZipInstance} * that tells which current zip file to be used. * * Created by k3b on 22.12.2017. */ @TargetApi(Build.VERSION_CODES.KITKAT) public class ZipStorageDocumentFile implements ZipStorage { private static final String MIMETYPE_ZIP = "application/zip"; /** used by logfile*/ private static final String MIMETYPE_TEXT = "text/plain"; private final Context context; private final DocumentFile directory; private final String filename; public ZipStorageDocumentFile(Context context, DocumentFile directory, String filename) { this.context = context; this.directory = directory; this.filename = filename; } /** * {@inheritDoc} */ @Override public boolean exists() { return null != directory.findFile(filename); } /** * {@inheritDoc} */ @Override public boolean delete(ZipInstance zipInstance) { DocumentFile zipFile = directory.findFile(getZipFileNameWithoutPath(zipInstance)); return (zipFile != null) && zipFile.delete(); } /** * {@inheritDoc} */ @Override public OutputStream createOutputStream(ZipInstance zipInstance) throws FileNotFoundException { // find existing DocumentFile zipFile = getDocumentFile(zipInstance); // if not found create it. if (zipFile == null) { final String mimetype = (zipInstance == ZipInstance.logfile) ? MIMETYPE_TEXT : MIMETYPE_ZIP; zipFile = directory.createFile(mimetype, getZipFileNameWithoutPath(zipInstance)); } if (zipFile != null) return context.getContentResolver().openOutputStream(zipFile.getUri(), "w"); return null; } private DocumentFile getDocumentFile(ZipInstance zipInstance) { return directory.findFile(getZipFileNameWithoutPath(zipInstance)); } /** * {@inheritDoc} */ @Override public String getFullZipUriOrNull() { DocumentFile zipFile = getDocumentFile(ZipStorage.ZipInstance.current); if (zipFile != null) return zipFile.getUri().toString(); return null; } /** * {@inheritDoc} */ @Override public InputStream createInputStream() throws FileNotFoundException { DocumentFile zipFile = directory.findFile(filename); if (zipFile != null) return context.getContentResolver().openInputStream(zipFile.getUri()); return null; } /** * {@inheritDoc} */ @Override public String getAbsolutePath() { return getPath(this.context, directory.getUri()) + "/" + filename; } /** * {@inheritDoc} */ @Override public boolean rename(ZipInstance zipInstanceFrom, ZipInstance zipInstanceTo) { DocumentFile zipFile = directory.findFile(getZipFileNameWithoutPath(zipInstanceFrom)); if (zipFile != null) return zipFile.renameTo(getZipFileNameWithoutPath(zipInstanceTo)); return false; } /** * {@inheritDoc} */ @Override public String getZipFileNameWithoutPath(ZipInstance zipInstance) { return filename + zipInstance.getZipFileSuffix(); } public static String getPath(final Context context, final Uri uri) { // DocumentProvider if (Global.USE_DOCUMENT_PROVIDER && DocumentsContract.isDocumentUri(context, uri)) { // ExternalStorageProvider if (isExternalStorageDocument(uri)) { final String docId = DocumentsContract.getDocumentId(uri); final String[] split = docId.split(":"); final String type = split[0]; if ("primary".equalsIgnoreCase(type)) { final File externalStorageDirectory = Environment.getExternalStorageDirectory(); // split[1] results in index out of bound exception in storage root dir if (split.length == 1) return externalStorageDirectory.toString(); return externalStorageDirectory + "/" + split[1]; } // TODO handle non-primary volumes } } if ("file".equalsIgnoreCase(uri.getScheme())) { return uri.getPath(); } return null; } /** * @param uri The Uri to check. * @return Whether the Uri authority is ExternalStorageProvider. */ private static boolean isExternalStorageDocument(Uri uri) { return "com.android.externalstorage.documents".equals(uri.getAuthority()); } }