Google 日历 API 和警报管理器错误
Google Calendar API & Alarm Manager Error
我使用此代码从 Google 日历 API 中获得了 1 小时的免费时段。
MainActivity.java:
private List<String> getDataFromApi() throws IOException {
LocalDateTime now = LocalDateTime.now();
int year = now.getYear();
int month = now.getMonthOfYear();
int day = now.getDayOfMonth();
org.joda.time.DateTime startDateJoda= new org.joda.time.DateTime(year,month,day,7,00);
org.joda.time.DateTime endDateJoda= new org.joda.time.DateTime(year,month,day,22,00);
// Convert from Joda-Time to old bundled j.u.Date
java.util.Date juDateStart = startDateJoda.toDate();
java.util.Date juDateEnd = endDateJoda.toDate();
Log.v(TAG,"Start Date joda value: "+juDateStart.toString());
Log.v(TAG,"End Date joda value: "+juDateEnd.toString());
// Convert from j.u.Date to Google Date.
com.google.api.client.util.DateTime googleDateTimeStart = new com.google.api.client.util.DateTime( juDateStart );
com.google.api.client.util.DateTime googleDateTimeEnd = new com.google.api.client.util.DateTime( juDateEnd );
Log.v(TAG,"Start Date Google value: "+googleDateTimeStart.toString());
Log.v(TAG,"End Date Google value: "+googleDateTimeEnd.toString());
List<String> eventStrings = new ArrayList<String>();
org.joda.time.DateTime rootStart = startDateJoda;
org.joda.time.DateTime rootEnd = endDateJoda;
Events events = mService.events().list("primary")
.setMaxResults(10)
.setTimeMin(googleDateTimeStart)
.setTimeMax(googleDateTimeEnd)
.setOrderBy("startTime")
.setSingleEvents(true)
.execute();
List<Event> items = events.getItems();
Log.v(TAG,"Items : "+items.toString()+"\n");
Log.v(TAG,"Items size : "+items.size());
int interval = 1 ; // how big single slot should be (in this case 1 hrs)
ArrayList<MyEvent> freeSlots = new ArrayList<MyEvent>();
for (int index =0;index<items.size();index++) {
Event event = items.get(index);
Log.v(TAG,"Items Index: "+event.toString()+"\n");
DateTime teststart=event.getStart().getDateTime();
DateTime testend=event.getEnd().getDateTime();
Log.v(TAG,"Test Start Date value: "+teststart.toString());
Log.v(TAG,"Test End Date value: "+testend.toString());
long milliseconds1 = teststart.getValue();
long milliseconds2 = testend.getValue();
org.joda.time.DateTime eventStartJoda= new org.joda.time.DateTime(milliseconds1);
org.joda.time.DateTime eventEndJoda= new org.joda.time.DateTime(milliseconds2);
Log.v(TAG,"Event Start Date joda value: "+eventStartJoda.toString());
Log.v(TAG,"Event Date joda value: "+eventEndJoda.toString());
Log.v(TAG,"Before if index == 0 && start<end");
if ((index == 0) && (startDateJoda.isBefore(eventStartJoda)) ) {
Log.v(TAG,"Before Inside if index == 0 && start<end");
freeSlots.add( new MyEvent(startDateJoda,eventEndJoda) );
Log.v(TAG,"After Inside if index == 0 && start<end");
}
if (index == 0) {
Log.v(TAG,"Before else if index == 0");
DateTime teststart2=event.getEnd().getDateTime();
long milliseconds3 = teststart2.getValue();
startDateJoda=new org.joda.time.DateTime(milliseconds3);
Log.v(TAG,"startDateJoda value: "+startDateJoda.toString());
}
long milliseconds5=0;
Log.v(TAG,"Before teststart4");
if(index!=0) {
DateTime teststart4 = items.get(index - 1).getEnd().getDateTime();
Log.v(TAG, "After teststart4");
milliseconds5 = teststart4.getValue();
Log.v(TAG, "Before if milliseconds5");
}
if (new org.joda.time.DateTime(milliseconds5).isBefore(eventStartJoda)) {
if(index!=0) {
freeSlots.add(new MyEvent
(new org.joda.time.DateTime(milliseconds5), eventStartJoda));
Log.v(TAG,"xxxxxxx1 value: "+ new org.joda.time.DateTime(milliseconds5).toString());
}
}
DateTime teststart3=event.getEnd().getDateTime();
long milliseconds4 = teststart3.getValue();
if ((items.size() == (index + 1)) && new org.joda.time.DateTime(milliseconds4).isBefore(endDateJoda)) {
freeSlots.add(new MyEvent(eventEndJoda, endDateJoda));
Log.v(TAG,"xxxxxxx2 value: "+ new org.joda.time.DateTime(milliseconds4).toString());
}
}
Log.v(TAG,"Before outside items size == 0 ");
if (items.size() == 0) {
Log.v(TAG,"Before Inside items size == 0 ");
freeSlots.add(new MyEvent(startDateJoda,endDateJoda));
Log.v(TAG,"After Inside items size == 0 ");
}
Log.v(TAG,"After outside items size == 0 ");
ArrayList<MyEvent> hourSlots = new ArrayList<MyEvent>();
org.joda.time.DateTime tempstart= null;
org.joda.time.DateTime tempend= null;
MyEvent temp = new MyEvent();
int val=0;
for(int index =0;index<freeSlots.size();index++){
MyEvent free = (MyEvent) freeSlots.get(index);
Log.v(TAG,"Free slot size : "+freeSlots.size());
int freeHours = free.endDate.getHourOfDay()- free.startDate.getHourOfDay();
Log.v(TAG,"FreeHours: "+freeHours);
org.joda.time.DateTime freeStart = free.startDate, freeEnd = free.endDate;
Log.v(TAG,"Free Start Date: "+free.startDate.toString()+"Free End Date: "+free.endDate.toString());
Log.v(TAG,"Before eventStrings: "+free.startDate.toString()+" : "+free.endDate.toString());
while(freeStart.getHourOfDay() + freeHours + interval>=0) { if(freeHours>=interval) {
Log.v(TAG,"free startDate : "+free.startDate);
tempend=free.startDate;
Log.v(TAG,"Temp startDate : "+tempend);
tempend= tempend.hourOfDay().setCopy(tempend.getHourOfDay()+freeHours);
Log.v(TAG,"Tmp Start Date1: "+String.valueOf(tempstart)+"Tmp End Date1: "+String.valueOf(tempend));
tempstart=free.startDate;
Log.v(TAG,"Temp endDate : "+tempstart);
tempstart = tempstart.hourOfDay().setCopy(tempstart.getHourOfDay()+freeHours-interval);
Log.v(TAG,"Tmp Start Date2: "+tempstart+"Tmp End Date2: "+tempend);
if(tempstart.getHourOfDay() >= freeStart.getHourOfDay() && tempend.getHourOfDay() <= freeEnd.getHourOfDay()) {
Log.v(TAG,"While loop inside if condition inside if condition inside");
if(val!=0) {
hourSlots.add(new MyEvent(tempstart, tempend));
Log.v(TAG, "Tmp hour slot: " + tempstart + " : " + tempend);
eventStrings.add(
String.format(" " + tempstart.toString("dd/MM/yy HH:mm:ss") + " - " + tempend.toString("dd/MM/yy HH:mm:ss")));
Log.v(TAG, "After eventStrings: " + tempstart.toString("dd/MM/yy HH:mm:ss") + " : " + tempend.toString("dd/MM/yy HH:mm:ss"));
int hour=Integer.valueOf(tempstart.toString("HH"));
int mminute=Integer.valueOf(tempstart.toString("mm"));
Log.v(TAG,"Alarm Time "+hour+":"+mminute);
startAlarm(hour,mminute);
}
val++;
tempstart=null;
tempend=null;
}
}
freeHours--;
}
}
Log.v(TAG,"Event Strings : "+eventStrings);
return eventStrings;
}
MainActivity.java(部分code2):
在此代码段中,我为每个空闲时间段的开始时间创建了警报。
int broadcastCode=0;
public void startAlarm(int hour,int mminute){
broadcastCode++;
Intent intent=new Intent(MainActivity.this,MyBroadcastReceiver.class);
PendingIntent pendingIntent=PendingIntent.getBroadcast(MainActivity.this,broadcastCode,intent,0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Calendar cal_alarm=Calendar.getInstance();
cal_alarm.set(Calendar.HOUR_OF_DAY,hour);
cal_alarm.set(Calendar.MINUTE,mminute);
cal_alarm.set(Calendar.SECOND,00);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
alarmManager.setExact(AlarmManager.RTC_WAKEUP,cal_alarm.getTimeInMillis(),pendingIntent);
Toast.makeText(MainActivity.this,"Alarm > KITKAT & Alarm Set For: "+hour+" : "+mminute,Toast.LENGTH_SHORT).show();
}
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT){
alarmManager.set(AlarmManager.RTC_WAKEUP,cal_alarm.getTimeInMillis(),pendingIntent);
Toast.makeText(MainActivity.this,"Alarm < KITKAT & Alarm Set For: "+hour+" : "+mminute,Toast.LENGTH_SHORT).show();
}
}
当我在 getDataFromApi() 函数的 while 循环中调用 startAlarm() 函数时,
我收到这个错误:
can't create handler inside thread that has not called Looper.prepare()
如果有人能给我解决方案或指导,我将很高兴。谢谢。
在此处查看 link:
Can't create handler inside thread that has not called Looper.prepare()
但问题是 startAlarm 方法中的 'toast' 行,如下所示:
Toast.makeText(MainActivity.this,"Alarm > KITKAT & Alarm Set For: "+hour+" : "+mminute,Toast.LENGTH_SHORT).show();
任何时候在 Android 中更新视图都必须在 'main thread' 上完成,也称为 'UI thread'。
在这里使用日志记录可能比 toast 更好。
我使用此代码从 Google 日历 API 中获得了 1 小时的免费时段。
MainActivity.java:
private List<String> getDataFromApi() throws IOException {
LocalDateTime now = LocalDateTime.now();
int year = now.getYear();
int month = now.getMonthOfYear();
int day = now.getDayOfMonth();
org.joda.time.DateTime startDateJoda= new org.joda.time.DateTime(year,month,day,7,00);
org.joda.time.DateTime endDateJoda= new org.joda.time.DateTime(year,month,day,22,00);
// Convert from Joda-Time to old bundled j.u.Date
java.util.Date juDateStart = startDateJoda.toDate();
java.util.Date juDateEnd = endDateJoda.toDate();
Log.v(TAG,"Start Date joda value: "+juDateStart.toString());
Log.v(TAG,"End Date joda value: "+juDateEnd.toString());
// Convert from j.u.Date to Google Date.
com.google.api.client.util.DateTime googleDateTimeStart = new com.google.api.client.util.DateTime( juDateStart );
com.google.api.client.util.DateTime googleDateTimeEnd = new com.google.api.client.util.DateTime( juDateEnd );
Log.v(TAG,"Start Date Google value: "+googleDateTimeStart.toString());
Log.v(TAG,"End Date Google value: "+googleDateTimeEnd.toString());
List<String> eventStrings = new ArrayList<String>();
org.joda.time.DateTime rootStart = startDateJoda;
org.joda.time.DateTime rootEnd = endDateJoda;
Events events = mService.events().list("primary")
.setMaxResults(10)
.setTimeMin(googleDateTimeStart)
.setTimeMax(googleDateTimeEnd)
.setOrderBy("startTime")
.setSingleEvents(true)
.execute();
List<Event> items = events.getItems();
Log.v(TAG,"Items : "+items.toString()+"\n");
Log.v(TAG,"Items size : "+items.size());
int interval = 1 ; // how big single slot should be (in this case 1 hrs)
ArrayList<MyEvent> freeSlots = new ArrayList<MyEvent>();
for (int index =0;index<items.size();index++) {
Event event = items.get(index);
Log.v(TAG,"Items Index: "+event.toString()+"\n");
DateTime teststart=event.getStart().getDateTime();
DateTime testend=event.getEnd().getDateTime();
Log.v(TAG,"Test Start Date value: "+teststart.toString());
Log.v(TAG,"Test End Date value: "+testend.toString());
long milliseconds1 = teststart.getValue();
long milliseconds2 = testend.getValue();
org.joda.time.DateTime eventStartJoda= new org.joda.time.DateTime(milliseconds1);
org.joda.time.DateTime eventEndJoda= new org.joda.time.DateTime(milliseconds2);
Log.v(TAG,"Event Start Date joda value: "+eventStartJoda.toString());
Log.v(TAG,"Event Date joda value: "+eventEndJoda.toString());
Log.v(TAG,"Before if index == 0 && start<end");
if ((index == 0) && (startDateJoda.isBefore(eventStartJoda)) ) {
Log.v(TAG,"Before Inside if index == 0 && start<end");
freeSlots.add( new MyEvent(startDateJoda,eventEndJoda) );
Log.v(TAG,"After Inside if index == 0 && start<end");
}
if (index == 0) {
Log.v(TAG,"Before else if index == 0");
DateTime teststart2=event.getEnd().getDateTime();
long milliseconds3 = teststart2.getValue();
startDateJoda=new org.joda.time.DateTime(milliseconds3);
Log.v(TAG,"startDateJoda value: "+startDateJoda.toString());
}
long milliseconds5=0;
Log.v(TAG,"Before teststart4");
if(index!=0) {
DateTime teststart4 = items.get(index - 1).getEnd().getDateTime();
Log.v(TAG, "After teststart4");
milliseconds5 = teststart4.getValue();
Log.v(TAG, "Before if milliseconds5");
}
if (new org.joda.time.DateTime(milliseconds5).isBefore(eventStartJoda)) {
if(index!=0) {
freeSlots.add(new MyEvent
(new org.joda.time.DateTime(milliseconds5), eventStartJoda));
Log.v(TAG,"xxxxxxx1 value: "+ new org.joda.time.DateTime(milliseconds5).toString());
}
}
DateTime teststart3=event.getEnd().getDateTime();
long milliseconds4 = teststart3.getValue();
if ((items.size() == (index + 1)) && new org.joda.time.DateTime(milliseconds4).isBefore(endDateJoda)) {
freeSlots.add(new MyEvent(eventEndJoda, endDateJoda));
Log.v(TAG,"xxxxxxx2 value: "+ new org.joda.time.DateTime(milliseconds4).toString());
}
}
Log.v(TAG,"Before outside items size == 0 ");
if (items.size() == 0) {
Log.v(TAG,"Before Inside items size == 0 ");
freeSlots.add(new MyEvent(startDateJoda,endDateJoda));
Log.v(TAG,"After Inside items size == 0 ");
}
Log.v(TAG,"After outside items size == 0 ");
ArrayList<MyEvent> hourSlots = new ArrayList<MyEvent>();
org.joda.time.DateTime tempstart= null;
org.joda.time.DateTime tempend= null;
MyEvent temp = new MyEvent();
int val=0;
for(int index =0;index<freeSlots.size();index++){
MyEvent free = (MyEvent) freeSlots.get(index);
Log.v(TAG,"Free slot size : "+freeSlots.size());
int freeHours = free.endDate.getHourOfDay()- free.startDate.getHourOfDay();
Log.v(TAG,"FreeHours: "+freeHours);
org.joda.time.DateTime freeStart = free.startDate, freeEnd = free.endDate;
Log.v(TAG,"Free Start Date: "+free.startDate.toString()+"Free End Date: "+free.endDate.toString());
Log.v(TAG,"Before eventStrings: "+free.startDate.toString()+" : "+free.endDate.toString());
while(freeStart.getHourOfDay() + freeHours + interval>=0) { if(freeHours>=interval) {
Log.v(TAG,"free startDate : "+free.startDate);
tempend=free.startDate;
Log.v(TAG,"Temp startDate : "+tempend);
tempend= tempend.hourOfDay().setCopy(tempend.getHourOfDay()+freeHours);
Log.v(TAG,"Tmp Start Date1: "+String.valueOf(tempstart)+"Tmp End Date1: "+String.valueOf(tempend));
tempstart=free.startDate;
Log.v(TAG,"Temp endDate : "+tempstart);
tempstart = tempstart.hourOfDay().setCopy(tempstart.getHourOfDay()+freeHours-interval);
Log.v(TAG,"Tmp Start Date2: "+tempstart+"Tmp End Date2: "+tempend);
if(tempstart.getHourOfDay() >= freeStart.getHourOfDay() && tempend.getHourOfDay() <= freeEnd.getHourOfDay()) {
Log.v(TAG,"While loop inside if condition inside if condition inside");
if(val!=0) {
hourSlots.add(new MyEvent(tempstart, tempend));
Log.v(TAG, "Tmp hour slot: " + tempstart + " : " + tempend);
eventStrings.add(
String.format(" " + tempstart.toString("dd/MM/yy HH:mm:ss") + " - " + tempend.toString("dd/MM/yy HH:mm:ss")));
Log.v(TAG, "After eventStrings: " + tempstart.toString("dd/MM/yy HH:mm:ss") + " : " + tempend.toString("dd/MM/yy HH:mm:ss"));
int hour=Integer.valueOf(tempstart.toString("HH"));
int mminute=Integer.valueOf(tempstart.toString("mm"));
Log.v(TAG,"Alarm Time "+hour+":"+mminute);
startAlarm(hour,mminute);
}
val++;
tempstart=null;
tempend=null;
}
}
freeHours--;
}
}
Log.v(TAG,"Event Strings : "+eventStrings);
return eventStrings;
}
MainActivity.java(部分code2):
在此代码段中,我为每个空闲时间段的开始时间创建了警报。
int broadcastCode=0;
public void startAlarm(int hour,int mminute){
broadcastCode++;
Intent intent=new Intent(MainActivity.this,MyBroadcastReceiver.class);
PendingIntent pendingIntent=PendingIntent.getBroadcast(MainActivity.this,broadcastCode,intent,0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Calendar cal_alarm=Calendar.getInstance();
cal_alarm.set(Calendar.HOUR_OF_DAY,hour);
cal_alarm.set(Calendar.MINUTE,mminute);
cal_alarm.set(Calendar.SECOND,00);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
alarmManager.setExact(AlarmManager.RTC_WAKEUP,cal_alarm.getTimeInMillis(),pendingIntent);
Toast.makeText(MainActivity.this,"Alarm > KITKAT & Alarm Set For: "+hour+" : "+mminute,Toast.LENGTH_SHORT).show();
}
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT){
alarmManager.set(AlarmManager.RTC_WAKEUP,cal_alarm.getTimeInMillis(),pendingIntent);
Toast.makeText(MainActivity.this,"Alarm < KITKAT & Alarm Set For: "+hour+" : "+mminute,Toast.LENGTH_SHORT).show();
}
}
当我在 getDataFromApi() 函数的 while 循环中调用 startAlarm() 函数时,
我收到这个错误:
can't create handler inside thread that has not called Looper.prepare()
如果有人能给我解决方案或指导,我将很高兴。谢谢。
在此处查看 link: Can't create handler inside thread that has not called Looper.prepare()
但问题是 startAlarm 方法中的 'toast' 行,如下所示:
Toast.makeText(MainActivity.this,"Alarm > KITKAT & Alarm Set For: "+hour+" : "+mminute,Toast.LENGTH_SHORT).show();
任何时候在 Android 中更新视图都必须在 'main thread' 上完成,也称为 'UI thread'。
在这里使用日志记录可能比 toast 更好。