10
votes

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!

2
Could you please provide info. about implementation of how you provided an option to return to app from Calendar ?Android_programmer_office
Hi Woestman ! Could you please provide us information about your implementation mechanism for return to the app from Calendar to view more information about it.Android_programmer_office

2 Answers

12
votes

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.

4
votes

The first option you listed works fine on my Nexus S. I just tried it right now to make sure it was working coming from the default Google Calendar app.

In my case, I'm not intercepting myapp://event/1000, I'm intercepting an actual url more like https://myspecialdomain.com/blahblah. The browser starts to load, but before it has the time to load anything, it gets swapped out by my application.

I can show you my code tomorrow if you want.