/* FileLocationParser.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 java.io.IOException; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ProviderInfo; import android.content.res.XmlResourceParser; /** * ファイルの保存場所を解析する. * @author NTT DOCOMO, INC. */ final class FileLocationParser { /** * ファイル保存場所を格納するメタデータの名前. */ public static final String FILE_PROVIDER_META_DATA = "filelocation"; /** * Environment.getExternalStorageDirectory()で取得できる外部領域を表す. */ public static final int TYPE_EXTERNAL_PATH = 1; /** * Context.getFilesDir()で取得できるfiles/を表す. */ public static final int TYPE_INTERNAL_PATH = 2; /** * 外部領域を表すタグ. */ private static final String TAG_EXTERNAL_PATH = "external-location"; /** * アプリ内部保存領域を表すタグ. */ private static final String TAG_INTERNAL_PATH = "internal-location"; /** * パスを表すタグ. */ private static final String ATTR_PATH = "path"; /** * コンストラクタ. * ユーティリティクラスなので、privateにしておく。 */ private FileLocationParser() { } /** * AndroidManifest.xmlからproviderタグを探し出して、ファイルの保存先が定義されているxmlを解析する. * * <p> * 保存箇所が設定されていない場合には、デフォルトの保存場所を指定する。<br> * デフォルトの保存場所は、外部領域(SDカード)の直下にデバイスプラグインのパッケージで作成する。 * </p> * * @param context コンテキスト * @param fileProvider FileProviderクラス名 * @return ファイルの保存場所 */ public static FileLocation parse(final Context context, final String fileProvider) { PackageManager pkgMgr = context.getPackageManager(); FileLocation location = null; try { PackageInfo packageInfo = pkgMgr.getPackageInfo(context.getPackageName(), PackageManager.GET_PROVIDERS | PackageManager.GET_META_DATA); ProviderInfo[] providers = packageInfo.providers; if (providers != null) { for (ProviderInfo provider : providers) { if (fileProvider.equals(provider.name)) { location = parse(pkgMgr, provider); } } } } catch (NameNotFoundException e) { location = null; } // デフォルト設定 if (location == null) { location = new FileLocation(); location.mType = TYPE_EXTERNAL_PATH; location.mPath = context.getPackageName(); } else { // パスが指定されていない場合は、デフォルトを設定 if (location.mPath == null) { location.mPath = context.getPackageName(); } } return location; } /** * providerタグに存在するメタデータからxmlを読み込み、解析を行う. * * <p> * 解析に失敗もしくは、メタデータが存在しない場合には<code>null</code>を返却する。 * </p> * * @param pkgMgr パッケージマネジャー * @param info providerタグ情報 * @return 解析結果 */ private static FileLocation parse(final PackageManager pkgMgr, final ProviderInfo info) { XmlResourceParser xpp = info.loadXmlMetaData(pkgMgr, FILE_PROVIDER_META_DATA); if (xpp == null) { return null; } try { return parseFilePath(xpp); } catch (XmlPullParserException e) { return null; } catch (IOException e) { return null; } } /** * ファイル保存場所が記載されているxmlを解析する. * @param xpp xmlパーサ * @return 解析結果 * @throws XmlPullParserException xmlの解析に失敗した場合 * @throws IOException xmlファイルの読み込みに失敗した場合 */ private static FileLocation parseFilePath(final XmlResourceParser xpp) throws XmlPullParserException, IOException { FileLocation location = new FileLocation(); int eventType = xpp.getEventType(); while (eventType != XmlPullParser.END_DOCUMENT) { final String name = xpp.getName(); switch (eventType) { case XmlPullParser.START_TAG: if (TAG_EXTERNAL_PATH.equals(name)) { location.mType = TYPE_EXTERNAL_PATH; location.mPath = xpp.getAttributeValue(null, ATTR_PATH); } else if (TAG_INTERNAL_PATH.equals(name)) { location.mType = TYPE_INTERNAL_PATH; location.mPath = xpp.getAttributeValue(null, ATTR_PATH); } break; case XmlPullParser.END_TAG: break; default: break; } eventType = xpp.next(); } return location; } /** * ファイル保存場所のデータを格納するクラス. * @author NTT DOCOMO, INC. */ public static class FileLocation { /** * 保存場所. * <ul> * <li>{@link FileLocationParser#TYPE_EXTERNAL_PATH}外部保存領域</li> * <li>{@link FileLocationParser#TYPE_INTERNAL_PATH}アプリ保存領域</li> * </ul> */ private int mType; /** * 保存するパス. */ private String mPath; /** * 保存場所のタイプを取得する. * @return タイプ */ public int getType() { return mType; } /** * 保存場所のタイプを取得する. * @param type タイプ */ public void setType(final int type) { this.mType = type; } /** * パスを取得する. * @return パス */ public String getPath() { return mPath; } /** * パスを設定する. * @param path パス */ public void setPath(final String path) { this.mPath = path; } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("{") .append("type:") .append(mType) .append(", path:") .append(mPath) .append("}"); return builder.toString(); } } }