Android Calendar, Invalid column display name

2019-07-21 20:55发布

问题:

Hi i need to implement a code for insert, update events on android calendar, When i was trying add Events on Android Calendar it throws exception - invalid column displayname. i try to replace deprecated , because apps crash:

Cursor l_managedCursor = this.managedQuery(l_eventUri, l_projection, "calendar_id=" + m_selectedCalendarId, null, "dtstart DESC, dtend DESC");

with this , but i received error by logcat "invalid column displayname"

Cursor l_managedCursor = getContentResolver().query (l_calendars, l_projection,null,null,null);

this is code

    @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    /*get calendar list and populate the view*/
    getCalendars();
    populateCalendarSpinner();
    populateAddBtn();
    populateAddBtn2();
    populateTextEvent();
    populateGetEventsBtn();
}
private void populateCalendarSpinner() {
    m_spinner_calender = (Spinner)this.findViewById(R.id.spinner_calendar);
    ArrayAdapter l_arrayAdapter = new ArrayAdapter(this.getApplicationContext(), android.R.layout.simple_spinner_item, m_calendars);
    l_arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    m_spinner_calender.setAdapter(l_arrayAdapter);
    m_spinner_calender.setSelection(0);
    m_spinner_calender.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> p_parent, View p_view,
                                   int p_pos, long p_id) {
            m_selectedCalendarId = m_calendars[(int)p_id].id;
        }
        @Override
        public void onNothingSelected(AdapterView<?> arg0) {}
    });
}
private void populateAddBtn() {
    m_button_add = (Button) this.findViewById(R.id.button_add);
    m_button_add.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            addEvent();
        }
    });
}
private void populateAddBtn2() {
    m_button_add2 = (Button) this.findViewById(R.id.button_add2);
    m_button_add2.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            addEvent2();
        }
    });
}
private void populateGetEventsBtn() {
    m_button_getEvents = (Button) findViewById(R.id.button_get_events);
    m_button_getEvents.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            getLastThreeEvents();
        }
    });
}
private void populateTextEvent() {
    m_text_event = (TextView) findViewById(R.id.text_event);
    String l_str = "title: roman10 calendar tutorial test\n" +
            "description: This is a simple test for calendar api\n" +
            "eventLocation: @home\n" +
            "start time:" + getDateTimeStr(0) + "\n" +
            "end time: " + getDateTimeStr(30) + "\n" +
            "event status: confirmed\n" +
            "all day: no\n" +
            "has alarm: yes\n";
    m_text_event.setText(l_str);
}
/****************************************************************
 * Data part
 */
/*retrieve a list of available calendars*/
private MyCalendar m_calendars[];
private String m_selectedCalendarId = "0";
private void getCalendars() {
    String[] l_projection = new String[]{"_id", "displayName"};
    Uri l_calendars;
    if (Build.VERSION.SDK_INT >= 8) {
        l_calendars = Uri.parse("content://com.android.calendar/calendars");
    } else {
        l_calendars = Uri.parse("content://calendar/calendars");
    }
   // Cursor l_managedCursor = this.managedQuery(l_calendars, l_projection, null, null, null);  //all calendars
    //Cursor l_managedCursor = this.managedQuery(l_calendars, l_projection, "selected=1", null, null);   //active calendars
    Cursor l_managedCursor = getContentResolver().query (l_calendars, l_projection, "selected=1", null, null);  //all calendars
    if (l_managedCursor.moveToFirst()) {
        m_calendars = new MyCalendar[l_managedCursor.getCount()];
        String l_calName;
        String l_calId;
        int l_cnt = 0;
        int l_nameCol = l_managedCursor.getColumnIndex(l_projection[1]);
        int l_idCol = l_managedCursor.getColumnIndex(l_projection[0]);
        do {
            l_calName = l_managedCursor.getString(l_nameCol);
            l_calId = l_managedCursor.getString(l_idCol);
            m_calendars[l_cnt] = new MyCalendar(l_calName, l_calId);
            ++l_cnt;
        } while (l_managedCursor.moveToNext());
    }
}
/*add an event to calendar*/
private void addEvent() {
    ContentValues l_event = new ContentValues();
    l_event.put("calendar_id", m_selectedCalendarId);
    l_event.put("title", "roman10 calendar tutorial test");
    l_event.put("description", "This is a simple test for calendar api");
    l_event.put("eventLocation", "@home");
    l_event.put("dtstart", System.currentTimeMillis());
    l_event.put("dtend", System.currentTimeMillis() + 1800*1000);
    l_event.put("allDay", 0);
    //status: 0~ tentative; 1~ confirmed; 2~ canceled
    l_event.put("eventStatus", 1);
    //0~ default; 1~ confidential; 2~ private; 3~ public
    l_event.put("visibility", 0);
    //0~ opaque, no timing conflict is allowed; 1~ transparency, allow overlap of scheduling
    l_event.put("transparency", 0);
    //0~ false; 1~ true
    l_event.put("hasAlarm", 1);
    Uri l_eventUri;
    if (Build.VERSION.SDK_INT >= 8) {
        l_eventUri = Uri.parse("content://com.android.calendar/events");
    } else {
        l_eventUri = Uri.parse("content://calendar/events");
    }
    Uri l_uri = this.getContentResolver().insert(l_eventUri, l_event);
    Log.v("++++++test", l_uri.toString());
}

private void addEvent2() {
    Intent l_intent = new Intent(Intent.ACTION_EDIT);
    l_intent.setType("vnd.android.cursor.item/event");
    //l_intent.putExtra("calendar_id", m_selectedCalendarId);  //this doesn't work
    l_intent.putExtra("title", "roman10 calendar tutorial test");
    l_intent.putExtra("description", "This is a simple test for calendar api");
    l_intent.putExtra("eventLocation", "@home");
    l_intent.putExtra("beginTime", System.currentTimeMillis());
    l_intent.putExtra("endTime", System.currentTimeMillis() + 1800*1000);
    l_intent.putExtra("allDay", 0);
    //status: 0~ tentative; 1~ confirmed; 2~ canceled
    l_intent.putExtra("eventStatus", 1);
    //0~ default; 1~ confidential; 2~ private; 3~ public
    l_intent.putExtra("visibility", 0);
    //0~ opaque, no timing conflict is allowed; 1~ transparency, allow overlap of scheduling
    l_intent.putExtra("transparency", 0);
    //0~ false; 1~ true
    l_intent.putExtra("hasAlarm", 1);
    try {
        startActivity(l_intent);
    } catch (Exception e) {
        Toast.makeText(this.getApplicationContext(), "Sorry, no compatible calendar is found!", Toast.LENGTH_LONG).show();
    }
}

private void getLastThreeEvents() {
    Uri l_eventUri;
    if (Build.VERSION.SDK_INT >= 8) {
        l_eventUri = Uri.parse("content://com.android.calendar/events");
    } else {
        l_eventUri = Uri.parse("content://calendar/events");
    }
    String[] l_projection = new String[]{"title", "dtstart", "dtend"};
    //Cursor l_managedCursor = this.managedQuery(l_eventUri, l_projection, "calendar_id=" + m_selectedCalendarId, null, "dtstart DESC, dtend DESC");
   //Cursor l_managedCursor = this.managedQuery(l_eventUri, l_projection, null, null, null);
    Cursor l_managedCursor = this.getContentResolver().query(l_eventUri, l_projection, "calendar_id=" + m_selectedCalendarId, null, "dtstart DESC, dtend DESC");
    if (l_managedCursor.moveToFirst()) {
        int l_cnt = 0;
        String l_title;
        String l_begin;
        String l_end;
        StringBuilder l_displayText = new StringBuilder();
        int l_colTitle = l_managedCursor.getColumnIndex(l_projection[0]);
        int l_colBegin = l_managedCursor.getColumnIndex(l_projection[1]);
        int l_colEnd = l_managedCursor.getColumnIndex(l_projection[1]);
        do {
            l_title = l_managedCursor.getString(l_colTitle);
            l_begin = getDateTimeStr(l_managedCursor.getString(l_colBegin));
            l_end = getDateTimeStr(l_managedCursor.getString(l_colEnd));
            l_displayText.append(l_title + "\n" + l_begin + "\n" + l_end + "\n----------------\n");
            ++l_cnt;
        } while (l_managedCursor.moveToNext() && l_cnt < 3);
        m_text_event.setText(l_displayText.toString());
    }
}
/************************************************
 * utility part
 */
private static final String DATE_TIME_FORMAT = "yyyy MMM dd, HH:mm:ss";

public static String getDateTimeStr(int p_delay_min) {
    Calendar cal = Calendar.getInstance();
    SimpleDateFormat sdf = new SimpleDateFormat(DATE_TIME_FORMAT);
    if (p_delay_min == 0) {
        return sdf.format(cal.getTime());
    } else {
        Date l_time = cal.getTime();
        //l_time.getMinutes (l_time.getMinutes() + p_delay_min);

        return sdf.format(l_time);
    }
}
public static String getDateTimeStr(String p_time_in_millis) {
    SimpleDateFormat sdf = new SimpleDateFormat(DATE_TIME_FORMAT);
    Date l_time = new Date(Long.parseLong(p_time_in_millis));
    return sdf.format(l_time);
}

}

LOGCAT

01-05 17:09:26.690    2354-2354/app.android.ny E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: app.android.ny, PID: 2354
java.lang.RuntimeException: Unable to start activity ComponentInfo{app.android.ny/app.android.ny.Main}: java.lang.IllegalArgumentException: Invalid column displayName
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2298)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
        at android.app.ActivityThread.access$800(ActivityThread.java:144)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5221)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
 Caused by: java.lang.IllegalArgumentException: Invalid column displayName
        at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:167)
        at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:137)
        at android.content.ContentProviderProxy.query(ContentProviderNative.java:420)
        at android.content.ContentResolver.query(ContentResolver.java:478)
        at android.content.ContentResolver.query(ContentResolver.java:422)
        at app.android.ny.Main.getCalendars(Main.java:136)
        at app.android.ny.Main.onCreate(Main.java:58)
        at android.app.Activity.performCreate(Activity.java:5933)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251)

                        

回答1:

I Think there is a change in the way you query the calendars for newer API. They didn't seem to inform about it.

For API 10 I know displayName works.

For API >= 14 this code will work:

https://developer.android.com/guide/topics/providers/calendar-provider.html

// Projection array. Creating indices for this array instead of doing
// dynamic lookups improves performance.
public static final String[] EVENT_PROJECTION = new String[] {
Calendars._ID,                           // 0
Calendars.ACCOUNT_NAME,                  // 1
Calendars.CALENDAR_DISPLAY_NAME,         // 2
Calendars.OWNER_ACCOUNT                  // 3
};


// Run query
Cursor cur = null;
ContentResolver cr = getContentResolver();
Uri uri = Calendars.CONTENT_URI;
String selection = "((" + Calendars.ACCOUNT_NAME + " = ?) AND ("
                    + Calendars.ACCOUNT_TYPE + " = ?) AND ("
                    + Calendars.OWNER_ACCOUNT + " = ?))";
String[] selectionArgs = new String[] {"sampleuser@gmail.com", "com.google",
    "sampleuser@gmail.com"};
// Submit the query and get a Cursor object back.
cur = cr.query(uri, EVENT_PROJECTION, selection, selectionArgs, null);


回答2:

Your app is crashing because the column name you are passing to get calender info is wrong. Change this line

String[] l_projection = new String[]{"_id", "displayName"};

in method getCalendars() to

String[] l_projection = new String[]{"_id", "calendar_displayName"};


回答3:

You must have entered a different Column name. Kindly check the Upper case and lower case !!



回答4:

Even I was facing this error, finaly got it done by this piece of code, hope this will help many

new String[] { "_id", Calendars.CALENDAR_DISPLAY_NAME }