org.xwalk.runtime.extension.api.device_capabilities.DeviceCapabilitiesStorage.java Source code

Java tutorial

Introduction

Here is the source code for org.xwalk.runtime.extension.api.device_capabilities.DeviceCapabilitiesStorage.java

Source

// Copyright (c) 2013 Intel Corporation. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.xwalk.runtime.extension.api.device_capabilities;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Environment;
import android.os.StatFs;
import android.util.Log;
import android.util.SparseArray;

import java.io.File;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.xwalk.runtime.extension.XWalkExtensionContext;

class DeviceCapabilitiesStorage {
    private static final String TAG = "DeviceCapabilitiesStorage";

    private DeviceCapabilities mDeviceCapabilities;
    private XWalkExtensionContext mExtensionContext;

    private static int mStorageCount = 0;
    // Holds all available storages.
    private final SparseArray<StorageUnit> mStorageList = new SparseArray<StorageUnit>();

    private boolean mIsListening = false;
    private IntentFilter mIntentFilter = new IntentFilter();

    class StorageUnit {
        private int mId;
        private String mName;
        private String mType;
        private long mCapacity;
        private long mAvailCapacity;
        private String mPath;

        public StorageUnit(int id, String name, String type) {
            mId = id;
            mName = name;
            mType = type;
            mPath = "";
            mCapacity = 0;
            mAvailCapacity = 0;
        }

        public int getId() {
            return mId;
        }

        public String getName() {
            return mName;
        }

        public String getType() {
            return mType;
        }

        public String getPath() {
            return mPath;
        }

        public long getCapacity() {
            return mCapacity;
        }

        public long getAvailCapacity() {
            return mAvailCapacity;
        }

        public void setType(String type) {
            mType = type;
        }

        public void setPath(String path) {
            mPath = path;
            updateCapacity();
        }

        public boolean isSame(StorageUnit unit) {
            return mPath == unit.getPath();
        }

        public boolean isValid() {
            if (mPath == null || mPath.isEmpty()) {
                mCapacity = 0;
                mAvailCapacity = 0;
                return false;
            }

            File file = new File(mPath);
            return file.canRead();
        }

        public void updateCapacity() {
            if (!isValid()) {
                return;
            }

            StatFs stat = new StatFs(mPath);
            // FIXME(halton): After API level 18, use getTotalBytes() and
            // getAvailableBytes() instead
            long blockSize = stat.getBlockSize();
            mCapacity = blockSize * stat.getBlockCount();
            mAvailCapacity = blockSize * stat.getAvailableBlocks();
        }

        public JSONObject convertToJSON() {
            JSONObject out = new JSONObject();

            try {
                out.put("id", mId + 1); // Display from 1
                out.put("name", mName);
                out.put("type", mType);
                out.put("capacity", mCapacity);
                out.put("availCapacity", mAvailCapacity);
            } catch (JSONException e) {
                return mDeviceCapabilities.setErrorMessage(e.toString());
            }

            return out;
        }
    }

    private final BroadcastReceiver mStorageListener = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (Intent.ACTION_MEDIA_MOUNTED.equals(action)) {
                notifyAndSaveAttachedStorage();
            }

            if (Intent.ACTION_MEDIA_UNMOUNTED.equals(action) || Intent.ACTION_MEDIA_REMOVED.equals(action)
                    || Intent.ACTION_MEDIA_BAD_REMOVAL.equals(action)) {
                notifyAndRemoveDetachedStorage();
            }
        }
    };

    public DeviceCapabilitiesStorage(DeviceCapabilities instance, XWalkExtensionContext context) {
        mDeviceCapabilities = instance;
        mExtensionContext = context;

        registerIntentFilter();

        // Fetch the original storage list
        initStorageList();
    }

    public JSONObject getInfo() {
        JSONObject out = new JSONObject();
        JSONArray arr = new JSONArray();
        try {
            for (int i = 0; i < mStorageList.size(); i++) {
                arr.put(mStorageList.valueAt(i).convertToJSON());
            }
            out.put("storages", arr);
        } catch (JSONException e) {
            return mDeviceCapabilities.setErrorMessage(e.toString());
        }

        return out;
    }

    private void initStorageList() {
        mStorageList.clear();
        mStorageCount = 0;

        StorageUnit unit = new StorageUnit(mStorageCount, "Internal", "fixed");
        unit.setPath(Environment.getRootDirectory().getAbsolutePath());
        mStorageList.put(mStorageCount, unit);
        ++mStorageCount;

        // Attempt to add emulated stroage first
        int sdcardNum = mStorageCount - 1; // sdcard count from 0
        unit = new StorageUnit(mStorageCount, new String("sdcard" + Integer.toString(sdcardNum)), "fixed");
        if (Environment.isExternalStorageRemovable()) {
            unit.setType("removable");
        }
        unit.setPath(Environment.getExternalStorageDirectory().getAbsolutePath());

        if (unit.isValid()) {
            mStorageList.put(mStorageCount, unit);
            ++mStorageCount;
        }

        // Then attempt to add real removable storage
        attemptAddExternalStorage();
    }

    private void registerIntentFilter() {
        mIntentFilter.addAction(Intent.ACTION_MEDIA_BAD_REMOVAL);
        mIntentFilter.addAction(Intent.ACTION_MEDIA_MOUNTED);
        mIntentFilter.addAction(Intent.ACTION_MEDIA_REMOVED);
        mIntentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
        mIntentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED);
        mIntentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
        mIntentFilter.addDataScheme("file");
    }

    private boolean attemptAddExternalStorage() {
        int sdcardNum = mStorageCount - 1;
        StorageUnit unit = new StorageUnit(mStorageCount, new String("sdcard" + Integer.toString(sdcardNum)),
                "removable");
        unit.setPath("/storage/sdcard" + Integer.toString(sdcardNum));

        if (!unit.isValid()) {
            return false;
        }

        for (int i = 0; i < mStorageList.size(); i++) {
            if (unit.isSame(mStorageList.valueAt(i))) {
                return false;
            }
        }

        mStorageList.put(mStorageCount, unit);
        ++mStorageCount;
        return true;
    }

    public void registerListener() {
        if (mIsListening) {
            return;
        }

        mIsListening = true;
        mExtensionContext.getActivity().registerReceiver(mStorageListener, mIntentFilter);
    }

    public void unregisterListener() {
        if (!mIsListening) {
            return;
        }

        mIsListening = false;
        mExtensionContext.getActivity().unregisterReceiver(mStorageListener);
    }

    private void notifyAndSaveAttachedStorage() {
        if (!attemptAddExternalStorage()) {
            return;
        }

        StorageUnit unit = mStorageList.valueAt(mStorageList.size() - 1);
        JSONObject out = new JSONObject();
        try {
            out.put("reply", "attachStorage");
            out.put("eventName", "storageattach");
            out.put("data", unit.convertToJSON());

            mDeviceCapabilities.broadcastMessage(out.toString());
        } catch (JSONException e) {
            mDeviceCapabilities.printErrorMessage(e);
        }

    }

    private void notifyAndRemoveDetachedStorage() {
        StorageUnit unit = mStorageList.valueAt(mStorageList.size() - 1);

        if (unit.getType() != "removable") {
            return;
        }

        JSONObject out = new JSONObject();
        try {
            out.put("reply", "detachStorage");
            out.put("eventName", "storagedetach");
            out.put("data", unit.convertToJSON());

            mDeviceCapabilities.broadcastMessage(out.toString());
            mStorageList.remove(unit.getId());
            --mStorageCount;
        } catch (JSONException e) {
            mDeviceCapabilities.printErrorMessage(e);
        }
    }

    public void onResume() {
        // Fistly, check the lasted external storage is valid.
        // If not, remove it and send "ondetached" event.
        StorageUnit lastUnit = mStorageList.valueAt(mStorageList.size() - 1);
        if (!lastUnit.isValid()) {
            notifyAndRemoveDetachedStorage();
        }

        // Secondly, attmpt to add a possible external storage and send "onattached" event.
        notifyAndSaveAttachedStorage();

        registerListener();
    }

    public void onPause() {
        unregisterListener();
    }

    public void onDestroy() {
    }
}