Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Opening Android App from Calendar

The app I'm working on needs to be able to create events in a chosen Calendar and then when the user views these events in their calendar viewing app it offers an option to return to the my app to view more information about it and the data related to it.

Using Calendar Provider I'm able to create the events and I store the Uri to the event for later use/removal but I haven't found a good way to open my app from these events in a calendar viewing app.

The 2 options that I have considered are to include a custom URL in the event description that when clicked will be caught by an intent filter in my app (e.g. myapp://event/1000) or I could set the CUSTOM_APP_PACKAGE and CUSTOM_APP_URI values from CalendarContract when creating the event.

My problem with the first option is that I don't think I can guarantee that the calendar viewing app will correctly treat my custom URL as a link and let the user click on it (didn't work in Google calendar on my tablet). The 2nd option looks more promising but I haven't been able to find much documentation explaining how to use it.

Does anyone know how to properly do this? Any help is appreciated!

like image 797
woestman Avatar asked Apr 10 '13 07:04

woestman


1 Answers

If targeting Jelly Bean (API 16+) is acceptable then using CUSTOM_APP_PACKAGE is the best solution. When adding the new calendar event, you just need to fill the CUSTOM_APP_PACKAGE and CUSTOM_APP_URI fields (with your package name and an URI identifying the event respectively):

ContentValues values = new ContentValues();
values.put(CalendarContract.Events.CALENDAR_ID, 1);
values.put(CalendarContract.Events.TITLE, "Check stackoverflow.com");
values.put(CalendarContract.Events.DTSTART, beginTime.getTimeInMillis());
values.put(CalendarContract.Events.DTEND, endTime.getTimeInMillis());
values.put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().getID());

values.put(CalendarContract.Events.CUSTOM_APP_PACKAGE, getPackageName());
values.put(CalendarContract.Events.CUSTOM_APP_URI, "myAppointment://1");

getContentResolver().insert(CalendarContract.Events.CONTENT_URI, values);       

Then you need to specify as part of AndroidManifest.xml (as the documentation explains) the Activity that will be called from the Calendar app to show the detailed view, e.g.

    <activity android:name=".ShowCalendarDetailActivity">
        <intent-filter>
            <action android:name="android.provider.calendar.action.HANDLE_CUSTOM_EVENT" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:mimeType="vnd.android.cursor.item/event" />
        </intent-filter>            
    </activity>

ShowCalendarDetailActivity will be started when tapping on the button that appears, and will be passed an Intent with action "android.provider.calendar.action.HANDLE_CUSTOM_EVENT" and its URI will be the calendar item URI.

The custom URI you supplied is in the extras, with key CalendarContract.EXTRA_CUSTOM_APP_URI.

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    String myCustomUri = getIntent().getStringExtra(CalendarContract.EXTRA_CUSTOM_APP_URI);

    ...
}

If you want to take a look at the code where the Calendar app builds this intent, see EventInfoFragment.updateCustomAppButton() in EventInfoFragment.java.

like image 195
matiash Avatar answered Oct 28 '22 15:10

matiash