/*
FileProvider.java
Copyright (c) 2014 NTT DOCOMO,INC.
Released under the MIT license
http://opensource.org/licenses/mit-license.php
*/
package org.deviceconnect.android.provider;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import org.deviceconnect.android.provider.FileLocationParser.FileLocation;
import java.io.File;
import java.io.FileNotFoundException;
/**
* ファイル用のContentProvider.
*
* このクラスはデバイスプラグインで一時的にファイルを保持してdConnectManagerにファイルを
* 送信するためのContentProviderになる。
*
* FileProfileを実装する場合には、必須となる。
*
* AndroidManifest.xml に以下の記述を追加する必要がある。
* <pre>
* <provider
* android:name="org.deviceconnect.android.provider.FileProvider"
* android:authorities="com.mycompany.android.deviceplugin.provider"
* android:exported="true" />
* </pre>
*
* android:authoritiesの部分には、各デバイスプラグインでauthoritiesを設定すること。
*
* <p>
* デフォルトでは、SDカードの直下にデバイスプラグインのパッケージ名のフォルダを作成して、その下にファイルが保存される。<br>
* 保存場所を変えたい場合には、providerにメタデータを持たせることで変更できる。
* </p>
*
* <pre>
* <provider
* android:name="org.deviceconnect.android.provider.FileProvider"
* android:authorities="com.mycompany.android.deviceplugin.provider"
* android:exported="true">
* <meta-data
* android:name="filelocation"
* android:resource="@xml/filelocation" />
* <provider>
* </pre>
*
* res/xml/filelocation.xmlを用意する。<br>
*
* 以下のようにexternal-locationタグを指定することで、SDカードに保存される。
* <pre>
* <file-locations xmlns:android="http://schemas.android.com/apk/res/android">
* <external-location path="sample" />
* </file-locations>
* </pre>
* 属性pathには、SDカードからのパスを指定することができる。<br>
* <br>
* 以下のようにinternal-locationタグを指定することで、端末内のアプリ領域に保存される。
* <pre>
* <file-locations xmlns:android="http://schemas.android.com/apk/res/android">
* <internal-location path="sample" />
* </file-locations>
* </pre>
* 属性pathには、/data/data/{アプリのパッケージ名}/filesからのパスを指定することができる。<br>
* <br>
* なお、属性pathには絶対パス、相対パスのいずれかを指定できる。
* 絶対パスの先頭の / は省略可能。つまり、<code>path="/path/to/file"</code> と <code>path="path/to/file"</code>
* は同じ意味になる。<br />
* <br>
*
* 複数のexternal-location や internal-locationタグが記載された場合には、最後のタグが反映される。
*
* @author NTT DOCOMO, INC.
*/
public class FileProvider extends ContentProvider {
/**
* ファイルの保存場所.
*/
private FileLocation mLocation;
/**
* ファイルを入出力用のメソッド.
*
* @param uri ContentProviderのURL
* @param mode 書き込み読み込み時のモード
* @return ファイルを読み書きするためのストリーム
* @throws FileNotFoundException ファイルが見つからない場合に発生
*/
@Override
public ParcelFileDescriptor openFile(final Uri uri, final String mode) throws FileNotFoundException {
String accessToken = uri.getQueryParameter("");
if (!checkAccessToken(accessToken)) {
throw new IllegalArgumentException("accessToken is invalid.");
}
File file = new File(getBasePath(), uri.getPath());
ParcelFileDescriptor parcel = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
return parcel;
}
/**
* ファイルを管理するためのベースとなるパスを取得する.
* @return パス
*/
public File getBasePath() {
if (mLocation == null) {
mLocation = FileLocationParser.parse(getContext(), this.getClass().getName());
}
if (mLocation.getType() == FileLocationParser.TYPE_EXTERNAL_PATH) {
return new File(Environment.getExternalStorageDirectory(), mLocation.getPath());
} else {
return new File(getContext().getFilesDir(), mLocation.getPath());
}
}
/**
* アクセストークンの正当性をチェックする.
* @param accessToken アクセストークン
* @return アクセストークンが有効の場合にはtrue、それ以外はfalse
*/
private boolean checkAccessToken(final String accessToken) {
// TODO アクセストークンをチェックすること。
return true;
}
@Override
public int delete(final Uri uri, final String selection,
final String[] selectionArgs) {
return 0;
}
@Override
public String getType(final Uri uri) {
return null;
}
@Override
public Uri insert(final Uri uri, final ContentValues values) {
return null;
}
@Override
public boolean onCreate() {
return true;
}
@Override
public Cursor query(final Uri uri, final String[] projection,
final String selection, final String[] selectionArgs, final String sortOrder) {
return null;
}
@Override
public int update(final Uri uri, final ContentValues values,
final String selection, final String[] selectionArgs) {
return 0;
}
}