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() {
63 private Button mImportButton;
64 private Button mCancelButton;
65 private Spinner mCalendars;
66 private TextView mNumEvents;
68 private ICalendar.Component mCalendar = null;
70 private View.OnClickListener mImportListener = new View.OnClickListener() {
71 public void onClick(View v) {
77 private View.OnClickListener mCancelListener = new View.OnClickListener() {
78 public void onClick(View v) {
84 protected void onCreate(Bundle icicle) {
85 super.onCreate(icicle);
86 setContentView(R.layout.ics_import_activity);
88 mCalendars = (Spinner) findViewById(R.id.calendars);
91 mImportButton = (Button) findViewById(R.id.import_button);
92 mImportButton.setOnClickListener(mImportListener);
93 mCancelButton = (Button) findViewById(R.id.cancel_button);
94 mCancelButton.setOnClickListener(mCancelListener);
96 mNumEvents = (TextView) findViewById(R.id.num_events);
98 Intent intent = getIntent();
99 String data = intent.getStringExtra("ics");
101 Uri content = intent.getData();
102 if (content != null) {
103 InputStream is = null;
105 is = getContentResolver().openInputStream(content);
106 ByteArrayOutputStream baos = new ByteArrayOutputStream();
107 byte[] buf = new byte[8096];
110 while ((bytesRead = is.read(buf)) != -1) {
111 baos.write(buf, pos, bytesRead);
114 data = new String(baos.toByteArray(), "UTF-8");
115 } catch (FileNotFoundException fnfe) {
116 Log.w(TAG, "Could not open data.", fnfe);
117 } catch (IOException ioe) {
118 Log.w(TAG, "Could not read data.", ioe);
123 } catch (IOException ioe) {
124 Log.w(TAG, "Could not close InputStream.", ioe);
131 Log.w(TAG, "No iCalendar data to parse.");
138 private void populateCalendars() {
139 ContentResolver cr = getContentResolver();
140 Cursor c = cr.query(Calendar.Calendars.CONTENT_URI,
141 new String[] { Calendar.Calendars._ID,
142 Calendar.Calendars.DISPLAY_NAME,
143 Calendar.Calendars.SELECTED,
144 Calendar.Calendars.ACCESS_LEVEL },
145 Calendar.Calendars.SELECTED + "=1 AND "
146 + Calendar.Calendars.ACCESS_LEVEL + ">="
147 + Calendar.Calendars.CONTRIBUTOR_ACCESS,
148 null, null /* sort order */);
150 ArrayList<CalendarInfo> items = new ArrayList<CalendarInfo>();
152 // TODO: write a custom adapter that wraps the cursor?
153 int idColumn = c.getColumnIndex(Calendar.Calendars._ID);
154 int nameColumn = c.getColumnIndex(Calendar.Calendars.DISPLAY_NAME);
155 while (c.moveToNext()) {
156 long id = c.getLong(idColumn);
157 String name = c.getString(nameColumn);
158 items.add(new CalendarInfo(id, name));
164 mCalendars.setAdapter(new ArrayAdapter<CalendarInfo>(this,
165 android.R.layout.simple_spinner_item, items));
168 private void parseCalendar(String data) {
171 mCalendar = ICalendar.parseCalendar(data);
172 } catch (ICalendar.FormatException fe) {
174 Log.d(TAG, "Could not parse iCalendar.", fe);
175 // TODO: show an error message.
180 if (mCalendar.getComponents() == null) {
181 Log.d(TAG, "No events in iCalendar.");
186 for (ICalendar.Component component : mCalendar.getComponents()) {
187 if ("VEVENT".equals(component.getName())) {
188 // TODO: display a list of the events (start time, title) in
193 // TODO: special-case a single-event calendar. switch to the
194 // EventActivity, once the EventActivity supports displaying data that
195 // is passed in via the extras.
196 // OR, we could flip things around, where the EventActivity handles ICS
197 // import by default, and delegates to the IcsImportActivity if it finds
198 // that there are more than one event in the iCalendar. that would
199 // avoid an extra activity launch for the expected common case of
200 // importing a single event.
201 mNumEvents.setText(Integer.toString(numEvents));
204 private void importCalendar() {
206 ContentResolver cr = getContentResolver();
209 ContentValues values = new ContentValues();
211 for (ICalendar.Component component : mCalendar.getComponents()) {
212 if ("VEVENT".equals(component.getName())) {
213 CalendarInfo calInfo =
214 (CalendarInfo) mCalendars.getSelectedItem();
215 if (Calendar.Events.insertVEvent(cr, component, calInfo.id,
216 Calendar.Events.STATUS_CONFIRMED, values) != null) {
221 // TODO: display how many were imported.