2 * Copyright (C) 2007 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.calendar;
19 import android.app.Activity;
20 import android.content.ContentResolver;
21 import android.content.ContentValues;
22 import android.content.Intent;
23 import android.database.Cursor;
24 import android.net.Uri;
25 import android.os.Bundle;
26 import android.pim.ICalendar;
27 import android.provider.Calendar;
28 import android.util.Config;
29 import android.util.Log;
30 import android.view.View;
31 import android.widget.ArrayAdapter;
32 import android.widget.Button;
33 import android.widget.ImageView;
34 import android.widget.Spinner;
35 import android.widget.TextView;
37 import java.io.ByteArrayOutputStream;
38 import java.io.FileNotFoundException;
39 import java.io.IOException;
40 import java.io.InputStream;
41 import java.util.ArrayList;
43 public class IcsImportActivity extends Activity {
45 private static final String TAG = "Calendar";
47 // TODO: consolidate this code with the EventActivity
48 private static class CalendarInfo {
50 public final String name;
52 public CalendarInfo(long id, String name) {
58 public String toString() {
64 private Button mImportButton;
65 private Button mCancelButton;
66 private Spinner mCalendars;
67 private ImageView mCalendarIcon;
68 private TextView mNumEvents;
70 private ICalendar.Component mCalendar = null;
72 private View.OnClickListener mImportListener = new View.OnClickListener() {
73 public void onClick(View v) {
79 private View.OnClickListener mCancelListener = new View.OnClickListener() {
80 public void onClick(View v) {
86 protected void onCreate(Bundle icicle) {
87 super.onCreate(icicle);
88 setContentView(R.layout.ics_import_activity);
89 mView = findViewById(R.id.import_ics);
91 mCalendarIcon = (ImageView) findViewById(R.id.calendar_icon);
92 mCalendars = (Spinner) findViewById(R.id.calendars);
95 mImportButton = (Button) findViewById(R.id.import_button);
96 mImportButton.setOnClickListener(mImportListener);
97 mCancelButton = (Button) findViewById(R.id.cancel_button);
98 mCancelButton.setOnClickListener(mCancelListener);
100 mNumEvents = (TextView) findViewById(R.id.num_events);
102 Intent intent = getIntent();
103 String data = intent.getStringExtra("ics");
105 Uri content = intent.getData();
106 if (content != null) {
107 InputStream is = null;
109 is = getContentResolver().openInputStream(content);
110 ByteArrayOutputStream baos = new ByteArrayOutputStream();
111 byte[] buf = new byte[8096];
114 while ((bytesRead = is.read(buf)) != -1) {
115 baos.write(buf, pos, bytesRead);
118 data = new String(baos.toByteArray(), "UTF-8");
119 } catch (FileNotFoundException fnfe) {
120 Log.w(TAG, "Could not open data.", fnfe);
121 } catch (IOException ioe) {
122 Log.w(TAG, "Could not read data.", ioe);
127 } catch (IOException ioe) {
128 Log.w(TAG, "Could not close InputStream.", ioe);
135 Log.w(TAG, "No iCalendar data to parse.");
142 private void populateCalendars() {
143 ContentResolver cr = getContentResolver();
144 Cursor c = cr.query(Calendar.Calendars.CONTENT_URI,
145 new String[] { Calendar.Calendars._ID,
146 Calendar.Calendars.DISPLAY_NAME,
147 Calendar.Calendars.SELECTED,
148 Calendar.Calendars.ACCESS_LEVEL },
149 Calendar.Calendars.SELECTED + "=1 AND "
150 + Calendar.Calendars.ACCESS_LEVEL + ">="
151 + Calendar.Calendars.CONTRIBUTOR_ACCESS,
152 null, null /* sort order */);
154 ArrayList<CalendarInfo> items = new ArrayList<CalendarInfo>();
156 // TODO: write a custom adapter that wraps the cursor?
157 int idColumn = c.getColumnIndex(Calendar.Calendars._ID);
158 int nameColumn = c.getColumnIndex(Calendar.Calendars.DISPLAY_NAME);
159 while (c.moveToNext()) {
160 long id = c.getLong(idColumn);
161 String name = c.getString(nameColumn);
162 items.add(new CalendarInfo(id, name));
168 mCalendars.setAdapter(new ArrayAdapter<CalendarInfo>(this,
169 android.R.layout.simple_spinner_item, items));
172 private void parseCalendar(String data) {
175 mCalendar = ICalendar.parseCalendar(data);
176 } catch (ICalendar.FormatException fe) {
178 Log.d(TAG, "Could not parse iCalendar.", fe);
179 // TODO: show an error message.
184 if (mCalendar.getComponents() == null) {
185 Log.d(TAG, "No events in iCalendar.");
190 for (ICalendar.Component component : mCalendar.getComponents()) {
191 if ("VEVENT".equals(component.getName())) {
192 // TODO: display a list of the events (start time, title) in
197 // TODO: special-case a single-event calendar. switch to the
198 // EventActivity, once the EventActivity supports displaying data that
199 // is passed in via the extras.
200 // OR, we could flip things around, where the EventActivity handles ICS
201 // import by default, and delegates to the IcsImportActivity if it finds
202 // that there are more than one event in the iCalendar. that would
203 // avoid an extra activity launch for the expected common case of
204 // importing a single event.
205 mNumEvents.setText(Integer.toString(numEvents));
208 private void importCalendar() {
210 ContentResolver cr = getContentResolver();
213 ContentValues values = new ContentValues();
215 for (ICalendar.Component component : mCalendar.getComponents()) {
216 if ("VEVENT".equals(component.getName())) {
217 CalendarInfo calInfo =
218 (CalendarInfo) mCalendars.getSelectedItem();
219 if (Calendar.Events.insertVEvent(cr, component, calInfo.id,
220 Calendar.Events.STATUS_CONFIRMED, values) != null) {
225 // TODO: display how many were imported.