C'è un modo per accedere alle voci del calendario senza utilizzare GData-java-client?

StackOverflow https://stackoverflow.com/questions/846942

  •  21-08-2019
  •  | 
  •  

Domanda

E 'possibile ottenere le voci del calendario dalla linea telefonica? Esso sembra l'unico modo è quello di utilizzare GData-java-client .

È stato utile?

Soluzione

Queste risposte sono buone, ma tutti implicano hard-codifica la Calendar URI (che ho visto in tre diverse incarnazioni attraverso diversi dispositivi Android).

Un modo migliore per ottenere che URI (che hard-codifica il nome di una classe e di un campo al posto) sarebbe qualcosa di simile:

Class<?> calendarProviderClass = Class.forName("android.provider.Calendar");
Field uriField = calendarProviderClass.getField("CONTENT_URI");
Uri calendarUri = (Uri) uriField.get(null);

Questa non è perfetto (si romperà se mai rimuovere il android.provider.Calendar classe o la CONTENT_URI campo) ma funziona su più piattaforme di qualsiasi singolo URI hard-code.

Si noti che questi metodi di riflessione getteranno exceptions che dovrà essere catturati o ri-generata dal metodo chiamante.

Altri suggerimenti

Josef e le soluzioni di Isacco per l'accesso al calendario funzionano solo in Android 2.1 e versioni precedenti. Google hanno cambiato il contenuto URI di base a 2.2 dal "contenuto: // calendario" a "contenuti: //com.android.calendar". Questo cambiamento implica l'approccio migliore è quello di tentare di ottenere un cursore con il vecchio URI di base, e se il cursore restituito è nullo, quindi provare il nuovo URI di base.

Si prega di notare che ho avuto questo approccio dal aperta codice di prova fonte che Shane Conder e Lauren Darcey fornire con la loro di lavoro con il calendario Android articolo.

private final static String BASE_CALENDAR_URI_PRE_2_2 = "content://calendar";
private final static String BASE_CALENDAR_URI_2_2 = "content://com.android.calendar";
/*
 * Determines if we need to use a pre 2.2 calendar Uri, or a 2.2 calendar Uri, and returns the base Uri
 */
private String getCalendarUriBase() {
    Uri calendars = Uri.parse(BASE_CALENDAR_URI_PRE_2_2 + "/calendars");
    try {
        Cursor managedCursor = managedQuery(calendars, null, null, null, null);
        if (managedCursor != null) {
            return BASE_CALENDAR_URI_PRE_2_2;
        }
        else {
            calendars = Uri.parse(BASE_CALENDAR_URI_2_2 + "/calendars");
            managedCursor = managedQuery(calendars, null, null, null, null);

            if (managedCursor != null) {
                return BASE_CALENDAR_URI_2_2;
            }
        }
    } catch (Exception e) { /* eat any exceptions */ }

    return null; // No working calendar URI found
}

Al momento, questo non è possibile senza l'utilizzo di API private (vedi post di Josef.) C'è un fornitore di calendario, ma non è ancora pubblico. Potrebbe cambiare in qualsiasi momento e rompere la vostra applicazione.
Anche se, probabilmente non cambierà (non credo che cambierà da "calendario"), cui si potrebbe essere in grado di usarlo. Ma la mia raccomandazione è di usare una classe separata in questo modo:

public class CalendarProvider {
     public static final Uri CONTENT_URI = Uri.parse("content://calendar");
     public static final String TITLE = "title";
     public static final String ....

E utilizzare quelli invece delle corde direttamente. Questo vi permetterà di cambiare molto facilmente se / quando cambia API o che sia reso pubblico.

È possibile utilizzare il provider di contenuti del calendario (com.android.providers.calendar.CalendarProvider). Esempio:


ContentResolver contentResolver = context.getContentResolver();
Cursor cursor = contentResolver.query(Uri.parse("content://calendar/events"), null, null, null, null);

while(cursor.moveToNext()) {
    String eventTitle = cursor.getString(cursor.getColumnIndex("title"));
    Date eventStart = new Date(cursor.getLong(cursor.getColumnIndex("dtstart")));
    // etc.
}

modifica : si potrebbe desiderare di mettere questo in un involucro (vedi posta di Isacco) in quanto è attualmente un'API privato.

È possibile utilizzare l'CalendarContract da qui: https://github.com/dschuermann/android- calendar-compatibilità

E 'la stessa classe di API come disponibile su Android 4, ma ha fatto di lavorare con Android> = 2.2.

A proposito l'API che può cambiare ... L'approccio intero ContentProvider non cambierà rapidamente che così può già superato un sacco di problemi da solo aggiornando le corde. Perciò creare costanti si riutilizza per l'intero progetto.

public static final String URI_CONTENT_CALENDAR_EVENTS = "content://calendar/events";

ContentResolver contentResolver = context.getContentResolver();
Cursor cursor = contentResolver.query(Uri.parse(URI_CONTENT_CALENDAR_EVENTS), null, null, null, null);
    //etc

Se si vuole una vera e propria API privato dovrete creare un POJO e alcuni servizi in questo modo:

public class CalendarEvent {
    private long id;
    private long date;
    //etc...
}

public interface CalendarService {

    public Set<CalendarEvent> getAllCalendarEvents();

    public CalendarEvent findCalendarEventById(long id);

    public CalendarEvent findCalendarEventByDate(long date);

}

e così via. In questo modo si avrà solo per aggiornare l'oggetto CalendarEvent e questo servizio nel caso in cui i cambiamenti API.

La soluzione di Nick coinvolge managedQuery, che non è definito nella classe Context. Molte volte quando si esegue le cose in background che si vorrebbe utilizzare un oggetto contesto. Ecco una versione modificata:

public String getCalendarUriBase () {

ritorno (android.os.Build.VERSION.SDK_INT> = 8)? "Contenuti: //com.android.calendar": "Tenore: // calendario"; }

La cattura per nulla non deve essere effettuato qui da quando ci potrebbe essere più eccezioni, anche se il managedQuery è riuscito in precedenza.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top