BluetoothOppManager.java revision 1ac5507790a87810061a19dadec36eb328a222ea
1/*
2 * Copyright (c) 2008-2009, Motorola, Inc.
3 *
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * - Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 *
12 * - Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
15 *
16 * - Neither the name of the Motorola, Inc. nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33package com.android.bluetooth.opp;
34
35import com.android.bluetooth.R;
36
37import android.bluetooth.BluetoothAdapter;
38import android.bluetooth.BluetoothDevice;
39import android.content.ContentResolver;
40import android.content.ContentValues;
41import android.content.Context;
42import android.content.SharedPreferences;
43import android.net.Uri;
44import android.util.Log;
45
46import java.util.ArrayList;
47
48/**
49 * This class provides a simplified interface on top of other Bluetooth service
50 * layer components; Also it handles some Opp application level variables. It's
51 * a singleton got from BluetoothOppManager.getInstance(context);
52 */
53public class BluetoothOppManager {
54    private static final String TAG = "BluetoothOppManager";
55
56    private static BluetoothOppManager INSTANCE;
57
58    /** Used when obtaining a reference to the singleton instance. */
59    private static Object INSTANCE_LOCK = new Object();
60
61    private boolean mInitialized;
62
63    private Context mContext;
64
65    private BluetoothAdapter mAdapter;
66
67    private String mMimeTypeOfSendigFile;
68
69    private String mUriOfSendingFile;
70
71    private String mMimeTypeOfSendigFiles;
72
73    private ArrayList<Uri> mUrisOfSendingFiles;
74
75    private boolean mCanStartTransfer = false;
76
77    private static final String OPP_PREFERENCE_FILE = "OPPMGR";
78
79    private static final String SENDING_FLAG = "SENDINGFLAG";
80
81    private static final String MIME_TYPE = "MIMETYPE";
82
83    private static final String FILE_URI = "FILE_URI";
84
85    private static final String MIME_TYPE_MULTIPLE = "MIMETYPE_MULTIPLE";
86
87    private static final String FILE_URIS = "FILE_URIS";
88
89    private static final String MULTIPLE_FLAG = "MULTIPLE_FLAG";
90
91    private static final String ARRAYLIST_ITEM_SEPERATOR = "!";
92
93    // used to judge if need continue sending process after received a
94    // ENABLED_ACTION
95    public boolean mSendingFlag;
96
97    public boolean mMultipleFlag;
98
99    public int mfileNumInBatch;
100
101    /**
102     * Get singleton instance.
103     */
104    public static BluetoothOppManager getInstance(Context context) {
105        synchronized (INSTANCE_LOCK) {
106            if (INSTANCE == null) {
107                INSTANCE = new BluetoothOppManager();
108            }
109            INSTANCE.init(context);
110
111            return INSTANCE;
112        }
113    }
114
115    /**
116     * init
117     */
118    private boolean init(Context context) {
119        if (mInitialized)
120            return true;
121        mInitialized = true;
122
123        // This will be around as long as this process is
124        mContext = context.getApplicationContext();
125
126        mAdapter = (BluetoothAdapter) context.getSystemService(Context.BLUETOOTH_SERVICE);
127        if (mAdapter == null) {
128            if (Constants.LOGVV) {
129                Log.v(TAG, "BLUETOOTH_SERVICE is not started! ");
130            }
131        }
132
133        // Restore data from preference
134        restoreApplicationData();
135
136        return true;
137    }
138
139    /**
140     * Restore data from preference
141     */
142    private void restoreApplicationData() {
143        SharedPreferences settings = mContext.getSharedPreferences(OPP_PREFERENCE_FILE, 0);
144
145        mSendingFlag = settings.getBoolean(SENDING_FLAG, false);
146        mMimeTypeOfSendigFile = settings.getString(MIME_TYPE, null);
147        mUriOfSendingFile = settings.getString(FILE_URI, null);
148        mMimeTypeOfSendigFiles = settings.getString(MIME_TYPE_MULTIPLE, null);
149        mMultipleFlag = settings.getBoolean(MULTIPLE_FLAG, false);
150
151        if (Constants.LOGVV) {
152            Log.v(TAG, "restoreApplicationData! " + mSendingFlag + mMultipleFlag
153                    + mMimeTypeOfSendigFile + mUriOfSendingFile);
154        }
155
156        String strUris = settings.getString(FILE_URIS, null);
157        // TODO(Moto): restore mUrisOfSendingFiles from strUris.
158    }
159
160    /**
161     * Save application data to preference, need restore these data later
162     */
163    private void onDestroy() {
164        SharedPreferences.Editor editor = mContext.getSharedPreferences(OPP_PREFERENCE_FILE, 0)
165                .edit();
166        editor.putBoolean(SENDING_FLAG, mSendingFlag).commit();
167        editor.putString(MIME_TYPE, mMimeTypeOfSendigFile).commit();
168        editor.putString(FILE_URI, mUriOfSendingFile).commit();
169        editor.putString(MIME_TYPE_MULTIPLE, mMimeTypeOfSendigFiles).commit();
170        editor.putBoolean(MULTIPLE_FLAG, mMultipleFlag).commit();
171        String strUris;
172        StringBuilder sb = new StringBuilder();
173        for (int i = 0, count = mUrisOfSendingFiles.size(); i < count; i++) {
174            Uri uriContent = mUrisOfSendingFiles.get(i);
175            sb.append(uriContent);
176            sb.append(ARRAYLIST_ITEM_SEPERATOR);
177        }
178        strUris = sb.toString();
179        editor.putString(FILE_URIS, strUris).commit();
180        if (Constants.LOGVV) {
181            Log.v(TAG, "finalize is called and application data saved by SharedPreference! ");
182        }
183    }
184
185    /**
186     * Save data to preference when this class is destroyed by system due to
187     * memory lack
188     */
189    protected void finalize() throws Throwable {
190        try {
191            onDestroy();
192        } finally {
193            super.finalize();
194        }
195    }
196
197    public void saveSendingFileInfo(String mimeType, String uri) {
198        mMultipleFlag = false;
199        mMimeTypeOfSendigFile = mimeType;
200        mUriOfSendingFile = uri;
201        mCanStartTransfer = true;
202    }
203
204    public void saveSendingFileInfo(String mimeType, ArrayList<Uri> uris) {
205        mMultipleFlag = true;
206        mMimeTypeOfSendigFiles = mimeType;
207        mUrisOfSendingFiles = uris;
208        mCanStartTransfer = true;
209    }
210    /**
211     * Get the current status of Bluetooth hardware.
212     * @return true if Bluetooth enabled, false otherwise.
213     */
214    public boolean isEnabled() {
215        if (mAdapter != null) {
216            return mAdapter.isEnabled();
217        } else {
218            if (Constants.LOGVV) {
219                Log.v(TAG, "BLUETOOTH_SERVICE is not available! ");
220            }
221            return false;
222        }
223    }
224
225    /**
226     * Enable Bluetooth hardware.
227     */
228    public void enableBluetooth() {
229        if (mAdapter != null) {
230            mAdapter.enable();
231        }
232    }
233
234    /**
235     * Disable Bluetooth hardware.
236     */
237    public void disableBluetooth() {
238        if (mAdapter != null) {
239            mAdapter.disable();
240        }
241    }
242
243    /**
244     * Get device name per bluetooth address.
245     */
246    public String getDeviceName(BluetoothDevice device) {
247        String deviceName;
248
249        deviceName = BluetoothOppPreference.getInstance(mContext).getName(device);
250
251        if (deviceName == null && mAdapter != null) {
252            deviceName = device.getName();
253        }
254
255        if (deviceName == null) {
256            deviceName = mContext.getString(R.string.unknown_device);
257        }
258
259        return deviceName;
260    }
261
262    /**
263     * insert sending sessions to db, only used by Opp application.
264     */
265    public void startTransfer(BluetoothDevice device) {
266        if (device == null) {
267            Log.e(TAG, "Target bt device is null!");
268            return;
269        }
270
271        if (!mCanStartTransfer) {
272            if (Constants.LOGVV) {
273                Log.v(TAG, "No transfer info restored: fileType&fileName");
274            }
275            return;
276        }
277
278        if (mMultipleFlag == true) {
279            int count = mUrisOfSendingFiles.size();
280            mfileNumInBatch = count;
281
282            Long ts = System.currentTimeMillis();
283            for (int i = 0; i < count; i++) {
284                Uri fileUri = mUrisOfSendingFiles.get(i);
285                ContentResolver contentResolver = mContext.getContentResolver();
286                String contentType = contentResolver.getType(fileUri);
287                if (Constants.LOGVV) {
288                    Log.v(TAG, "Got mimetype: " + contentType + "  Got uri: " + fileUri);
289                }
290
291                ContentValues values = new ContentValues();
292                values.put(BluetoothShare.URI, fileUri.toString());
293                values.put(BluetoothShare.MIMETYPE, contentType);
294                values.put(BluetoothShare.DESTINATION, device.getAddress());
295                values.put(BluetoothShare.TIMESTAMP, ts);
296
297                final Uri contentUri = mContext.getContentResolver().insert(
298                        BluetoothShare.CONTENT_URI, values);
299                if (Constants.LOGVV) {
300                    Log.v(TAG, "Insert contentUri: " + contentUri + "  to device: "
301                            + getDeviceName(device));
302                }
303            }
304        } else {
305            ContentValues values = new ContentValues();
306            values.put(BluetoothShare.URI, mUriOfSendingFile);
307            values.put(BluetoothShare.MIMETYPE, mMimeTypeOfSendigFile);
308            values.put(BluetoothShare.DESTINATION, device.getAddress());
309
310            final Uri contentUri = mContext.getContentResolver().insert(BluetoothShare.CONTENT_URI,
311                    values);
312            if (Constants.LOGVV) {
313                Log.v(TAG, "Insert contentUri: " + contentUri + "  to device: "
314                        + getDeviceName(device));
315            }
316        }
317
318        // reset vars
319        mMimeTypeOfSendigFile = null;
320        mUriOfSendingFile = null;
321        mUrisOfSendingFiles = null;
322        mMultipleFlag = false;
323        mCanStartTransfer = false;
324    }
325}
326