blob: c4f5fdea42f9a41864ad3c7ab268a55cec6ef1d2 [file] [log] [blame]
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.calendar;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.pim.ICalendar;
import android.provider.Calendar;
import android.util.Config;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
public class IcsImportActivity extends Activity {
private static final String TAG = "Calendar";
// TODO: consolidate this code with the EventActivity
private static class CalendarInfo {
public final long id;
public final String name;
public CalendarInfo(long id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return name;
}
}
private View mView;
private Button mImportButton;
private Button mCancelButton;
private Spinner mCalendars;
private ImageView mCalendarIcon;
private TextView mNumEvents;
private ICalendar.Component mCalendar = null;
private View.OnClickListener mImportListener = new View.OnClickListener() {
public void onClick(View v) {
importCalendar();
finish();
}
};
private View.OnClickListener mCancelListener = new View.OnClickListener() {
public void onClick(View v) {
finish();
}
};
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.ics_import_activity);
mView = findViewById(R.id.import_ics);
mCalendarIcon = (ImageView) findViewById(R.id.calendar_icon);
mCalendars = (Spinner) findViewById(R.id.calendars);
populateCalendars();
mImportButton = (Button) findViewById(R.id.import_button);
mImportButton.setOnClickListener(mImportListener);
mCancelButton = (Button) findViewById(R.id.cancel_button);
mCancelButton.setOnClickListener(mCancelListener);
mNumEvents = (TextView) findViewById(R.id.num_events);
Intent intent = getIntent();
String data = intent.getStringExtra("ics");
if (data == null) {
Uri content = intent.getData();
if (content != null) {
InputStream is = null;
try {
is = getContentResolver().openInputStream(content);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[8096];
int bytesRead = -1;
int pos = 0;
while ((bytesRead = is.read(buf)) != -1) {
baos.write(buf, pos, bytesRead);
pos += bytesRead;
}
data = new String(baos.toByteArray(), "UTF-8");
} catch (FileNotFoundException fnfe) {
Log.w(TAG, "Could not open data.", fnfe);
} catch (IOException ioe) {
Log.w(TAG, "Could not read data.", ioe);
} finally {
if (is != null) {
try {
is.close();
} catch (IOException ioe) {
Log.w(TAG, "Could not close InputStream.", ioe);
}
}
}
}
}
if (data == null) {
Log.w(TAG, "No iCalendar data to parse.");
finish();
return;
}
parseCalendar(data);
}
private void populateCalendars() {
ContentResolver cr = getContentResolver();
Cursor c = cr.query(Calendar.Calendars.CONTENT_URI,
new String[] { Calendar.Calendars._ID,
Calendar.Calendars.DISPLAY_NAME,
Calendar.Calendars.SELECTED,
Calendar.Calendars.ACCESS_LEVEL },
Calendar.Calendars.SELECTED + "=1 AND "
+ Calendar.Calendars.ACCESS_LEVEL + ">="
+ Calendar.Calendars.CONTRIBUTOR_ACCESS,
null, null /* sort order */);
ArrayList<CalendarInfo> items = new ArrayList<CalendarInfo>();
try {
// TODO: write a custom adapter that wraps the cursor?
int idColumn = c.getColumnIndex(Calendar.Calendars._ID);
int nameColumn = c.getColumnIndex(Calendar.Calendars.DISPLAY_NAME);
while (c.moveToNext()) {
long id = c.getLong(idColumn);
String name = c.getString(nameColumn);
items.add(new CalendarInfo(id, name));
}
} finally {
c.deactivate();
}
mCalendars.setAdapter(new ArrayAdapter<CalendarInfo>(this,
android.R.layout.simple_spinner_item, items));
}
private void parseCalendar(String data) {
mCalendar = null;
try {
mCalendar = ICalendar.parseCalendar(data);
} catch (ICalendar.FormatException fe) {
if (Config.LOGD) {
Log.d(TAG, "Could not parse iCalendar.", fe);
// TODO: show an error message.
finish();
return;
}
}
if (mCalendar.getComponents() == null) {
Log.d(TAG, "No events in iCalendar.");
finish();
return;
}
int numEvents = 0;
for (ICalendar.Component component : mCalendar.getComponents()) {
if ("VEVENT".equals(component.getName())) {
// TODO: display a list of the events (start time, title) in
// the UI?
++numEvents;
}
}
// TODO: special-case a single-event calendar. switch to the
// EventActivity, once the EventActivity supports displaying data that
// is passed in via the extras.
// OR, we could flip things around, where the EventActivity handles ICS
// import by default, and delegates to the IcsImportActivity if it finds
// that there are more than one event in the iCalendar. that would
// avoid an extra activity launch for the expected common case of
// importing a single event.
mNumEvents.setText(Integer.toString(numEvents));
}
private void importCalendar() {
ContentResolver cr = getContentResolver();
int numImported = 0;
ContentValues values = new ContentValues();
for (ICalendar.Component component : mCalendar.getComponents()) {
if ("VEVENT".equals(component.getName())) {
CalendarInfo calInfo =
(CalendarInfo) mCalendars.getSelectedItem();
if (Calendar.Events.insertVEvent(cr, component, calInfo.id,
Calendar.Events.STATUS_CONFIRMED, values) != null) {
++numImported;
}
}
}
// TODO: display how many were imported.
}
}