/*
* Copyright (C) 2013 uPhyca Inc. http://www.uphyca.com/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.uphyca.kitkat.storage.ui;
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.SecureRandom;
import javax.inject.Inject;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.provider.DocumentsContract;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import butterknife.OnClick;
import com.uphyca.kitkat.storage.R;
import com.uphyca.kitkat.storage.internal.SkyDriveClient;
/**
* サンプルUIのfragment。
* SkyDriveをバックエンドにした DocumentsProviderに対して以下の機能が使える。
* SkyDriveへのログインにLive IDが必要。
* <ul>
* <li>ディレクトリの作成</li>
* <li>テキストファイルの作成</li>
* <li>テキストファイルのダンプ</li>
* <li>テキストファイルの編集(固定的な文字列です)</li>
* <li>テキストファイルの削除(エラーが出て失敗する)</li>
* </ul>
*
* @author masui@uphyca.com
*/
public class MainFragment extends Fragment {
private static final int REQUEST_OPEN = 1;
private static final int REQUEST_CREATE = 2;
private static final int REQUEST_EDIT = 3;
private static final int REQUEST_MKDIR = 4;
private static final int REQUEST_DELETE = 5;
@Inject
SkyDriveClient mSkyDriveClient;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_main, container, false);
}
@TargetApi(Build.VERSION_CODES.KITKAT)
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == Activity.RESULT_OK && data.getData() != null) {
int takeFlags = data.getFlags();
takeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
// Check for the freshest data.
getActivity().getContentResolver()
.takePersistableUriPermission(data.getData(), takeFlags);
}
switch (requestCode) {
case REQUEST_OPEN:
onOpenRequestResult(resultCode, data);
return;
case REQUEST_EDIT:
case REQUEST_CREATE:
onEditRequestResult(resultCode, data);
return;
case REQUEST_DELETE:
onDeleteRequestResult(resultCode, data);
return;
default:
super.onActivityResult(requestCode, resultCode, data);
}
}
/**
* Live APIの認証を行う。
*/
@OnClick(R.id.button_auth)
void onAuthButtonClick() {
mSkyDriveClient.login(getActivity(), new SkyDriveClient.SkyDriveAuthListener() {
@Override
public void onAuthComplete() {
Toast.makeText(getActivity(), "Logged in", Toast.LENGTH_SHORT)
.show();
}
@Override
public void onAuthError(Exception exception) {
Toast.makeText(getActivity(), exception.getMessage(), Toast.LENGTH_SHORT)
.show();
}
});
}
/**
* ファイルをダンプする。
*/
@OnClick(R.id.button_open)
void onOpenButtonClick() {
Intent intent = new Intent().setAction(Intent.ACTION_OPEN_DOCUMENT)
.addCategory(Intent.CATEGORY_OPENABLE)
.setType("text/*");
startActivityForResult(intent, REQUEST_OPEN);
}
/**
* ディレクトリを作成する。
*/
@OnClick(R.id.button_mkdir)
void onMkdirButtonClick() {
String fileName = String.format("folder-%d", new SecureRandom().nextInt());
Intent intent = new Intent().setAction(Intent.ACTION_CREATE_DOCUMENT)
.addCategory(Intent.CATEGORY_OPENABLE)
.setType(DocumentsContract.Document.MIME_TYPE_DIR)
.putExtra(Intent.EXTRA_TITLE, fileName);
startActivityForResult(intent, REQUEST_MKDIR);
}
/**
* ファイルを作成する。
*/
@OnClick(R.id.button_create)
void onCreateButtonClick() {
String fileName = String.format("document-%d.txt", new SecureRandom().nextInt());
Intent intent = new Intent().setAction(Intent.ACTION_CREATE_DOCUMENT)
.addCategory(Intent.CATEGORY_OPENABLE)
.setType("text/plain")
.putExtra(Intent.EXTRA_TITLE, fileName);
startActivityForResult(intent, REQUEST_CREATE);
}
/**
* ファイルを編集する。
*/
@OnClick(R.id.button_edit)
void onEditButtonClick() {
Intent intent = new Intent().setAction(Intent.ACTION_OPEN_DOCUMENT)
.addCategory(Intent.CATEGORY_OPENABLE)
.setType("text/plain");
startActivityForResult(intent, REQUEST_EDIT);
}
/**
* ファイルを削除する。
*/
@OnClick(R.id.button_delete)
void onDeleteButtonClick() {
Intent intent = new Intent().setAction(Intent.ACTION_OPEN_DOCUMENT)
.addCategory(Intent.CATEGORY_OPENABLE)
.setType("text/plain");
startActivityForResult(intent, REQUEST_DELETE);
}
/**
* テキストファイルのダンプを実行する。
*
* @param resultCode
* @param data
*/
void onOpenRequestResult(int resultCode, Intent data) {
if (resultCode != Activity.RESULT_OK || data == null) {
return;
}
new AsyncTask<Uri, Void, String>() {
Context appContext = getActivity().getApplicationContext();
@Override
protected String doInBackground(Uri... params) {
String text;
try {
text = readTextFromUri(params[0]);
} catch (IOException e) {
text = e.getMessage();
}
return text;
}
@Override
protected void onPostExecute(String s) {
Toast.makeText(appContext, s, Toast.LENGTH_SHORT)
.show();
}
}.execute(data.getData());
}
/**
* テキストファイルの編集を実行する。
*
* @param resultCode
* @param data
*/
void onEditRequestResult(int resultCode, Intent data) {
if (resultCode != Activity.RESULT_OK || data == null) {
return;
}
new AsyncTask<Uri, Void, String>() {
Context appContext = getActivity().getApplicationContext();
@Override
protected String doInBackground(Uri... params) {
String text;
try {
alterDocument(params[0]);
text = "Overwritten";
} catch (IOException e) {
text = e.getMessage();
}
return text;
}
@Override
protected void onPostExecute(String s) {
Toast.makeText(appContext, s, Toast.LENGTH_SHORT)
.show();
}
}.execute(data.getData());
}
/**
* ファイルの削除を実行する。
*
* @param resultCode
* @param data
*/
void onDeleteRequestResult(int resultCode, Intent data) {
if (resultCode != Activity.RESULT_OK || data == null) {
return;
}
new AsyncTask<Uri, Void, String>() {
Context appContext = getActivity().getApplicationContext();
@Override
protected String doInBackground(Uri... params) {
//FIXME エラー吐いて削除できない
DocumentsContract.deleteDocument(getActivity().getContentResolver(), params[0]);
return "Delete...できない!";
}
@Override
protected void onPostExecute(String s) {
Toast.makeText(appContext, s, Toast.LENGTH_SHORT)
.show();
}
}.execute(data.getData());
}
/**
* uriに対応するテキストファイルの内容をダンプする。
*
* @param uri
* @return
* @throws IOException
*/
private String readTextFromUri(Uri uri) throws IOException {
InputStream inputStream = getActivity().getContentResolver()
.openInputStream(uri);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder stringBuilder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
stringBuilder.append(line);
}
reader.close();
inputStream.close();
return stringBuilder.toString();
}
/**
* uriに対応するテキストファイルの内容を書き換える。
*
* @param uri
* @throws IOException
*/
private void alterDocument(Uri uri) throws IOException {
ParcelFileDescriptor pfd = getActivity().getContentResolver()
.openFileDescriptor(uri, "w");
FileOutputStream fileOutputStream = new FileOutputStream(pfd.getFileDescriptor());
fileOutputStream.write(("Overwritten by MyCloud at " + System.currentTimeMillis() + "\n").getBytes());
// Let the document provider know you're done by closing the stream.
fileOutputStream.close();
pfd.close();
}
}