1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.providers.calendar;
18
19import android.app.Activity;
20import android.content.Intent;
21import android.media.MediaScannerConnection;
22import android.net.Uri;
23import android.os.AsyncTask;
24import android.os.Bundle;
25import android.os.Environment;
26import android.util.Log;
27import android.view.View;
28import android.view.Window;
29import android.view.View.OnClickListener;
30import android.widget.Button;
31import android.widget.TextView;
32
33import java.io.File;
34import java.io.FileInputStream;
35import java.io.FileOutputStream;
36import java.io.IOException;
37import java.io.InputStream;
38import java.util.zip.ZipEntry;
39import java.util.zip.ZipOutputStream;
40
41/**
42 * Prompts the user before copying their calendar database to the SD card.
43 *
44 */
45public class CalendarDebugActivity extends Activity implements OnClickListener {
46    private static String TAG = "CalendarDebugActivity";
47    private Button mConfirmButton;
48    private Button mCancelButton;
49    private Button mDeleteButton;
50    private TextView mTextView;
51
52    private static final String OUT_FILE = "calendar.db.zip";
53    private static final String MIME_TYPE = "application/zip";
54
55    protected void onCreate(Bundle savedInstanceState) {
56        // Be sure to call the super class.
57        super.onCreate(savedInstanceState);
58
59        requestWindowFeature(Window.FEATURE_LEFT_ICON);
60
61        setContentView(R.layout.dialog_activity);
62
63        getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON,
64                android.R.drawable.ic_dialog_alert);
65
66        mConfirmButton = (Button) findViewById(R.id.confirm);
67        mCancelButton = (Button) findViewById(R.id.cancel);
68        mDeleteButton = (Button) findViewById(R.id.delete);
69        updateDeleteButton();
70    }
71
72    private void updateDeleteButton() {
73        final boolean fileExist =
74            new File(Environment.getExternalStorageDirectory(), OUT_FILE).exists();
75        mDeleteButton.setEnabled(fileExist);
76    }
77
78    @Override
79    public void onClick(View v) {
80        switch (v.getId()) {
81            case R.id.confirm:
82                mConfirmButton.setEnabled(false);
83                mCancelButton.setEnabled(false);
84                new DumpDbTask().execute();
85                break;
86            case R.id.delete:
87                cleanup();
88                updateDeleteButton();
89                break;
90            case R.id.cancel:
91                finish();
92                break;
93        }
94    }
95
96    private void cleanup() {
97        Log.i(TAG, "Deleting " + OUT_FILE);
98        File outFile = new File(Environment.getExternalStorageDirectory(), OUT_FILE);
99        outFile.delete();
100    }
101
102    private class DumpDbTask extends AsyncTask<Void, Void, File> {
103
104        /**
105         * Starts spinner while task is running.
106         */
107        @Override
108        protected void onPreExecute() {
109            setProgressBarIndeterminateVisibility(true);
110        }
111
112        protected File doInBackground(Void... params) {
113            InputStream is = null;
114            ZipOutputStream os = null;
115
116            try {
117                File path = Environment.getExternalStorageDirectory();
118                File outFile = new File(path, OUT_FILE);
119                outFile.delete();
120                Log.i(TAG, "Outfile=" + outFile.getAbsolutePath());
121
122                final File inFile = getDatabasePath("calendar.db");
123                is = new FileInputStream(inFile);
124
125                os = new ZipOutputStream(new FileOutputStream(outFile));
126                os.putNextEntry(new ZipEntry(inFile.getName()));
127
128                byte[] buf = new byte[4096];
129                int totalLen = 0;
130                while (true) {
131                    int len = is.read(buf);
132                    if (len <= 0) {
133                        break;
134                    }
135                    os.write(buf, 0, len);
136                    totalLen += len;
137                }
138                os.closeEntry();
139
140                Log.i(TAG, "bytes read " + totalLen);
141                os.flush();
142                os.close();
143                os = null;
144
145                // Tell the media scanner about the new file so that it is
146                // immediately available to the user.
147                MediaScannerConnection.scanFile(CalendarDebugActivity.this, new String[] {
148                    outFile.toString()
149                }, new String[] {
150                    MIME_TYPE
151                }, null);
152                return outFile;
153
154            } catch (IOException e) {
155                Log.i(TAG, "Error " + e.toString());
156            } finally {
157                try {
158                    if (is != null) {
159                        is.close();
160                    }
161                    if (os != null) {
162                        os.close();
163                    }
164                } catch (IOException e) {
165                    Log.i(TAG, "Error " + e.toString());
166                }
167            }
168            return null;
169        }
170
171        /**
172         * Runs on the UI thread
173         */
174        @Override
175        protected void onPostExecute(File outFile) {
176            if (outFile != null) {
177                emailFile(outFile);
178            }
179        }
180    }
181
182    @Override
183    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
184        updateDeleteButton();
185        mConfirmButton.setEnabled(true);
186        mCancelButton.setEnabled(true);
187    }
188
189    private void emailFile(File file) {
190        Log.i(TAG, "Drafting email to send " + file.getAbsolutePath());
191        Intent intent = new Intent(Intent.ACTION_SEND);
192        intent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.debug_tool_email_subject));
193        intent.putExtra(Intent.EXTRA_TEXT, getString(R.string.debug_tool_email_body));
194        intent.setType(MIME_TYPE);
195        intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
196        startActivityForResult(Intent.createChooser(intent,
197                getString(R.string.debug_tool_email_sender_picker)), 0);
198    }
199}
200