19774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan/*
29774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan * Copyright (C) 2011 The Android Open Source Project
39774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan *
49774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan * Licensed under the Apache License, Version 2.0 (the "License");
59774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan * you may not use this file except in compliance with the License.
69774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan * You may obtain a copy of the License at
79774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan *
89774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan *      http://www.apache.org/licenses/LICENSE-2.0
99774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan *
109774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan * Unless required by applicable law or agreed to in writing, software
119774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan * distributed under the License is distributed on an "AS IS" BASIS,
129774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan * See the License for the specific language governing permissions and
149774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan * limitations under the License.
159774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan */
169774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan
179774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chanpackage com.android.providers.calendar;
189774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan
199774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chanimport android.app.Activity;
209774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chanimport android.content.Intent;
219774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chanimport android.media.MediaScannerConnection;
229774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chanimport android.net.Uri;
239774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chanimport android.os.AsyncTask;
249774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chanimport android.os.Bundle;
259774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chanimport android.os.Environment;
269774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chanimport android.util.Log;
279774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chanimport android.view.View;
289774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chanimport android.view.Window;
299774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chanimport android.view.View.OnClickListener;
309774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chanimport android.widget.Button;
319774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chanimport android.widget.TextView;
329774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan
339774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chanimport java.io.File;
349774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chanimport java.io.FileInputStream;
359774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chanimport java.io.FileOutputStream;
369774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chanimport java.io.IOException;
379774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chanimport java.io.InputStream;
389774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chanimport java.util.zip.ZipEntry;
399774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chanimport java.util.zip.ZipOutputStream;
409774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan
419774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan/**
429774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan * Prompts the user before copying their calendar database to the SD card.
439774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan *
449774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan */
459774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chanpublic class CalendarDebugActivity extends Activity implements OnClickListener {
469774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan    private static String TAG = "CalendarDebugActivity";
479774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan    private Button mConfirmButton;
489774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan    private Button mCancelButton;
499774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan    private Button mDeleteButton;
509774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan    private TextView mTextView;
519774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan
529774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan    private static final String OUT_FILE = "calendar.db.zip";
539774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan    private static final String MIME_TYPE = "application/zip";
549774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan
559774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan    protected void onCreate(Bundle savedInstanceState) {
569774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        // Be sure to call the super class.
579774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        super.onCreate(savedInstanceState);
589774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan
599774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        requestWindowFeature(Window.FEATURE_LEFT_ICON);
609774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan
619774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        setContentView(R.layout.dialog_activity);
629774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan
639774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON,
649774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                android.R.drawable.ic_dialog_alert);
659774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan
669774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        mConfirmButton = (Button) findViewById(R.id.confirm);
679774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        mCancelButton = (Button) findViewById(R.id.cancel);
689774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        mDeleteButton = (Button) findViewById(R.id.delete);
699774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        updateDeleteButton();
709774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan    }
719774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan
729774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan    private void updateDeleteButton() {
739774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        final boolean fileExist =
749774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan            new File(Environment.getExternalStorageDirectory(), OUT_FILE).exists();
759774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        mDeleteButton.setEnabled(fileExist);
769774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan    }
779774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan
789774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan    @Override
799774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan    public void onClick(View v) {
809774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        switch (v.getId()) {
819774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan            case R.id.confirm:
829774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                mConfirmButton.setEnabled(false);
839774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                mCancelButton.setEnabled(false);
849774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                new DumpDbTask().execute();
859774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                break;
869774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan            case R.id.delete:
879774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                cleanup();
889774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                updateDeleteButton();
899774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                break;
909774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan            case R.id.cancel:
919774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                finish();
929774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                break;
939774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        }
949774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan    }
959774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan
969774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan    private void cleanup() {
979774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        Log.i(TAG, "Deleting " + OUT_FILE);
989774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        File outFile = new File(Environment.getExternalStorageDirectory(), OUT_FILE);
999774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        outFile.delete();
1009774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan    }
1019774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan
1029774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan    private class DumpDbTask extends AsyncTask<Void, Void, File> {
1039774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan
1049774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        /**
1059774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan         * Starts spinner while task is running.
1069774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan         */
1079774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        @Override
1089774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        protected void onPreExecute() {
1099774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan            setProgressBarIndeterminateVisibility(true);
1109774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        }
1119774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan
1129774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        protected File doInBackground(Void... params) {
1139774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan            InputStream is = null;
1149774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan            ZipOutputStream os = null;
1159774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan
1169774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan            try {
1179774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                File path = Environment.getExternalStorageDirectory();
1189774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                File outFile = new File(path, OUT_FILE);
1199774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                outFile.delete();
1209774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                Log.i(TAG, "Outfile=" + outFile.getAbsolutePath());
1219774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan
1229774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                final File inFile = getDatabasePath("calendar.db");
1239774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                is = new FileInputStream(inFile);
1249774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan
1259774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                os = new ZipOutputStream(new FileOutputStream(outFile));
1269774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                os.putNextEntry(new ZipEntry(inFile.getName()));
1279774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan
1289774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                byte[] buf = new byte[4096];
1299774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                int totalLen = 0;
1309774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                while (true) {
1319774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                    int len = is.read(buf);
1329774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                    if (len <= 0) {
1339774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                        break;
1349774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                    }
1359774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                    os.write(buf, 0, len);
1369774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                    totalLen += len;
1379774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                }
1389774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                os.closeEntry();
1399774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan
1409774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                Log.i(TAG, "bytes read " + totalLen);
1419774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                os.flush();
1429774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                os.close();
1439774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                os = null;
1449774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan
1459774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                // Tell the media scanner about the new file so that it is
1469774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                // immediately available to the user.
1479774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                MediaScannerConnection.scanFile(CalendarDebugActivity.this, new String[] {
1489774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                    outFile.toString()
1499774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                }, new String[] {
1509774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                    MIME_TYPE
1519774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                }, null);
1529774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                return outFile;
1539774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan
1549774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan            } catch (IOException e) {
1559774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                Log.i(TAG, "Error " + e.toString());
1569774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan            } finally {
1579774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                try {
1589774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                    if (is != null) {
1599774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                        is.close();
1609774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                    }
1619774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                    if (os != null) {
1629774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                        os.close();
1639774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                    }
1649774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                } catch (IOException e) {
1659774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                    Log.i(TAG, "Error " + e.toString());
1669774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                }
1679774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan            }
1689774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan            return null;
1699774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        }
1709774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan
1719774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        /**
1729774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan         * Runs on the UI thread
1739774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan         */
1749774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        @Override
1759774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        protected void onPostExecute(File outFile) {
1769774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan            if (outFile != null) {
1779774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                emailFile(outFile);
1789774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan            }
1799774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        }
1809774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan    }
1819774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan
1829774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan    @Override
1839774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
1849774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        updateDeleteButton();
1859774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        mConfirmButton.setEnabled(true);
1869774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        mCancelButton.setEnabled(true);
1879774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan    }
1889774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan
1899774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan    private void emailFile(File file) {
1909774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        Log.i(TAG, "Drafting email to send " + file.getAbsolutePath());
1919774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        Intent intent = new Intent(Intent.ACTION_SEND);
1929774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        intent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.debug_tool_email_subject));
1939774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        intent.putExtra(Intent.EXTRA_TEXT, getString(R.string.debug_tool_email_body));
1949774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        intent.setType(MIME_TYPE);
1959774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
1969774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan        startActivityForResult(Intent.createChooser(intent,
1979774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan                getString(R.string.debug_tool_email_sender_picker)), 0);
1989774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan    }
1999774e10b9b34b6b0715f8d5e413f068d7e29cd26Michael Chan}
200