Existe uma maneira de acessar entradas do calendário sem usar gdata-java-client?

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

  •  21-08-2019
  •  | 
  •  

Pergunta

É possível obter entradas do calendário a partir do telefone offline? Ele parece a única maneira é usar gdata-java-client .

Foi útil?

Solução

Estas respostas são boas, mas todas elas envolvem embutir o Calendar URI (que eu já vi em três encarnações diferentes em diferentes dispositivos Android).

A melhor maneira de conseguir que URI (que rígidos códigos o nome de uma classe e um campo em vez) seria algo como isto:

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

Este não é perfeito (ele vai quebrar se eles nunca remover a classe android.provider.Calendar ou o campo CONTENT_URI) mas funciona em mais plataformas do que qualquer codificar URI único.

Note que estes métodos reflexão vai jogar exceptions que terão de ser preso ou re-lançada pelo método de chamada.

Outras dicas

Josef e soluções de Isaac para acessar o calendário único trabalho em Android 2.1 e anteriores. Google mudaram o conteúdo URI base em 2,2 a partir de "conteúdo: // calendário" para "conteúdo: //com.android.calendar". Esta mudança significa que a melhor abordagem é tentar obter um cursor usando a antiga base URI, e se o cursor retornado é nulo, em seguida, tentar a nova base URI.

Por favor note que eu tenho essa abordagem a partir da open source código de teste que Shane Conder e Lauren Darcey fornecer com sua trabalhar com o Calendário Android artigo.

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
}

Atualmente, isso não é possível sem o uso de APIs privadas (ver post de Josef.) Há um provedor de calendário, mas não é pública ainda. Ele poderia mudar a qualquer momento e quebrar seu aplicativo.
No entanto, ele provavelmente não vai mudar (eu não acho que eles vão mudá-lo de "calendário"), de modo que você pode ser capaz de usá-lo. Mas a minha recomendação é usar uma classe separada assim:

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

E usar aqueles em vez das cordas diretamente. Isso permitirá que você alterá-lo muito facilmente se / quando as mudanças na API ou torna-se público.

Você pode usar o provedor de conteúdo de calendário (com.android.providers.calendar.CalendarProvider). Exemplo:


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.
}

Editar : você pode querer colocar isso em um invólucro (ver o Isaac pós ) como é actualmente uma API privada.

Você pode usar o CalendarContract a partir daqui: https://github.com/dschuermann/android- calendário de compatibilidade de

É a mesma classe API como disponível no Android 4, mas feito para trabalhar com Android> = 2.2.

Sobre o API que pode mudar ... A abordagem ContentProvider toda não vai mudar isso rapidamente, para já pode superar uma série de problemas em apenas atualizando as cordas. Mesmos criar constantes que você reutilizar ao longo de todo o projeto.

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 você quer uma API privada adequado, você terá que criar um pojo e alguns serviços como este:

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 assim por diante. Desta forma, você só tem que atualizar o objeto CalendarEvent e este serviço no caso das mudanças na API.

A solução de Nick envolve managedQuery, que não é definido na classe de contexto. Muitas vezes, quando você está executando as coisas no fundo que você iria querer usar um objeto de contexto. Aqui está uma versão modificada:

getCalendarUriBase public String () {

retorno (android.os.Build.VERSION.SDK_INT> = 8)? "Conteúdo: //com.android.calendar": "Conteúdo: // calendário"; }

A captura for null não deve ser realizado aqui desde pode haver mais excepções, mesmo que o managedQuery conseguiram antes.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top