android上通过反射,获取存储器列表


各种android设备的存储器路径,是不一样的,比如T卡路径,可能是/mnt/sdcard、/mnt/extsd、/mnt/external_sd或者/mnt/sdcard2,有时内置存储器的路径也可能是/mnt/sdcard,而host usb存储器的路径也是各种各样的。
因此,想要运行在各种android设备上的应用,就必须在运行期间动态获取各个可用的存储器路径,避免一个存储器空间不足就不能运行的问题。
下面方法是通过反射,调用StorageManager的隐藏接口getVolumePaths(),实现获取存储器列表。
[java]
package ckl.storage.list;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import android.app.Activity;
import android.os.storage.StorageManager;

public class StorageList {
private Activity mActivity;
private StorageManager mStorageManager;
private Method mMethodGetPaths;

public StorageList(Activity activity) {
mActivity = activity;
if (mActivity != null) {
mStorageManager = (StorageManager)mActivity
.getSystemService(Activity.STORAGE_SERVICE);
try {
mMethodGetPaths = mStorageManager.getClass()
.getMethod("getVolumePaths");
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}

public String[] getVolumePaths() {
String[] paths = null;
try {
paths = (String[]) mMethodGetPaths.invoke(mStorageManager);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return paths;
}
}

另外,附上StorageManager.java
[java]
/*
* Copyright (C) 2008 The Android Open Source Project
*
* 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 android.os.storage;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
import android.util.SparseArray;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
* StorageManager is the interface to the systems storage service. The storage
* manager handles storage-related items such as Opaque Binary Blobs (OBBs).
* <p>
* OBBs contain a filesystem that maybe be encrypted on disk and mounted
* on-demand from an application. OBBs are a good way of providing large amounts
* of binary assets without packaging them into APKs as they may be multiple
* gigabytes in size. However, due to their size, they're most likely stored in
* a shared storage pool accessible from all programs. The system does not
* guarantee the security of the OBB file itself: if any program modifies the
* OBB, there is no guarantee that a read from that OBB will produce the
* expected output.
* <p>
* Get an instance of this class by calling
*{@linkandroid.content.Context#getSystemService(java.lang.String)} with an
* argument of{@linkandroid.content.Context#STORAGE_SERVICE}.
*/

public class StorageManager
{
private static final String TAG = "StorageManager";

/*
* Our internal MountService binder reference
*/
private IMountService mMountService;

/*
* The looper target for callbacks
*/
Looper mTgtLooper;

/*
* Target listener for binder callbacks
*/
private MountServiceBinderListener mBinderListener;

/*
* List of our listeners
*/
private List<ListenerDelegate> mListeners = new ArrayList<ListenerDelegate>();

/*
* Next available nonce
*/
final private AtomicInteger mNextNonce = new AtomicInteger(0);

private class MountServiceBinderListener extends IMountServiceListener.Stub {
public void onUsbMassStorageConnectionChanged(boolean available) {
final int size = mListeners.size();
for (int i = 0; i < size; i++) {
mListeners.get(i).sendShareAvailabilityChanged(available);
}
}

public void onStorageStateChanged(String path, String oldState, String newState) {
final int size = mListeners.size();
for (int i = 0; i < size; i++) {
mListeners.get(i).sendStorageStateChanged(path, oldState, newState);
}
}
}

/**
* Binder listener for OBB action results.
*/
private final ObbActionListener mObbActionListener = new ObbActionListener();

private class ObbActionListener extends IObbActionListener.Stub {
@SuppressWarnings("hiding")
private SparseArray<ObbListenerDelegate> mListeners = new SparseArray<ObbListenerDelegate>();

@Override
public void onObbResult(String filename, int nonce, int status) {
final ObbListenerDelegate delegate;
synchronized (mListeners) {
delegate = mListeners.get(nonce);
if (delegate != null) {
mListeners.remove(nonce);
}
}

if (delegate != null) {
delegate.sendObbStateChanged(filename, status);
}
}

public int addListener(OnObbStateChangeListener listener) {
final ObbListenerDelegate delegate = new ObbListenerDelegate(listener);

synchronized (mListeners) {
mListeners.put(delegate.nonce, delegate);
}

return delegate.nonce;
}
}

private int getNextNonce() {
return mNextNonce.getAndIncrement();
}

/**
* Private class containing sender and receiver code for StorageEvents.
*/
private class ObbListenerDelegate {
private final WeakReference<OnObbStateChangeListener> mObbEventListenerRef;
private final Handler mHandler;

private final int nonce;

ObbListenerDelegate(OnObbStateChangeListener listener) {
nonce = getNextNonce();
mObbEventListenerRef = new WeakReference<OnObbStateChangeListener>(listener);
mHandler = new Handler(mTgtLooper) {
@Override
public void handleMessage(Message msg) {
final OnObbStateChangeListener changeListener = getListener();
if (changeListener == null) {
return;
}

StorageEvent e = (StorageEvent) msg.obj;

if (msg.what == StorageEvent.EVENT_OBB_STATE_CHANGED) {
ObbStateChangedStorageEvent ev = (ObbStateChangedStorageEvent) e;
changeListener.onObbStateChange(ev.path, ev.state);
} else {
Log.e(TAG, "Unsupported event " + msg.what);
}
}
};
}

OnObbStateChangeListener getListener() {
if (mObbEventListenerRef == null) {
return null;
}
return mObbEventListenerRef.get();
}

void sendObbStateChanged(String path, int state) {
ObbStateChangedStorageEvent e = new ObbStateChangedStorageEvent(path, state);
mHandler.sendMessage(e.getMessage());
}
}

/**
* Message sent during an OBB status change event.
*/
private class ObbStateChangedStorageEvent extends StorageEvent {
public final String path;

public final int state;

public ObbStateChangedStorageEvent(String path, int state) {
super(EVENT_OBB_STATE_CHANGED);
this.path = path;
this.state = state;
}
}

/**
* Private base class for messages sent between the callback thread
* and the target looper handler.
*/
private class StorageEvent {
static final int EVENT_UMS_CONNECTION_CHANGED = 1;
static final int EVENT_STORAGE_STATE_CHANGED = 2;
static final int EVENT_OBB_STATE_CHANGED = 3;

private Message mMessage;

public StorageEvent(int what) {
mMessage = Message.obtain();
mMessage.what = what;
mMessage.obj = this;
}

public Message getMessage() {
return mMessage;
}
}

/**
* Message sent on a USB mass storage connection change.
*/
private class UmsConnectionChangedStorageEvent extends StorageEvent {
public boolean available;

public UmsConnectionChangedStorageEvent(boolean a) {
super(EVENT_UMS_CONNECTION_CHANGED);
available = a;
}
}

/**
* Message sent on volume state change.
*/
private class StorageStateChangedStorageEvent extends StorageEvent {
public String path;
public String oldState;
public String newState;

public StorageStateChangedStorageEvent(String p, String oldS, String newS) {
super(EVENT_STORAGE_STATE_CHANGED);
path = p;
oldState = oldS;
newState = newS;
}
}

/**
* Private class containing sender and receiver code for StorageEvents.
*/
private class ListenerDelegate {
final StorageEventListener mStorageEventListener;
private final Handler mHandler;

ListenerDelegate(StorageEventListener listener) {
mStorageEventListener = listener;
mHandler = new Handler(mTgtLooper) {
@Override
public void handleMessage(Message msg) {
StorageEvent e = (StorageEvent) msg.obj;

if (msg.what == StorageEvent.EVENT_UMS_CONNECTION_CHANGED) {
UmsConnectionChangedStorageEvent ev = (UmsConnectionChangedStorageEvent) e;
mStorageEventListener.onUsbMassStorageConnectionChanged(ev.available);
} else if (msg.what == StorageEvent.EVENT_STORAGE_STATE_CHANGED) {
StorageStateChangedStorageEvent ev = (StorageStateChangedStorageEvent) e;
mStorageEventListener.onStorageStateChanged(ev.path, ev.oldState, ev.newState);
} else {
Log.e(TAG, "Unsupported event " + msg.what);
}
}
};
}

StorageEventListener getListener() {
return mStorageEventListener;
}

void sendShareAvailabilityChanged(boolean available) {
UmsConnectionChangedStorageEvent e = new UmsConnectionChangedStorageEvent(available);
mHandler.sendMessage(e.getMessage());
}

void sendStorageStateChanged(String path, String oldState, String newState) {
StorageStateChangedStorageEvent e = new StorageStateChangedStorageEvent(path, oldState, newState);
mHandler.sendMessage(e.getMessage());
}
}

/**
* Constructs a StorageManager object through which an application can
* can communicate with the systems mount service.
*
* @param tgtLooper The{@android.os.Looper} which events will be received on.
*
* <p>Applications can get instance of this class by calling
*{@linkandroid.content.Context#getSystemService(java.lang.String)} with an argument
* of{@linkandroid.content.Context#STORAGE_SERVICE}.
*
* @hide
*/
public StorageManager(Looper tgtLooper) throws RemoteException {
mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount"));
if (mMountService == null) {
Log.e(TAG, "Unable to connect to mount service! - is it running yet?");
return;
}
mTgtLooper = tgtLooper;
mBinderListener = new MountServiceBinderListener();
mMountService.registerListener(mBinderListener);
}


/**
* Registers a{@linkandroid.os.storage.StorageEventListener StorageEventListener}.
*
* @param listener A{@linkandroid.os.storage.StorageEventListener StorageEventListener} object.
*
* @hide
*/
public void registerListener(StorageEventListener listener) {
if (listener == null) {
return;
}

synchronized (mListeners) {
mListeners.add(new ListenerDelegate(listener));
}
}

/**
* Unregisters a{@linkandroid.os.storage.StorageEventListener StorageEventListener}.
*
* @param listener A{@linkandroid.os.storage.StorageEventListener StorageEventListener} object.
*
* @hide
*/
public void unregisterListener(StorageEventListener listener) {
if (listener == null) {
return;
}

synchronized (mListeners) {
final int size = mListeners.size();
for (int i=0 ; i<size ; i++) {
ListenerDelegate l = mListeners.get(i);
if (l.getListener() == listener) {
mListeners.remove(i);
break;
}
}
}
}

/**
* Enables USB Mass Storage (UMS) on the device.
*
* @hide
*/
public void enableUsbMassStorage() {
try {
mMountService.setUsbMassStorageEnabled(true);
} catch (Exception ex) {
Log.e(TAG, "Failed to enable UMS", ex);
}
}

/**
* Disables USB Mass Storage (UMS) on the device.
*
* @hide
*/
public void disableUsbMassStorage() {
try {
mMountService.setUsbMassStorageEnabled(false);
} catch (Exception ex) {
Log.e(TAG, "Failed to disable UMS", ex);
}
}

/**
* Query if a USB Mass Storage (UMS) host is connected.
* @return true if UMS host is connected.
*
* @hide
*/
public boolean isUsbMassStorageConnected() {
try {
return mMountService.isUsbMassStorageConnected();
} catch (Exception ex) {
Log.e(TAG, "Failed to get UMS connection state", ex);
}
return false;
}

/**
* Query if a USB Mass Storage (UMS) is enabled on the device.
* @return true if UMS host is enabled.
*
* @hide
*/
public boolean isUsbMassStorageEnabled() {
try {
return mMountService.isUsbMassStorageEnabled();
} catch (RemoteException rex) {
Log.e(TAG, "Failed to get UMS enable state", rex);
}
return false;
}

/**
* Mount an Opaque Binary Blob (OBB) file. If a <code>key</code> is
* specified, it is supplied to the mounting process to be used in any
* encryption used in the OBB.
* <p>
* The OBB will remain mounted for as long as the StorageManager reference
* is held by the application. As soon as this reference is lost, the OBBs
* in use will be unmounted. The{@linkOnObbStateChangeListener} registered
* with this call will receive the success or failure of this operation.
* <p>
* <em>Note:</em> you can only mount OBB files for which the OBB tag on the
* file matches a package ID that is owned by the calling program's UID.
* That is, shared UID applications can attempt to mount any other
* application's OBB that shares its UID.
*
* @param filename the path to the OBB file
* @param key secret used to encrypt the OBB; may be <code>null</code> if no
* encryption was used on the OBB.
* @param listener will receive the success or failure of the operation
* @return whether the mount call was successfully queued or not
*/
public boolean mountObb(String filename, String key, OnObbStateChangeListener listener) {
if (filename == null) {
throw new IllegalArgumentException("filename cannot be null");
}

if (listener == null) {
throw new IllegalArgumentException("listener cannot be null");
}

try {
final int nonce = mObbActionListener.addListener(listener);
mMountService.mountObb(filename, key, mObbActionListener, nonce);
return true;
} catch (RemoteException e) {
Log.e(TAG, "Failed to mount OBB", e);
}

return false;
}

/**
* Unmount an Opaque Binary Blob (OBB) file asynchronously. If the
* <code>force</code> flag is true, it will kill any application needed to
* unmount the given OBB (even the calling application).
* <p>
* The{@linkOnObbStateChangeListener} registered with this call will
* receive the success or failure of this operation.
* <p>
* <em>Note:</em> you can only mount OBB files for which the OBB tag on the
* file matches a package ID that is owned by the calling program's UID.
* That is, shared UID applications can obtain access to any other
* application's OBB that shares its UID.
* <p>
*
* @param filename path to the OBB file
* @param force whether to kill any programs using this in order to unmount
* it
* @param listener will receive the success or failure of the operation
* @return whether the unmount call was successfully queued or not
*/
public boolean unmountObb(String filename, boolean force, OnObbStateChangeListener listener) {
if (filename == null) {
throw new IllegalArgumentException("filename cannot be null");
}

if (listener == null) {
throw new IllegalArgumentException("listener cannot be null");
}

try {
final int nonce = mObbActionListener.addListener(listener);
mMountService.unmountObb(filename, force, mObbActionListener, nonce);
return true;
} catch (RemoteException e) {
Log.e(TAG, "Failed to mount OBB", e);
}

return false;
}

/**
* Check whether an Opaque Binary Blob (OBB) is mounted or not.
*
* @param filename path to OBB image
* @return true if OBB is mounted; false if not mounted or on error
*/
public boolean isObbMounted(String filename) {
if (filename == null) {
throw new IllegalArgumentException("filename cannot be null");
}

try {
return mMountService.isObbMounted(filename);
} catch (RemoteException e) {
Log.e(TAG, "Failed to check if OBB is mounted", e);
}

return false;
}

/**
* Check the mounted path of an Opaque Binary Blob (OBB) file. This will
* give you the path to where you can obtain access to the internals of the
* OBB.
*
* @param filename path to OBB image
* @return absolute path to mounted OBB image data or <code>null</code> if
* not mounted or exception encountered trying to read status
*/
public String getMountedObbPath(String filename) {
if (filename == null) {
throw new IllegalArgumentException("filename cannot be null");
}

try {
return mMountService.getMountedObbPath(filename);
} catch (RemoteException e) {
Log.e(TAG, "Failed to find mounted path for OBB", e);
}

return null;
}

/**
* Gets the state of a volume via its mountpoint.
* @hide
*/
public String getVolumeState(String mountPoint) {
try {
return mMountService.getVolumeState(mountPoint);
} catch (RemoteException e) {
Log.e(TAG, "Failed to get volume state", e);
return null;
}
}

/**
* Returns list of all mountable volumes.
* @hide
*/
public StorageVolume[] getVolumeList() {
try {
Parcelable[] list = mMountService.getVolumeList();
if (list == null) return new StorageVolume[0];
int length = list.length;
StorageVolume[] result = new StorageVolume[length];
for (int i = 0; i < length; i++) {
result[i] = (StorageVolume)list[i];
}
return result;
} catch (RemoteException e) {
Log.e(TAG, "Failed to get volume list", e);
return null;
}
}

/**
* Returns list of paths for all mountable volumes.
* @hide
*/
public String[] getVolumePaths() {
StorageVolume[] volumes = getVolumeList();
if (volumes == null) return null;
int count = volumes.length;
String[] paths = new String[count];
for (int i = 0; i < count; i++) {
paths[i] = volumes[i].getPath();
}
return paths;
}
}

更多相关文章

  1. android 文档路径获取
  2. I2C-Tools 4.0使用说明及android平台移植,提供源码下载路径
  3. android 获取系统默认路径
  4. Android 安装路径问题 -- 导致无法启动模拟器
  5. Android 根据Video绝对路径获取其缩略图
  6. android获取指定路径下目录文件
  7. 2013.12.23 ——— android assents文件路径

随机推荐

  1. Android:Camera
  2. android横屏竖屏处理
  3. Android(安卓)画图之Matrix(二)
  4. android:targetSdkVersion引起的问题
  5. 【起航计划 002】2015 起航计划 Android(
  6. 搭建自己的Android浏览器(一)
  7. 在android上运行native可执行程序
  8. 【知识点】android中的adapter
  9. Android(安卓)开发入门
  10. Android(安卓)DEV : setOnClickListener(