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