From 43d5d6d9e8485c91cdb136bbb6372fcdc99066aa Mon Sep 17 00:00:00 2001 From: Trevor Slocum Date: Tue, 13 Oct 2015 18:09:33 -0700 Subject: [PATCH] Initial open source release --- .gitignore | 42 + MeditationAssistant/.gitignore | 1 + MeditationAssistant/google-services.json | 1 + MeditationAssistant/lint.xml | 4 + MeditationAssistant/proguard-project.txt | 216 ++ .../src/main/AndroidManifest.xml | 187 ++ .../meditationassistant/AboutActivity.java | 157 + .../meditationassistant/CalendarFragment.java | 304 ++ .../meditationassistant/CompleteActivity.java | 421 +++ .../meditationassistant/Crypt.java | 123 + .../DailyNotification.java | 163 + .../meditationassistant/DatabaseHandler.java | 374 +++ .../FadeOutAnimationListener.java | 27 + .../meditationassistant/FileUtils.java | 503 ++++ .../JavaScriptInterface.java | 47 + .../JavascriptCallback.java | 5 + .../ListPreferenceSound.java | 309 ++ .../meditationassistant/MainActivity.java | 2546 ++++++++++++++++ .../meditationassistant/MediNET.java | 417 +++ .../meditationassistant/MediNETActivity.java | 566 ++++ .../meditationassistant/MediNETTask.java | 479 +++ .../MeditationAssistant.java | 1497 ++++++++++ .../MeditationProvider.java | 87 + .../MeditationProvider1.java | 5 + .../MeditationProvider2.java | 5 + .../MeditationProvider3.java | 5 + .../MeditationService.java | 76 + .../MeditationSession.java | 30 + .../meditationassistant/MeditationSounds.java | 45 + .../meditationassistant/MonthAdapter.java | 17 + .../meditationassistant/MonthAdapterMA.java | 303 ++ .../meditationassistant/NumToWord.java | 94 + .../meditationassistant/NumberPicker.java | 2642 +++++++++++++++++ .../meditationassistant/Preset.java | 42 + .../meditationassistant/ProgressActivity.java | 811 +++++ .../meditationassistant/Scroller.java | 495 +++ .../meditationassistant/SessionAdapter.java | 84 + .../meditationassistant/SessionSQL.java | 42 + .../meditationassistant/SessionsFragment.java | 273 ++ .../meditationassistant/SettingsActivity.java | 745 +++++ .../meditationassistant/StatsFragment.java | 149 + .../meditationassistant/TimePicker.java | 551 ++++ .../meditationassistant/TimePickerDialog.java | 157 + .../meditationassistant/TimePreference.java | 114 + .../meditationassistant/WakeLocker.java | 36 + .../WearListenerService.java | 55 + .../src/main/res/anim/fadeinma.xml | 11 + .../src/main/res/anim/fadeoutma.xml | 11 + .../src/main/res/anim/spin.xml | 73 + .../ab_bottom_solid_buddhism.9.png | Bin 0 -> 205 bytes .../res/drawable-hdpi/ab_solid_buddhism.9.png | Bin 0 -> 214 bytes .../ab_stacked_solid_buddhism.9.png | Bin 0 -> 200 bytes .../ab_texture_tile_buddhism.png | Bin 0 -> 140 bytes .../ab_transparent_buddhism.9.png | Bin 0 -> 202 bytes .../btn_cab_done_default_buddhism.9.png | Bin 0 -> 111 bytes .../btn_cab_done_focused_buddhism.9.png | Bin 0 -> 118 bytes .../btn_cab_done_pressed_buddhism.9.png | Bin 0 -> 125 bytes ..._check_off_disabled_focused_holo_light.png | Bin 0 -> 390 bytes ...hism_btn_check_off_disabled_holo_light.png | Bin 0 -> 361 bytes ...dhism_btn_check_off_focused_holo_light.png | Bin 0 -> 401 bytes .../buddhism_btn_check_off_holo_light.png | Bin 0 -> 242 bytes ...dhism_btn_check_off_pressed_holo_light.png | Bin 0 -> 423 bytes ...n_check_on_disabled_focused_holo_light.png | Bin 0 -> 784 bytes ...dhism_btn_check_on_disabled_holo_light.png | Bin 0 -> 624 bytes ...ddhism_btn_check_on_focused_holo_light.png | Bin 0 -> 1637 bytes .../buddhism_btn_check_on_holo_light.png | Bin 0 -> 1461 bytes ...ddhism_btn_check_on_pressed_holo_light.png | Bin 0 -> 803 bytes ..._default_disabled_focused_holo_light.9.png | Bin 0 -> 315 bytes ...hism_btn_default_disabled_holo_light.9.png | Bin 0 -> 422 bytes ...dhism_btn_default_focused_holo_light.9.png | Bin 0 -> 372 bytes ...ddhism_btn_default_normal_holo_light.9.png | Bin 0 -> 310 bytes ...dhism_btn_default_pressed_holo_light.9.png | Bin 0 -> 306 bytes ..._radio_off_disabled_focused_holo_light.png | Bin 0 -> 1329 bytes ...hism_btn_radio_off_disabled_holo_light.png | Bin 0 -> 717 bytes ...dhism_btn_radio_off_focused_holo_light.png | Bin 0 -> 1459 bytes .../buddhism_btn_radio_off_holo_light.png | Bin 0 -> 790 bytes ...dhism_btn_radio_off_pressed_holo_light.png | Bin 0 -> 1574 bytes ...n_radio_on_disabled_focused_holo_light.png | Bin 0 -> 2314 bytes ...dhism_btn_radio_on_disabled_holo_light.png | Bin 0 -> 1169 bytes ...ddhism_btn_radio_on_focused_holo_light.png | Bin 0 -> 2204 bytes .../buddhism_btn_radio_on_holo_light.png | Bin 0 -> 1446 bytes ...ddhism_btn_radio_on_pressed_holo_light.png | Bin 0 -> 1908 bytes ...ggle_off_disabled_focused_holo_light.9.png | Bin 0 -> 366 bytes ...m_btn_toggle_off_disabled_holo_light.9.png | Bin 0 -> 419 bytes ...sm_btn_toggle_off_focused_holo_light.9.png | Bin 0 -> 368 bytes ...ism_btn_toggle_off_normal_holo_light.9.png | Bin 0 -> 459 bytes ...sm_btn_toggle_off_pressed_holo_light.9.png | Bin 0 -> 419 bytes ...oggle_on_disabled_focused_holo_light.9.png | Bin 0 -> 398 bytes ...sm_btn_toggle_on_disabled_holo_light.9.png | Bin 0 -> 512 bytes ...ism_btn_toggle_on_focused_holo_light.9.png | Bin 0 -> 416 bytes ...hism_btn_toggle_on_normal_holo_light.9.png | Bin 0 -> 520 bytes ...ism_btn_toggle_on_pressed_holo_light.9.png | Bin 0 -> 556 bytes ...buddhism_fastscroll_thumb_default_holo.png | Bin 0 -> 250 bytes ...buddhism_fastscroll_thumb_pressed_holo.png | Bin 0 -> 463 bytes .../buddhism_ic_navigation_drawer.png | Bin 0 -> 120 bytes .../buddhism_list_activated_holo.9.png | Bin 0 -> 115 bytes .../buddhism_list_focused_holo.9.png | Bin 0 -> 139 bytes .../buddhism_list_longpressed_holo.9.png | Bin 0 -> 115 bytes .../buddhism_list_pressed_holo_light.9.png | Bin 0 -> 115 bytes ...sm_list_selector_disabled_holo_light.9.png | Bin 0 -> 189 bytes .../buddhism_progress_bg_holo_light.9.png | Bin 0 -> 175 bytes ...buddhism_progress_primary_holo_light.9.png | Bin 0 -> 360 bytes ...ddhism_progress_secondary_holo_light.9.png | Bin 0 -> 143 bytes ...ddhism_progressbar_indeterminate_holo1.png | Bin 0 -> 779 bytes ...ddhism_progressbar_indeterminate_holo2.png | Bin 0 -> 862 bytes ...ddhism_progressbar_indeterminate_holo3.png | Bin 0 -> 970 bytes ...ddhism_progressbar_indeterminate_holo4.png | Bin 0 -> 1019 bytes ...ddhism_progressbar_indeterminate_holo5.png | Bin 0 -> 912 bytes ...ddhism_progressbar_indeterminate_holo6.png | Bin 0 -> 1007 bytes ...ddhism_progressbar_indeterminate_holo7.png | Bin 0 -> 806 bytes ...ddhism_progressbar_indeterminate_holo8.png | Bin 0 -> 882 bytes .../buddhism_spinner_default_holo_light.9.png | Bin 0 -> 416 bytes ...buddhism_spinner_disabled_holo_light.9.png | Bin 0 -> 378 bytes .../buddhism_spinner_focused_holo_light.9.png | Bin 0 -> 522 bytes .../buddhism_spinner_pressed_holo_light.9.png | Bin 0 -> 589 bytes .../buddhism_tab_selected_focused_holo.9.png | Bin 0 -> 111 bytes .../buddhism_tab_selected_holo.9.png | Bin 0 -> 105 bytes .../buddhism_tab_selected_pressed_holo.9.png | Bin 0 -> 113 bytes ...buddhism_tab_unselected_focused_holo.9.png | Bin 0 -> 107 bytes .../buddhism_tab_unselected_holo.9.png | Bin 0 -> 104 bytes ...buddhism_tab_unselected_pressed_holo.9.png | Bin 0 -> 113 bytes .../buddhism_text_select_handle_left.png | Bin 0 -> 1394 bytes .../buddhism_text_select_handle_middle.png | Bin 0 -> 1499 bytes .../buddhism_text_select_handle_right.png | Bin 0 -> 1478 bytes ...dhism_textfield_activated_holo_light.9.png | Bin 0 -> 194 bytes ...uddhism_textfield_default_holo_light.9.png | Bin 0 -> 227 bytes ...extfield_disabled_focused_holo_light.9.png | Bin 0 -> 1208 bytes ...ddhism_textfield_disabled_holo_light.9.png | Bin 0 -> 1116 bytes ...uddhism_textfield_focused_holo_light.9.png | Bin 0 -> 288 bytes .../cab_background_bottom_buddhism.9.png | Bin 0 -> 207 bytes .../cab_background_top_buddhism.9.png | Bin 0 -> 207 bytes .../res/drawable-hdpi/ic_action_accounts.png | Bin 0 -> 621 bytes .../ic_action_accounts_light.png | Bin 0 -> 633 bytes .../ic_action_brightness_low.png | Bin 0 -> 802 bytes .../ic_action_brightness_low_light.png | Bin 0 -> 768 bytes .../main/res/drawable-hdpi/ic_action_chat.png | Bin 0 -> 302 bytes .../drawable-hdpi/ic_action_chat_light.png | Bin 0 -> 297 bytes .../res/drawable-hdpi/ic_action_downcloud.png | Bin 0 -> 1036 bytes .../ic_action_downcloud_light.png | Bin 0 -> 1814 bytes .../res/drawable-hdpi/ic_action_flash_on.png | Bin 0 -> 583 bytes .../ic_action_flash_on_light.png | Bin 0 -> 721 bytes .../res/drawable-hdpi/ic_action_forward.png | Bin 0 -> 605 bytes .../drawable-hdpi/ic_action_forward_light.png | Bin 0 -> 592 bytes .../drawable-hdpi/ic_action_full_screen.png | Bin 0 -> 589 bytes .../ic_action_full_screen_light.png | Bin 0 -> 585 bytes .../drawable-hdpi/ic_action_go_to_today.png | Bin 0 -> 360 bytes .../ic_action_go_to_today_light.png | Bin 0 -> 356 bytes .../res/drawable-hdpi/ic_action_group.png | Bin 0 -> 1079 bytes .../drawable-hdpi/ic_action_group_light.png | Bin 0 -> 1017 bytes .../main/res/drawable-hdpi/ic_action_info.png | Bin 0 -> 614 bytes .../drawable-hdpi/ic_action_info_light.png | Bin 0 -> 563 bytes .../drawable-hdpi/ic_action_network_cell.png | Bin 0 -> 236 bytes .../ic_action_network_cell_light.png | Bin 0 -> 250 bytes .../main/res/drawable-hdpi/ic_action_new.png | Bin 0 -> 157 bytes .../res/drawable-hdpi/ic_action_new_light.png | Bin 0 -> 157 bytes .../res/drawable-hdpi/ic_action_next_item.png | Bin 0 -> 478 bytes .../ic_action_next_item_light.png | Bin 0 -> 470 bytes .../drawable-hdpi/ic_action_not_important.png | Bin 0 -> 950 bytes .../ic_action_not_important_light.png | Bin 0 -> 932 bytes .../res/drawable-hdpi/ic_action_pause.png | Bin 0 -> 276 bytes .../res/drawable-hdpi/ic_action_person.png | Bin 0 -> 642 bytes .../drawable-hdpi/ic_action_person_light.png | Bin 0 -> 638 bytes .../drawable-hdpi/ic_action_previous_item.png | Bin 0 -> 547 bytes .../ic_action_previous_item_light.png | Bin 0 -> 529 bytes .../res/drawable-hdpi/ic_action_refresh.png | Bin 0 -> 992 bytes .../drawable-hdpi/ic_action_refresh_light.png | Bin 0 -> 958 bytes .../drawable-hdpi/ic_action_ring_volume.png | Bin 0 -> 834 bytes .../ic_action_ring_volume_light.png | Bin 0 -> 786 bytes .../res/drawable-hdpi/ic_action_settings.png | Bin 0 -> 807 bytes .../ic_action_settings_light.png | Bin 0 -> 953 bytes .../res/drawable-hdpi/ic_action_share.png | Bin 0 -> 641 bytes .../drawable-hdpi/ic_action_share_light.png | Bin 0 -> 613 bytes .../res/drawable-hdpi/ic_action_sign_out.png | Bin 0 -> 602 bytes .../ic_action_sign_out_light.png | Bin 0 -> 646 bytes .../drawable-hdpi/ic_action_sort_by_size.png | Bin 0 -> 267 bytes .../ic_action_sort_by_size_light.png | Bin 0 -> 270 bytes .../main/res/drawable-hdpi/ic_action_stop.png | Bin 0 -> 139 bytes .../main/res/drawable-hdpi/ic_action_time.png | Bin 0 -> 747 bytes .../drawable-hdpi/ic_action_time_light.png | Bin 0 -> 739 bytes .../res/drawable-hdpi/ic_action_upcloud.png | Bin 0 -> 1891 bytes .../drawable-hdpi/ic_action_upcloud_light.png | Bin 0 -> 1897 bytes .../drawable-hdpi/ic_action_view_as_list.png | Bin 0 -> 330 bytes .../ic_action_view_as_list_light.png | Bin 0 -> 335 bytes .../res/drawable-hdpi/ic_action_volume_on.png | Bin 0 -> 1078 bytes .../ic_action_volume_on_light.png | Bin 0 -> 1043 bytes .../res/drawable-hdpi/ic_action_website.png | Bin 0 -> 1442 bytes .../drawable-hdpi/ic_action_website_light.png | Bin 0 -> 1358 bytes .../res/drawable-hdpi/ic_notification.png | Bin 0 -> 1003 bytes .../drawable-hdpi/list_focused_buddhism.9.png | Bin 0 -> 148 bytes .../res/drawable-hdpi/list_focused_holo.9.png | Bin 0 -> 191 bytes .../drawable-hdpi/list_longpressed_holo.9.png | Bin 0 -> 154 bytes .../drawable-hdpi/list_pressed_buddhism.9.png | Bin 0 -> 113 bytes .../list_pressed_holo_dark.9.png | Bin 0 -> 159 bytes .../list_pressed_holo_light.9.png | Bin 0 -> 159 bytes .../list_selector_disabled_holo_dark.9.png | Bin 0 -> 189 bytes .../list_selector_disabled_holo_light.9.png | Bin 0 -> 189 bytes .../menu_dropdown_panel_buddhism.9.png | Bin 0 -> 1236 bytes .../np_numberpicker_selection_divider.9.png | Bin 0 -> 141 bytes .../drawable-hdpi/progress_bg_buddhism.9.png | Bin 0 -> 133 bytes .../progress_primary_buddhism.9.png | Bin 0 -> 761 bytes .../progress_secondary_buddhism.9.png | Bin 0 -> 139 bytes .../spinner_ab_default_buddhism.9.png | Bin 0 -> 376 bytes .../spinner_ab_disabled_buddhism.9.png | Bin 0 -> 358 bytes .../spinner_ab_focused_buddhism.9.png | Bin 0 -> 566 bytes .../spinner_ab_pressed_buddhism.9.png | Bin 0 -> 461 bytes .../drawable-hdpi/tab_selected_buddhism.9.png | Bin 0 -> 101 bytes .../tab_selected_focused_buddhism.9.png | Bin 0 -> 107 bytes .../tab_selected_pressed_buddhism.9.png | Bin 0 -> 107 bytes .../tab_unselected_buddhism.9.png | Bin 0 -> 103 bytes .../tab_unselected_focused_buddhism.9.png | Bin 0 -> 112 bytes .../tab_unselected_pressed_buddhism.9.png | Bin 0 -> 112 bytes .../res/drawable-ldpi/ic_action_accounts.png | Bin 0 -> 410 bytes .../ic_action_accounts_light.png | Bin 0 -> 382 bytes .../ic_action_brightness_low.png | Bin 0 -> 418 bytes .../ic_action_brightness_low_light.png | Bin 0 -> 404 bytes .../main/res/drawable-ldpi/ic_action_chat.png | Bin 0 -> 250 bytes .../drawable-ldpi/ic_action_chat_light.png | Bin 0 -> 250 bytes .../res/drawable-ldpi/ic_action_downcloud.png | Bin 0 -> 644 bytes .../ic_action_downcloud_light.png | Bin 0 -> 1402 bytes .../res/drawable-ldpi/ic_action_flash_on.png | Bin 0 -> 319 bytes .../ic_action_flash_on_light.png | Bin 0 -> 356 bytes .../res/drawable-ldpi/ic_action_forward.png | Bin 0 -> 376 bytes .../drawable-ldpi/ic_action_forward_light.png | Bin 0 -> 359 bytes .../drawable-ldpi/ic_action_full_screen.png | Bin 0 -> 312 bytes .../ic_action_full_screen_light.png | Bin 0 -> 311 bytes .../drawable-ldpi/ic_action_go_to_today.png | Bin 0 -> 282 bytes .../ic_action_go_to_today_light.png | Bin 0 -> 280 bytes .../res/drawable-ldpi/ic_action_group.png | Bin 0 -> 571 bytes .../drawable-ldpi/ic_action_group_light.png | Bin 0 -> 596 bytes .../main/res/drawable-ldpi/ic_action_info.png | Bin 0 -> 288 bytes .../drawable-ldpi/ic_action_info_light.png | Bin 0 -> 276 bytes .../drawable-ldpi/ic_action_network_cell.png | Bin 0 -> 227 bytes .../ic_action_network_cell_light.png | Bin 0 -> 227 bytes .../main/res/drawable-ldpi/ic_action_new.png | Bin 0 -> 138 bytes .../res/drawable-ldpi/ic_action_new_light.png | Bin 0 -> 138 bytes .../res/drawable-ldpi/ic_action_next_item.png | Bin 0 -> 280 bytes .../ic_action_next_item_light.png | Bin 0 -> 269 bytes .../drawable-ldpi/ic_action_not_important.png | Bin 0 -> 458 bytes .../ic_action_not_important_light.png | Bin 0 -> 445 bytes .../res/drawable-ldpi/ic_action_pause.png | Bin 0 -> 176 bytes .../res/drawable-ldpi/ic_action_person.png | Bin 0 -> 360 bytes .../drawable-ldpi/ic_action_person_light.png | Bin 0 -> 350 bytes .../drawable-ldpi/ic_action_previous_item.png | Bin 0 -> 294 bytes .../ic_action_previous_item_light.png | Bin 0 -> 280 bytes .../res/drawable-ldpi/ic_action_refresh.png | Bin 0 -> 558 bytes .../drawable-ldpi/ic_action_refresh_light.png | Bin 0 -> 593 bytes .../drawable-ldpi/ic_action_ring_volume.png | Bin 0 -> 461 bytes .../ic_action_ring_volume_light.png | Bin 0 -> 450 bytes .../res/drawable-ldpi/ic_action_settings.png | Bin 0 -> 242 bytes .../ic_action_settings_light.png | Bin 0 -> 244 bytes .../res/drawable-ldpi/ic_action_share.png | Bin 0 -> 348 bytes .../drawable-ldpi/ic_action_share_light.png | Bin 0 -> 377 bytes .../res/drawable-ldpi/ic_action_sign_out.png | Bin 0 -> 385 bytes .../ic_action_sign_out_light.png | Bin 0 -> 416 bytes .../drawable-ldpi/ic_action_sort_by_size.png | Bin 0 -> 229 bytes .../ic_action_sort_by_size_light.png | Bin 0 -> 228 bytes .../main/res/drawable-ldpi/ic_action_stop.png | Bin 0 -> 131 bytes .../main/res/drawable-ldpi/ic_action_time.png | Bin 0 -> 406 bytes .../drawable-ldpi/ic_action_time_light.png | Bin 0 -> 404 bytes .../res/drawable-ldpi/ic_action_upcloud.png | Bin 0 -> 1387 bytes .../drawable-ldpi/ic_action_upcloud_light.png | Bin 0 -> 1396 bytes .../drawable-ldpi/ic_action_view_as_list.png | Bin 0 -> 259 bytes .../ic_action_view_as_list_light.png | Bin 0 -> 267 bytes .../res/drawable-ldpi/ic_action_volume_on.png | Bin 0 -> 580 bytes .../ic_action_volume_on_light.png | Bin 0 -> 614 bytes .../res/drawable-ldpi/ic_action_website.png | Bin 0 -> 729 bytes .../drawable-ldpi/ic_action_website_light.png | Bin 0 -> 746 bytes .../res/drawable-ldpi/ic_notification.png | Bin 0 -> 470 bytes .../ab_bottom_solid_buddhism.9.png | Bin 0 -> 156 bytes .../res/drawable-mdpi/ab_solid_buddhism.9.png | Bin 0 -> 166 bytes .../ab_stacked_solid_buddhism.9.png | Bin 0 -> 158 bytes .../ab_texture_tile_buddhism.png | Bin 0 -> 105 bytes .../ab_transparent_buddhism.9.png | Bin 0 -> 164 bytes .../btn_cab_done_default_buddhism.9.png | Bin 0 -> 106 bytes .../btn_cab_done_focused_buddhism.9.png | Bin 0 -> 114 bytes .../btn_cab_done_pressed_buddhism.9.png | Bin 0 -> 134 bytes ..._check_off_disabled_focused_holo_light.png | Bin 0 -> 287 bytes ...hism_btn_check_off_disabled_holo_light.png | Bin 0 -> 329 bytes ...dhism_btn_check_off_focused_holo_light.png | Bin 0 -> 309 bytes .../buddhism_btn_check_off_holo_light.png | Bin 0 -> 183 bytes ...dhism_btn_check_off_pressed_holo_light.png | Bin 0 -> 289 bytes ...n_check_on_disabled_focused_holo_light.png | Bin 0 -> 562 bytes ...dhism_btn_check_on_disabled_holo_light.png | Bin 0 -> 508 bytes ...ddhism_btn_check_on_focused_holo_light.png | Bin 0 -> 1068 bytes .../buddhism_btn_check_on_holo_light.png | Bin 0 -> 959 bytes ...ddhism_btn_check_on_pressed_holo_light.png | Bin 0 -> 554 bytes ..._default_disabled_focused_holo_light.9.png | Bin 0 -> 222 bytes ...hism_btn_default_disabled_holo_light.9.png | Bin 0 -> 313 bytes ...dhism_btn_default_focused_holo_light.9.png | Bin 0 -> 273 bytes ...ddhism_btn_default_normal_holo_light.9.png | Bin 0 -> 242 bytes ...dhism_btn_default_pressed_holo_light.9.png | Bin 0 -> 236 bytes ..._radio_off_disabled_focused_holo_light.png | Bin 0 -> 747 bytes ...hism_btn_radio_off_disabled_holo_light.png | Bin 0 -> 479 bytes ...dhism_btn_radio_off_focused_holo_light.png | Bin 0 -> 801 bytes .../buddhism_btn_radio_off_holo_light.png | Bin 0 -> 428 bytes ...dhism_btn_radio_off_pressed_holo_light.png | Bin 0 -> 962 bytes ...n_radio_on_disabled_focused_holo_light.png | Bin 0 -> 1282 bytes ...dhism_btn_radio_on_disabled_holo_light.png | Bin 0 -> 736 bytes ...ddhism_btn_radio_on_focused_holo_light.png | Bin 0 -> 1209 bytes .../buddhism_btn_radio_on_holo_light.png | Bin 0 -> 838 bytes ...ddhism_btn_radio_on_pressed_holo_light.png | Bin 0 -> 1118 bytes ...ggle_off_disabled_focused_holo_light.9.png | Bin 0 -> 301 bytes ...m_btn_toggle_off_disabled_holo_light.9.png | Bin 0 -> 331 bytes ...sm_btn_toggle_off_focused_holo_light.9.png | Bin 0 -> 346 bytes ...ism_btn_toggle_off_normal_holo_light.9.png | Bin 0 -> 344 bytes ...sm_btn_toggle_off_pressed_holo_light.9.png | Bin 0 -> 298 bytes ...oggle_on_disabled_focused_holo_light.9.png | Bin 0 -> 292 bytes ...sm_btn_toggle_on_disabled_holo_light.9.png | Bin 0 -> 344 bytes ...ism_btn_toggle_on_focused_holo_light.9.png | Bin 0 -> 307 bytes ...hism_btn_toggle_on_normal_holo_light.9.png | Bin 0 -> 389 bytes ...ism_btn_toggle_on_pressed_holo_light.9.png | Bin 0 -> 361 bytes ...buddhism_fastscroll_thumb_default_holo.png | Bin 0 -> 168 bytes ...buddhism_fastscroll_thumb_pressed_holo.png | Bin 0 -> 301 bytes .../buddhism_ic_navigation_drawer.png | Bin 0 -> 105 bytes .../buddhism_list_activated_holo.9.png | Bin 0 -> 110 bytes .../buddhism_list_focused_holo.9.png | Bin 0 -> 117 bytes .../buddhism_list_longpressed_holo.9.png | Bin 0 -> 110 bytes .../buddhism_list_pressed_holo_light.9.png | Bin 0 -> 110 bytes ...sm_list_selector_disabled_holo_light.9.png | Bin 0 -> 171 bytes .../buddhism_progress_bg_holo_light.9.png | Bin 0 -> 161 bytes ...buddhism_progress_primary_holo_light.9.png | Bin 0 -> 256 bytes ...ddhism_progress_secondary_holo_light.9.png | Bin 0 -> 133 bytes ...ddhism_progressbar_indeterminate_holo1.png | Bin 0 -> 455 bytes ...ddhism_progressbar_indeterminate_holo2.png | Bin 0 -> 526 bytes ...ddhism_progressbar_indeterminate_holo3.png | Bin 0 -> 586 bytes ...ddhism_progressbar_indeterminate_holo4.png | Bin 0 -> 570 bytes ...ddhism_progressbar_indeterminate_holo5.png | Bin 0 -> 544 bytes ...ddhism_progressbar_indeterminate_holo6.png | Bin 0 -> 582 bytes ...ddhism_progressbar_indeterminate_holo7.png | Bin 0 -> 530 bytes ...ddhism_progressbar_indeterminate_holo8.png | Bin 0 -> 551 bytes .../buddhism_spinner_default_holo_light.9.png | Bin 0 -> 286 bytes ...buddhism_spinner_disabled_holo_light.9.png | Bin 0 -> 274 bytes .../buddhism_spinner_focused_holo_light.9.png | Bin 0 -> 374 bytes .../buddhism_spinner_pressed_holo_light.9.png | Bin 0 -> 419 bytes .../buddhism_tab_selected_focused_holo.9.png | Bin 0 -> 109 bytes .../buddhism_tab_selected_holo.9.png | Bin 0 -> 102 bytes .../buddhism_tab_selected_pressed_holo.9.png | Bin 0 -> 112 bytes ...buddhism_tab_unselected_focused_holo.9.png | Bin 0 -> 108 bytes .../buddhism_tab_unselected_holo.9.png | Bin 0 -> 103 bytes ...buddhism_tab_unselected_pressed_holo.9.png | Bin 0 -> 114 bytes .../buddhism_text_select_handle_left.png | Bin 0 -> 875 bytes .../buddhism_text_select_handle_middle.png | Bin 0 -> 899 bytes .../buddhism_text_select_handle_right.png | Bin 0 -> 937 bytes ...dhism_textfield_activated_holo_light.9.png | Bin 0 -> 162 bytes ...uddhism_textfield_default_holo_light.9.png | Bin 0 -> 182 bytes ...extfield_disabled_focused_holo_light.9.png | Bin 0 -> 1133 bytes ...ddhism_textfield_disabled_holo_light.9.png | Bin 0 -> 1094 bytes ...uddhism_textfield_focused_holo_light.9.png | Bin 0 -> 251 bytes .../cab_background_bottom_buddhism.9.png | Bin 0 -> 157 bytes .../cab_background_top_buddhism.9.png | Bin 0 -> 155 bytes .../res/drawable-mdpi/ic_action_accounts.png | Bin 0 -> 476 bytes .../ic_action_accounts_light.png | Bin 0 -> 467 bytes .../ic_action_brightness_low.png | Bin 0 -> 524 bytes .../ic_action_brightness_low_light.png | Bin 0 -> 509 bytes .../main/res/drawable-mdpi/ic_action_chat.png | Bin 0 -> 263 bytes .../drawable-mdpi/ic_action_chat_light.png | Bin 0 -> 259 bytes .../res/drawable-mdpi/ic_action_downcloud.png | Bin 0 -> 801 bytes .../ic_action_downcloud_light.png | Bin 0 -> 1523 bytes .../res/drawable-mdpi/ic_action_flash_on.png | Bin 0 -> 386 bytes .../ic_action_flash_on_light.png | Bin 0 -> 467 bytes .../res/drawable-mdpi/ic_action_forward.png | Bin 0 -> 408 bytes .../drawable-mdpi/ic_action_forward_light.png | Bin 0 -> 399 bytes .../drawable-mdpi/ic_action_full_screen.png | Bin 0 -> 408 bytes .../ic_action_full_screen_light.png | Bin 0 -> 409 bytes .../drawable-mdpi/ic_action_go_to_today.png | Bin 0 -> 262 bytes .../ic_action_go_to_today_light.png | Bin 0 -> 257 bytes .../res/drawable-mdpi/ic_action_group.png | Bin 0 -> 743 bytes .../drawable-mdpi/ic_action_group_light.png | Bin 0 -> 737 bytes .../main/res/drawable-mdpi/ic_action_info.png | Bin 0 -> 434 bytes .../drawable-mdpi/ic_action_info_light.png | Bin 0 -> 397 bytes .../drawable-mdpi/ic_action_network_cell.png | Bin 0 -> 244 bytes .../ic_action_network_cell_light.png | Bin 0 -> 234 bytes .../main/res/drawable-mdpi/ic_action_new.png | Bin 0 -> 132 bytes .../res/drawable-mdpi/ic_action_new_light.png | Bin 0 -> 132 bytes .../res/drawable-mdpi/ic_action_next_item.png | Bin 0 -> 345 bytes .../ic_action_next_item_light.png | Bin 0 -> 333 bytes .../drawable-mdpi/ic_action_not_important.png | Bin 0 -> 633 bytes .../ic_action_not_important_light.png | Bin 0 -> 631 bytes .../res/drawable-mdpi/ic_action_pause.png | Bin 0 -> 169 bytes .../res/drawable-mdpi/ic_action_person.png | Bin 0 -> 472 bytes .../drawable-mdpi/ic_action_person_light.png | Bin 0 -> 457 bytes .../drawable-mdpi/ic_action_previous_item.png | Bin 0 -> 374 bytes .../ic_action_previous_item_light.png | Bin 0 -> 363 bytes .../res/drawable-mdpi/ic_action_refresh.png | Bin 0 -> 748 bytes .../drawable-mdpi/ic_action_refresh_light.png | Bin 0 -> 733 bytes .../drawable-mdpi/ic_action_ring_volume.png | Bin 0 -> 595 bytes .../ic_action_ring_volume_light.png | Bin 0 -> 573 bytes .../res/drawable-mdpi/ic_action_settings.png | Bin 0 -> 550 bytes .../ic_action_settings_light.png | Bin 0 -> 594 bytes .../res/drawable-mdpi/ic_action_share.png | Bin 0 -> 458 bytes .../drawable-mdpi/ic_action_share_light.png | Bin 0 -> 450 bytes .../res/drawable-mdpi/ic_action_sign_out.png | Bin 0 -> 406 bytes .../ic_action_sign_out_light.png | Bin 0 -> 450 bytes .../drawable-mdpi/ic_action_sort_by_size.png | Bin 0 -> 265 bytes .../ic_action_sort_by_size_light.png | Bin 0 -> 268 bytes .../main/res/drawable-mdpi/ic_action_stop.png | Bin 0 -> 126 bytes .../main/res/drawable-mdpi/ic_action_time.png | Bin 0 -> 527 bytes .../drawable-mdpi/ic_action_time_light.png | Bin 0 -> 524 bytes .../res/drawable-mdpi/ic_action_upcloud.png | Bin 0 -> 1567 bytes .../drawable-mdpi/ic_action_upcloud_light.png | Bin 0 -> 1577 bytes .../drawable-mdpi/ic_action_view_as_list.png | Bin 0 -> 310 bytes .../ic_action_view_as_list_light.png | Bin 0 -> 300 bytes .../res/drawable-mdpi/ic_action_volume_on.png | Bin 0 -> 781 bytes .../ic_action_volume_on_light.png | Bin 0 -> 752 bytes .../res/drawable-mdpi/ic_action_website.png | Bin 0 -> 982 bytes .../drawable-mdpi/ic_action_website_light.png | Bin 0 -> 925 bytes .../res/drawable-mdpi/ic_notification.png | Bin 0 -> 737 bytes .../drawable-mdpi/list_focused_buddhism.9.png | Bin 0 -> 121 bytes .../res/drawable-mdpi/list_focused_holo.9.png | Bin 0 -> 171 bytes .../drawable-mdpi/list_longpressed_holo.9.png | Bin 0 -> 151 bytes .../drawable-mdpi/list_pressed_buddhism.9.png | Bin 0 -> 110 bytes .../list_pressed_holo_dark.9.png | Bin 0 -> 158 bytes .../list_pressed_holo_light.9.png | Bin 0 -> 158 bytes .../list_selector_disabled_holo_dark.9.png | Bin 0 -> 172 bytes .../list_selector_disabled_holo_light.9.png | Bin 0 -> 171 bytes .../menu_dropdown_panel_buddhism.9.png | Bin 0 -> 812 bytes .../np_numberpicker_selection_divider.9.png | Bin 0 -> 135 bytes .../drawable-mdpi/progress_bg_buddhism.9.png | Bin 0 -> 126 bytes .../progress_primary_buddhism.9.png | Bin 0 -> 482 bytes .../progress_secondary_buddhism.9.png | Bin 0 -> 126 bytes .../spinner_ab_default_buddhism.9.png | Bin 0 -> 314 bytes .../spinner_ab_disabled_buddhism.9.png | Bin 0 -> 308 bytes .../spinner_ab_focused_buddhism.9.png | Bin 0 -> 410 bytes .../spinner_ab_pressed_buddhism.9.png | Bin 0 -> 351 bytes .../drawable-mdpi/tab_selected_buddhism.9.png | Bin 0 -> 97 bytes .../tab_selected_focused_buddhism.9.png | Bin 0 -> 104 bytes .../tab_selected_pressed_buddhism.9.png | Bin 0 -> 104 bytes .../tab_unselected_buddhism.9.png | Bin 0 -> 107 bytes .../tab_unselected_focused_buddhism.9.png | Bin 0 -> 112 bytes .../tab_unselected_pressed_buddhism.9.png | Bin 0 -> 114 bytes .../src/main/res/drawable-xhdpi/.directory | 8 + .../ab_bottom_solid_buddhism.9.png | Bin 0 -> 263 bytes .../drawable-xhdpi/ab_solid_buddhism.9.png | Bin 0 -> 275 bytes .../ab_stacked_solid_buddhism.9.png | Bin 0 -> 241 bytes .../ab_texture_tile_buddhism.png | Bin 0 -> 123 bytes .../ab_transparent_buddhism.9.png | Bin 0 -> 267 bytes .../btn_cab_done_default_buddhism.9.png | Bin 0 -> 122 bytes .../btn_cab_done_focused_buddhism.9.png | Bin 0 -> 125 bytes .../btn_cab_done_pressed_buddhism.9.png | Bin 0 -> 129 bytes ..._check_off_disabled_focused_holo_light.png | Bin 0 -> 452 bytes ...hism_btn_check_off_disabled_holo_light.png | Bin 0 -> 375 bytes ...dhism_btn_check_off_focused_holo_light.png | Bin 0 -> 466 bytes .../buddhism_btn_check_off_holo_light.png | Bin 0 -> 293 bytes ...dhism_btn_check_off_pressed_holo_light.png | Bin 0 -> 549 bytes ...n_check_on_disabled_focused_holo_light.png | Bin 0 -> 1038 bytes ...dhism_btn_check_on_disabled_holo_light.png | Bin 0 -> 762 bytes ...ddhism_btn_check_on_focused_holo_light.png | Bin 0 -> 2805 bytes .../buddhism_btn_check_on_holo_light.png | Bin 0 -> 2536 bytes ...ddhism_btn_check_on_pressed_holo_light.png | Bin 0 -> 1134 bytes ..._default_disabled_focused_holo_light.9.png | Bin 0 -> 375 bytes ...hism_btn_default_disabled_holo_light.9.png | Bin 0 -> 541 bytes ...dhism_btn_default_focused_holo_light.9.png | Bin 0 -> 466 bytes ...ddhism_btn_default_normal_holo_light.9.png | Bin 0 -> 381 bytes ...dhism_btn_default_pressed_holo_light.9.png | Bin 0 -> 367 bytes ..._radio_off_disabled_focused_holo_light.png | Bin 0 -> 1996 bytes ...hism_btn_radio_off_disabled_holo_light.png | Bin 0 -> 919 bytes ...dhism_btn_radio_off_focused_holo_light.png | Bin 0 -> 2181 bytes .../buddhism_btn_radio_off_holo_light.png | Bin 0 -> 1043 bytes ...dhism_btn_radio_off_pressed_holo_light.png | Bin 0 -> 2235 bytes ...n_radio_on_disabled_focused_holo_light.png | Bin 0 -> 3505 bytes ...dhism_btn_radio_on_disabled_holo_light.png | Bin 0 -> 1643 bytes ...ddhism_btn_radio_on_focused_holo_light.png | Bin 0 -> 3615 bytes .../buddhism_btn_radio_on_holo_light.png | Bin 0 -> 2460 bytes ...ddhism_btn_radio_on_pressed_holo_light.png | Bin 0 -> 2683 bytes ...ggle_off_disabled_focused_holo_light.9.png | Bin 0 -> 402 bytes ...m_btn_toggle_off_disabled_holo_light.9.png | Bin 0 -> 528 bytes ...sm_btn_toggle_off_focused_holo_light.9.png | Bin 0 -> 433 bytes ...ism_btn_toggle_off_normal_holo_light.9.png | Bin 0 -> 574 bytes ...sm_btn_toggle_off_pressed_holo_light.9.png | Bin 0 -> 546 bytes ...oggle_on_disabled_focused_holo_light.9.png | Bin 0 -> 443 bytes ...sm_btn_toggle_on_disabled_holo_light.9.png | Bin 0 -> 627 bytes ...ism_btn_toggle_on_focused_holo_light.9.png | Bin 0 -> 516 bytes ...hism_btn_toggle_on_normal_holo_light.9.png | Bin 0 -> 557 bytes ...ism_btn_toggle_on_pressed_holo_light.9.png | Bin 0 -> 721 bytes ...buddhism_fastscroll_thumb_default_holo.png | Bin 0 -> 335 bytes ...buddhism_fastscroll_thumb_pressed_holo.png | Bin 0 -> 604 bytes .../buddhism_ic_navigation_drawer.png | Bin 0 -> 132 bytes .../buddhism_list_activated_holo.9.png | Bin 0 -> 121 bytes .../buddhism_list_focused_holo.9.png | Bin 0 -> 154 bytes .../buddhism_list_longpressed_holo.9.png | Bin 0 -> 121 bytes .../buddhism_list_pressed_holo_light.9.png | Bin 0 -> 121 bytes ...sm_list_selector_disabled_holo_light.9.png | Bin 0 -> 188 bytes .../buddhism_progress_bg_holo_light.9.png | Bin 0 -> 178 bytes ...buddhism_progress_primary_holo_light.9.png | Bin 0 -> 459 bytes ...ddhism_progress_secondary_holo_light.9.png | Bin 0 -> 145 bytes ...ddhism_progressbar_indeterminate_holo1.png | Bin 0 -> 879 bytes ...ddhism_progressbar_indeterminate_holo2.png | Bin 0 -> 1056 bytes ...ddhism_progressbar_indeterminate_holo3.png | Bin 0 -> 1252 bytes ...ddhism_progressbar_indeterminate_holo4.png | Bin 0 -> 1205 bytes ...ddhism_progressbar_indeterminate_holo5.png | Bin 0 -> 1178 bytes ...ddhism_progressbar_indeterminate_holo6.png | Bin 0 -> 1284 bytes ...ddhism_progressbar_indeterminate_holo7.png | Bin 0 -> 1144 bytes ...ddhism_progressbar_indeterminate_holo8.png | Bin 0 -> 1127 bytes .../buddhism_spinner_default_holo_light.9.png | Bin 0 -> 519 bytes ...buddhism_spinner_disabled_holo_light.9.png | Bin 0 -> 420 bytes .../buddhism_spinner_focused_holo_light.9.png | Bin 0 -> 667 bytes .../buddhism_spinner_pressed_holo_light.9.png | Bin 0 -> 740 bytes .../buddhism_tab_selected_focused_holo.9.png | Bin 0 -> 112 bytes .../buddhism_tab_selected_holo.9.png | Bin 0 -> 110 bytes .../buddhism_tab_selected_pressed_holo.9.png | Bin 0 -> 115 bytes ...buddhism_tab_unselected_focused_holo.9.png | Bin 0 -> 111 bytes .../buddhism_tab_unselected_holo.9.png | Bin 0 -> 119 bytes ...buddhism_tab_unselected_pressed_holo.9.png | Bin 0 -> 120 bytes .../buddhism_text_select_handle_left.png | Bin 0 -> 1896 bytes .../buddhism_text_select_handle_middle.png | Bin 0 -> 2033 bytes .../buddhism_text_select_handle_right.png | Bin 0 -> 2045 bytes ...dhism_textfield_activated_holo_light.9.png | Bin 0 -> 226 bytes ...uddhism_textfield_default_holo_light.9.png | Bin 0 -> 220 bytes ...extfield_disabled_focused_holo_light.9.png | Bin 0 -> 1176 bytes ...ddhism_textfield_disabled_holo_light.9.png | Bin 0 -> 1116 bytes ...uddhism_textfield_focused_holo_light.9.png | Bin 0 -> 418 bytes .../cab_background_bottom_buddhism.9.png | Bin 0 -> 267 bytes .../cab_background_top_buddhism.9.png | Bin 0 -> 267 bytes .../res/drawable-xhdpi/ic_action_accounts.png | Bin 0 -> 777 bytes .../ic_action_accounts_light.png | Bin 0 -> 750 bytes .../ic_action_brightness_low.png | Bin 0 -> 1019 bytes .../ic_action_brightness_low_light.png | Bin 0 -> 966 bytes .../res/drawable-xhdpi/ic_action_chat.png | Bin 0 -> 291 bytes .../drawable-xhdpi/ic_action_chat_light.png | Bin 0 -> 291 bytes .../drawable-xhdpi/ic_action_downcloud.png | Bin 0 -> 1235 bytes .../ic_action_downcloud_light.png | Bin 0 -> 2092 bytes .../res/drawable-xhdpi/ic_action_flash_on.png | Bin 0 -> 805 bytes .../ic_action_flash_on_light.png | Bin 0 -> 949 bytes .../res/drawable-xhdpi/ic_action_forward.png | Bin 0 -> 671 bytes .../ic_action_forward_light.png | Bin 0 -> 679 bytes .../drawable-xhdpi/ic_action_full_screen.png | Bin 0 -> 708 bytes .../ic_action_full_screen_light.png | Bin 0 -> 693 bytes .../drawable-xhdpi/ic_action_go_to_today.png | Bin 0 -> 312 bytes .../ic_action_go_to_today_light.png | Bin 0 -> 310 bytes .../res/drawable-xhdpi/ic_action_group.png | Bin 0 -> 1394 bytes .../drawable-xhdpi/ic_action_group_light.png | Bin 0 -> 1262 bytes .../res/drawable-xhdpi/ic_action_info.png | Bin 0 -> 787 bytes .../drawable-xhdpi/ic_action_info_light.png | Bin 0 -> 748 bytes .../drawable-xhdpi/ic_action_network_cell.png | Bin 0 -> 261 bytes .../ic_action_network_cell_light.png | Bin 0 -> 257 bytes .../main/res/drawable-xhdpi/ic_action_new.png | Bin 0 -> 160 bytes .../drawable-xhdpi/ic_action_new_light.png | Bin 0 -> 160 bytes .../drawable-xhdpi/ic_action_next_item.png | Bin 0 -> 589 bytes .../ic_action_next_item_light.png | Bin 0 -> 579 bytes .../ic_action_not_important.png | Bin 0 -> 1257 bytes .../ic_action_not_important_light.png | Bin 0 -> 1173 bytes .../res/drawable-xhdpi/ic_action_pause.png | Bin 0 -> 314 bytes .../res/drawable-xhdpi/ic_action_person.png | Bin 0 -> 844 bytes .../drawable-xhdpi/ic_action_person_light.png | Bin 0 -> 788 bytes .../ic_action_previous_item.png | Bin 0 -> 663 bytes .../ic_action_previous_item_light.png | Bin 0 -> 628 bytes .../res/drawable-xhdpi/ic_action_refresh.png | Bin 0 -> 1251 bytes .../ic_action_refresh_light.png | Bin 0 -> 1164 bytes .../drawable-xhdpi/ic_action_ring_volume.png | Bin 0 -> 1123 bytes .../ic_action_ring_volume_light.png | Bin 0 -> 1037 bytes .../res/drawable-xhdpi/ic_action_settings.png | Bin 0 -> 1124 bytes .../ic_action_settings_light.png | Bin 0 -> 1231 bytes .../res/drawable-xhdpi/ic_action_share.png | Bin 0 -> 828 bytes .../drawable-xhdpi/ic_action_share_light.png | Bin 0 -> 761 bytes .../res/drawable-xhdpi/ic_action_sign_out.png | Bin 0 -> 650 bytes .../ic_action_sign_out_light.png | Bin 0 -> 729 bytes .../drawable-xhdpi/ic_action_sort_by_size.png | Bin 0 -> 283 bytes .../ic_action_sort_by_size_light.png | Bin 0 -> 286 bytes .../res/drawable-xhdpi/ic_action_stop.png | Bin 0 -> 132 bytes .../res/drawable-xhdpi/ic_action_time.png | Bin 0 -> 969 bytes .../drawable-xhdpi/ic_action_time_light.png | Bin 0 -> 939 bytes .../res/drawable-xhdpi/ic_action_upcloud.png | Bin 0 -> 2235 bytes .../ic_action_upcloud_light.png | Bin 0 -> 2210 bytes .../drawable-xhdpi/ic_action_view_as_list.png | Bin 0 -> 326 bytes .../ic_action_view_as_list_light.png | Bin 0 -> 326 bytes .../drawable-xhdpi/ic_action_volume_on.png | Bin 0 -> 1417 bytes .../ic_action_volume_on_light.png | Bin 0 -> 1332 bytes .../res/drawable-xhdpi/ic_action_website.png | Bin 0 -> 1860 bytes .../ic_action_website_light.png | Bin 0 -> 1710 bytes .../res/drawable-xhdpi/ic_notification.png | Bin 0 -> 1255 bytes .../list_focused_buddhism.9.png | Bin 0 -> 151 bytes .../drawable-xhdpi/list_focused_holo.9.png | Bin 0 -> 203 bytes .../list_longpressed_holo.9.png | Bin 0 -> 158 bytes .../list_pressed_buddhism.9.png | Bin 0 -> 114 bytes .../list_pressed_holo_dark.9.png | Bin 0 -> 163 bytes .../list_pressed_holo_light.9.png | Bin 0 -> 163 bytes .../list_selector_disabled_holo_dark.9.png | Bin 0 -> 190 bytes .../list_selector_disabled_holo_light.9.png | Bin 0 -> 188 bytes .../menu_dropdown_panel_buddhism.9.png | Bin 0 -> 1859 bytes .../np_numberpicker_selection_divider.9.png | Bin 0 -> 142 bytes .../drawable-xhdpi/progress_bg_buddhism.9.png | Bin 0 -> 134 bytes .../progress_primary_buddhism.9.png | Bin 0 -> 1021 bytes .../progress_secondary_buddhism.9.png | Bin 0 -> 134 bytes .../spinner_ab_default_buddhism.9.png | Bin 0 -> 476 bytes .../spinner_ab_disabled_buddhism.9.png | Bin 0 -> 457 bytes .../spinner_ab_focused_buddhism.9.png | Bin 0 -> 726 bytes .../spinner_ab_pressed_buddhism.9.png | Bin 0 -> 603 bytes .../tab_selected_buddhism.9.png | Bin 0 -> 105 bytes .../tab_selected_focused_buddhism.9.png | Bin 0 -> 111 bytes .../tab_selected_pressed_buddhism.9.png | Bin 0 -> 111 bytes .../tab_unselected_buddhism.9.png | Bin 0 -> 112 bytes .../tab_unselected_focused_buddhism.9.png | Bin 0 -> 125 bytes .../tab_unselected_pressed_buddhism.9.png | Bin 0 -> 125 bytes .../ab_bottom_solid_buddhism.9.png | Bin 0 -> 366 bytes .../drawable-xxhdpi/ab_solid_buddhism.9.png | Bin 0 -> 362 bytes .../ab_stacked_solid_buddhism.9.png | Bin 0 -> 345 bytes .../ab_texture_tile_buddhism.png | Bin 0 -> 283 bytes .../ab_transparent_buddhism.9.png | Bin 0 -> 351 bytes .../btn_cab_done_default_buddhism.9.png | Bin 0 -> 140 bytes .../btn_cab_done_focused_buddhism.9.png | Bin 0 -> 131 bytes .../btn_cab_done_pressed_buddhism.9.png | Bin 0 -> 148 bytes ..._check_off_disabled_focused_holo_light.png | Bin 0 -> 443 bytes ...hism_btn_check_off_disabled_holo_light.png | Bin 0 -> 1177 bytes ...dhism_btn_check_off_focused_holo_light.png | Bin 0 -> 523 bytes .../buddhism_btn_check_off_holo_light.png | Bin 0 -> 443 bytes ...dhism_btn_check_off_pressed_holo_light.png | Bin 0 -> 598 bytes ...n_check_on_disabled_focused_holo_light.png | Bin 0 -> 1089 bytes ...dhism_btn_check_on_disabled_holo_light.png | Bin 0 -> 1574 bytes ...ddhism_btn_check_on_focused_holo_light.png | Bin 0 -> 3780 bytes .../buddhism_btn_check_on_holo_light.png | Bin 0 -> 3499 bytes ...ddhism_btn_check_on_pressed_holo_light.png | Bin 0 -> 1155 bytes ..._default_disabled_focused_holo_light.9.png | Bin 0 -> 529 bytes ...hism_btn_default_disabled_holo_light.9.png | Bin 0 -> 1643 bytes ...dhism_btn_default_focused_holo_light.9.png | Bin 0 -> 818 bytes ...ddhism_btn_default_normal_holo_light.9.png | Bin 0 -> 847 bytes ...dhism_btn_default_pressed_holo_light.9.png | Bin 0 -> 793 bytes ..._radio_off_disabled_focused_holo_light.png | Bin 0 -> 2479 bytes ...hism_btn_radio_off_disabled_holo_light.png | Bin 0 -> 2208 bytes ...dhism_btn_radio_off_focused_holo_light.png | Bin 0 -> 2719 bytes .../buddhism_btn_radio_off_holo_light.png | Bin 0 -> 1660 bytes ...dhism_btn_radio_off_pressed_holo_light.png | Bin 0 -> 3039 bytes ...n_radio_on_disabled_focused_holo_light.png | Bin 0 -> 4354 bytes ...dhism_btn_radio_on_disabled_holo_light.png | Bin 0 -> 3894 bytes ...ddhism_btn_radio_on_focused_holo_light.png | Bin 0 -> 4909 bytes .../buddhism_btn_radio_on_holo_light.png | Bin 0 -> 3634 bytes ...ddhism_btn_radio_on_pressed_holo_light.png | Bin 0 -> 3544 bytes ...ggle_off_disabled_focused_holo_light.9.png | Bin 0 -> 593 bytes ...m_btn_toggle_off_disabled_holo_light.9.png | Bin 0 -> 1662 bytes ...sm_btn_toggle_off_focused_holo_light.9.png | Bin 0 -> 626 bytes ...ism_btn_toggle_off_normal_holo_light.9.png | Bin 0 -> 852 bytes ...sm_btn_toggle_off_pressed_holo_light.9.png | Bin 0 -> 869 bytes ...oggle_on_disabled_focused_holo_light.9.png | Bin 0 -> 671 bytes ...sm_btn_toggle_on_disabled_holo_light.9.png | Bin 0 -> 1031 bytes ...ism_btn_toggle_on_focused_holo_light.9.png | Bin 0 -> 759 bytes ...hism_btn_toggle_on_normal_holo_light.9.png | Bin 0 -> 841 bytes ...ism_btn_toggle_on_pressed_holo_light.9.png | Bin 0 -> 1197 bytes ...buddhism_fastscroll_thumb_default_holo.png | Bin 0 -> 625 bytes ...buddhism_fastscroll_thumb_pressed_holo.png | Bin 0 -> 983 bytes .../buddhism_ic_navigation_drawer.png | Bin 0 -> 159 bytes .../buddhism_list_activated_holo.9.png | Bin 0 -> 132 bytes .../buddhism_list_focused_holo.9.png | Bin 0 -> 157 bytes .../buddhism_list_longpressed_holo.9.png | Bin 0 -> 133 bytes .../buddhism_list_pressed_holo_light.9.png | Bin 0 -> 133 bytes ...sm_list_selector_disabled_holo_light.9.png | Bin 0 -> 280 bytes .../buddhism_progress_bg_holo_light.9.png | Bin 0 -> 1084 bytes ...buddhism_progress_primary_holo_light.9.png | Bin 0 -> 818 bytes ...ddhism_progress_secondary_holo_light.9.png | Bin 0 -> 141 bytes ...ddhism_progressbar_indeterminate_holo1.png | Bin 0 -> 1350 bytes ...ddhism_progressbar_indeterminate_holo2.png | Bin 0 -> 1651 bytes ...ddhism_progressbar_indeterminate_holo3.png | Bin 0 -> 1912 bytes ...ddhism_progressbar_indeterminate_holo4.png | Bin 0 -> 1910 bytes ...ddhism_progressbar_indeterminate_holo5.png | Bin 0 -> 1856 bytes ...ddhism_progressbar_indeterminate_holo6.png | Bin 0 -> 1973 bytes ...ddhism_progressbar_indeterminate_holo7.png | Bin 0 -> 1768 bytes ...ddhism_progressbar_indeterminate_holo8.png | Bin 0 -> 1769 bytes .../buddhism_spinner_default_holo_light.9.png | Bin 0 -> 445 bytes ...buddhism_spinner_disabled_holo_light.9.png | Bin 0 -> 1326 bytes .../buddhism_spinner_focused_holo_light.9.png | Bin 0 -> 667 bytes .../buddhism_spinner_pressed_holo_light.9.png | Bin 0 -> 632 bytes .../buddhism_tab_selected_focused_holo.9.png | Bin 0 -> 118 bytes .../buddhism_tab_selected_holo.9.png | Bin 0 -> 114 bytes .../buddhism_tab_selected_pressed_holo.9.png | Bin 0 -> 120 bytes ...buddhism_tab_unselected_focused_holo.9.png | Bin 0 -> 116 bytes .../buddhism_tab_unselected_holo.9.png | Bin 0 -> 124 bytes ...buddhism_tab_unselected_pressed_holo.9.png | Bin 0 -> 125 bytes .../buddhism_text_select_handle_left.png | Bin 0 -> 2804 bytes .../buddhism_text_select_handle_middle.png | Bin 0 -> 3043 bytes .../buddhism_text_select_handle_right.png | Bin 0 -> 2673 bytes ...dhism_textfield_activated_holo_light.9.png | Bin 0 -> 325 bytes ...uddhism_textfield_default_holo_light.9.png | Bin 0 -> 325 bytes ...extfield_disabled_focused_holo_light.9.png | Bin 0 -> 464 bytes ...ddhism_textfield_disabled_holo_light.9.png | Bin 0 -> 315 bytes ...uddhism_textfield_focused_holo_light.9.png | Bin 0 -> 501 bytes .../cab_background_bottom_buddhism.9.png | Bin 0 -> 373 bytes .../cab_background_top_buddhism.9.png | Bin 0 -> 361 bytes .../ic_action_brightness_low.png | Bin 0 -> 1409 bytes .../ic_action_brightness_low_light.png | Bin 0 -> 1500 bytes .../drawable-xxhdpi/ic_action_flash_on.png | Bin 0 -> 627 bytes .../ic_action_flash_on_light.png | Bin 0 -> 631 bytes .../drawable-xxhdpi/ic_action_full_screen.png | Bin 0 -> 1009 bytes .../ic_action_full_screen_light.png | Bin 0 -> 1127 bytes .../res/drawable-xxhdpi/ic_action_info.png | Bin 0 -> 1215 bytes .../drawable-xxhdpi/ic_action_info_light.png | Bin 0 -> 1409 bytes .../res/drawable-xxhdpi/ic_action_new.png | Bin 0 -> 288 bytes .../drawable-xxhdpi/ic_action_new_light.png | Bin 0 -> 305 bytes .../ic_action_not_important.png | Bin 0 -> 1466 bytes .../ic_action_not_important_light.png | Bin 0 -> 1722 bytes .../res/drawable-xxhdpi/ic_action_person.png | Bin 0 -> 950 bytes .../ic_action_person_light.png | Bin 0 -> 1004 bytes .../res/drawable-xxhdpi/ic_action_refresh.png | Bin 0 -> 1239 bytes .../ic_action_refresh_light.png | Bin 0 -> 1274 bytes .../drawable-xxhdpi/ic_action_ring_volume.png | Bin 0 -> 1299 bytes .../ic_action_ring_volume_light.png | Bin 0 -> 1586 bytes .../drawable-xxhdpi/ic_action_settings.png | Bin 0 -> 1661 bytes .../ic_action_settings_light.png | Bin 0 -> 1863 bytes .../res/drawable-xxhdpi/ic_action_share.png | Bin 0 -> 969 bytes .../drawable-xxhdpi/ic_action_share_light.png | Bin 0 -> 1094 bytes .../ic_action_sort_by_size.png | Bin 0 -> 253 bytes .../ic_action_sort_by_size_light.png | Bin 0 -> 257 bytes .../res/drawable-xxhdpi/ic_action_stop.png | Bin 0 -> 262 bytes .../res/drawable-xxhdpi/ic_action_time.png | Bin 0 -> 1317 bytes .../drawable-xxhdpi/ic_action_time_light.png | Bin 0 -> 1432 bytes .../drawable-xxhdpi/ic_action_volume_on.png | Bin 0 -> 1439 bytes .../ic_action_volume_on_light.png | Bin 0 -> 1497 bytes .../res/drawable-xxhdpi/ic_notification.png | Bin 0 -> 1955 bytes .../list_focused_buddhism.9.png | Bin 0 -> 164 bytes .../list_pressed_buddhism.9.png | Bin 0 -> 137 bytes .../menu_dropdown_panel_buddhism.9.png | Bin 0 -> 3971 bytes .../progress_bg_buddhism.9.png | Bin 0 -> 156 bytes .../progress_primary_buddhism.9.png | Bin 0 -> 1583 bytes .../progress_secondary_buddhism.9.png | Bin 0 -> 157 bytes .../spinner_ab_default_buddhism.9.png | Bin 0 -> 480 bytes .../spinner_ab_disabled_buddhism.9.png | Bin 0 -> 481 bytes .../spinner_ab_focused_buddhism.9.png | Bin 0 -> 819 bytes .../spinner_ab_pressed_buddhism.9.png | Bin 0 -> 744 bytes .../tab_selected_buddhism.9.png | Bin 0 -> 110 bytes .../tab_selected_focused_buddhism.9.png | Bin 0 -> 116 bytes .../tab_selected_pressed_buddhism.9.png | Bin 0 -> 116 bytes .../tab_unselected_buddhism.9.png | Bin 0 -> 110 bytes .../tab_unselected_focused_buddhism.9.png | Bin 0 -> 118 bytes .../tab_unselected_pressed_buddhism.9.png | Bin 0 -> 117 bytes .../res/drawable-xxxhdpi/ic_notification.png | Bin 0 -> 2677 bytes .../ab_background_textured_buddhism.xml | 21 + .../res/drawable/btn_cab_done_buddhism.xml | 27 + ...ddhism_activated_background_holo_light.xml | 20 + .../buddhism_btn_check_holo_light.xml | 65 + .../buddhism_btn_default_holo_light.xml | 32 + .../buddhism_btn_radio_holo_light.xml | 59 + .../buddhism_btn_toggle_holo_light.xml | 50 + .../buddhism_edit_text_holo_light.xml | 25 + .../buddhism_fastscroll_thumb_holo.xml | 20 + .../buddhism_item_background_holo_light.xml | 26 + ...ector_background_transition_holo_light.xml | 20 + .../buddhism_list_selector_holo_light.xml | 28 + ...uddhism_progress_horizontal_holo_light.xml | 32 + ...ss_indeterminate_horizontal_holo_light.xml | 30 + ...buddhism_spinner_background_holo_light.xml | 25 + .../drawable/buddhism_tab_indicator_holo.xml | 34 + .../src/main/res/drawable/charis.png | Bin 0 -> 92735 bytes .../drawable/item_background_holo_dark.xml | 26 + .../drawable/item_background_holo_light.xml | 26 + ...lector_background_transition_holo_dark.xml | 20 + ...ector_background_transition_holo_light.xml | 20 + .../src/main/res/drawable/logo_aol.png | Bin 0 -> 5569 bytes .../src/main/res/drawable/logo_aol_light.png | Bin 0 -> 5093 bytes .../src/main/res/drawable/logo_facebook.png | Bin 0 -> 6821 bytes .../main/res/drawable/logo_facebook_light.png | Bin 0 -> 5816 bytes .../src/main/res/drawable/logo_google.png | Bin 0 -> 37981 bytes .../main/res/drawable/logo_google_light.png | Bin 0 -> 27010 bytes .../src/main/res/drawable/logo_live.png | Bin 0 -> 3993 bytes .../src/main/res/drawable/logo_live_light.png | Bin 0 -> 3498 bytes .../src/main/res/drawable/logo_openid.png | Bin 0 -> 4154 bytes .../main/res/drawable/logo_openid_light.png | Bin 0 -> 3750 bytes .../src/main/res/drawable/logo_twitter.png | Bin 0 -> 5451 bytes .../main/res/drawable/logo_twitter_light.png | Bin 0 -> 4886 bytes .../drawable/progress_horizontal_buddhism.xml | 35 + .../selectable_background_buddhism.xml | 25 + .../spinner_background_ab_buddhism.xml | 28 + .../drawable/tab_indicator_ab_buddhism.xml | 37 + .../src/main/res/layout/activity_about.xml | 160 + .../src/main/res/layout/activity_complete.xml | 173 ++ .../src/main/res/layout/activity_main.xml | 520 ++++ .../src/main/res/layout/activity_medinet.xml | 35 + .../src/main/res/layout/activity_progress.xml | 45 + .../res/layout/activity_sessions_item.xml | 42 + .../layout/buddhism_tab_indicator_holo.xml | 39 + .../res/layout/fragment_progress_stats.xml | 343 +++ .../src/main/res/layout/medinet_signin.xml | 155 + .../number_picker_with_selector_wheel.xml | 32 + .../src/main/res/layout/session_add.xml | 185 ++ .../src/main/res/layout/session_details.xml | 59 + .../src/main/res/layout/set_preset.xml | 52 + .../main/res/layout/time_picker_dialog.xml | 23 + .../src/main/res/layout/time_picker_holo.xml | 87 + .../src/main/res/layout/widget_layout.xml | 37 + .../src/main/res/layout/widget_layout_1.xml | 36 + .../src/main/res/menu/about.xml | 17 + .../src/main/res/menu/complete.xml | 4 + .../src/main/res/menu/main.xml | 10 + .../src/main/res/menu/medinet.xml | 55 + .../src/main/res/menu/progress.xml | 9 + .../src/main/res/menu/settings.xml | 17 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 5875 bytes .../src/main/res/mipmap-ldpi/ic_launcher.png | Bin 0 -> 2250 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 3626 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 9565 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 14972 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 24741 bytes .../src/main/res/raw/bell_indian.mp3 | Bin 0 -> 352522 bytes .../src/main/res/raw/bell_temple.ogg | Bin 0 -> 28334 bytes MeditationAssistant/src/main/res/raw/gong.ogg | Bin 0 -> 60741 bytes .../src/main/res/raw/gong_burmese.mp3 | Bin 0 -> 17208 bytes .../src/main/res/raw/gong_heavy.ogg | Bin 0 -> 22375 bytes .../src/main/res/raw/gong_metal.ogg | Bin 0 -> 48960 bytes .../src/main/res/raw/tinsha.ogg | Bin 0 -> 31280 bytes .../src/main/res/values-ca-rES/strings.xml | 281 ++ .../src/main/res/values-de/strings.xml | 281 ++ .../src/main/res/values-es-rMX/strings.xml | 281 ++ .../src/main/res/values-es/strings.xml | 259 ++ .../src/main/res/values-et/strings.xml | 281 ++ .../src/main/res/values-fr/strings.xml | 281 ++ .../src/main/res/values-he/strings.xml | 281 ++ .../src/main/res/values-it/strings.xml | 282 ++ .../src/main/res/values-iw/strings.xml | 281 ++ .../src/main/res/values-ms/strings.xml | 281 ++ .../src/main/res/values-nl/strings.xml | 281 ++ .../src/main/res/values-pl/strings.xml | 281 ++ .../src/main/res/values-pt-rBR/strings.xml | 290 ++ .../src/main/res/values-pt/strings.xml | 281 ++ .../src/main/res/values-ru/strings.xml | 263 ++ .../src/main/res/values-uk/strings.xml | 259 ++ .../src/main/res/values-w820dp/dimens.xml | 3 + .../src/main/res/values/arrays.xml | 123 + .../src/main/res/values/attrs.xml | 47 + .../src/main/res/values/colors_buddhism.xml | 4 + .../src/main/res/values/dimens.xml | 5 + .../src/main/res/values/dimens_buddhism.xml | 4 + .../src/main/res/values/ids.xml | 11 + .../src/main/res/values/strings.xml | 264 ++ .../src/main/res/values/strings_extra.xml | 28 + .../src/main/res/values/styles.xml | 185 ++ .../src/main/res/values/styles_buddhism.xml | 168 ++ .../main/res/values/styles_numberpicker.xml | 59 + .../src/main/res/values/themes_buddhism.xml | 39 + .../src/main/res/xml/analytics.xml | 13 + .../src/main/res/xml/analytics_tracker.xml | 18 + .../src/main/res/xml/pref_headers.xml | 25 + .../src/main/res/xml/pref_medinet.xml | 60 + .../src/main/res/xml/pref_meditation.xml | 57 + .../src/main/res/xml/pref_miscellaneous.xml | 35 + .../src/main/res/xml/pref_reminder.xml | 38 + .../src/main/res/xml/pref_session.xml | 94 + .../src/main/res/xml/widget_1.xml | 13 + .../src/main/res/xml/widget_2.xml | 13 + .../src/main/res/xml/widget_3.xml | 13 + MeditationAssistantFull/.gitignore | 1 + MeditationAssistantFull/google-services.json | 1 + MeditationAssistantFull/lint.xml | 4 + MeditationAssistantFull/proguard-project.txt | 216 ++ MeditationAssistantFull/proguard-rules.txt | 17 + .../src/main/AndroidManifest.xml | 169 ++ MeditationAssistantWear/.gitignore | 1 + MeditationAssistantWear/build.gradle | 35 + MeditationAssistantWear/lint.xml | 4 + MeditationAssistantWear/proguard-rules.pro | 17 + .../src/main/AndroidManifest.xml | 32 + .../WearEditDurationActivity.java | 45 + .../meditationassistant/WearMainActivity.java | 82 + .../WearMeditationAssistant.java | 7 + .../src/main/res/layout/wear_editduration.xml | 11 + .../res/layout/wear_editduration_rect.xml | 13 + .../res/layout/wear_editduration_round.xml | 12 + .../src/main/res/layout/wear_main.xml | 11 + .../src/main/res/layout/wear_main_rect.xml | 10 + .../src/main/res/layout/wear_main_round.xml | 10 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 5875 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 3626 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 9565 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 14972 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 24741 bytes .../src/main/res/values/strings.xml | 5 + .../src/main/res/values/styles.xml | 14 + build.gradle | 20 + gradle.properties | 16 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 49896 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 164 + gradlew.bat | 90 + settings.gradle | 1 + 869 files changed, 24998 insertions(+) create mode 100644 .gitignore create mode 100644 MeditationAssistant/.gitignore create mode 100644 MeditationAssistant/google-services.json create mode 100644 MeditationAssistant/lint.xml create mode 100644 MeditationAssistant/proguard-project.txt create mode 100644 MeditationAssistant/src/main/AndroidManifest.xml create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/AboutActivity.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/CalendarFragment.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/CompleteActivity.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/Crypt.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/DailyNotification.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/DatabaseHandler.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/FadeOutAnimationListener.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/FileUtils.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/JavaScriptInterface.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/JavascriptCallback.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/ListPreferenceSound.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MainActivity.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MediNET.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MediNETActivity.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MediNETTask.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MeditationAssistant.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MeditationProvider.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MeditationProvider1.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MeditationProvider2.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MeditationProvider3.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MeditationService.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MeditationSession.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MeditationSounds.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MonthAdapter.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MonthAdapterMA.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/NumToWord.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/NumberPicker.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/Preset.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/ProgressActivity.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/Scroller.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/SessionAdapter.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/SessionSQL.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/SessionsFragment.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/SettingsActivity.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/StatsFragment.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/TimePicker.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/TimePickerDialog.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/TimePreference.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/WakeLocker.java create mode 100644 MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/WearListenerService.java create mode 100644 MeditationAssistant/src/main/res/anim/fadeinma.xml create mode 100644 MeditationAssistant/src/main/res/anim/fadeoutma.xml create mode 100644 MeditationAssistant/src/main/res/anim/spin.xml create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ab_bottom_solid_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ab_solid_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ab_stacked_solid_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ab_texture_tile_buddhism.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ab_transparent_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/btn_cab_done_default_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/btn_cab_done_focused_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/btn_cab_done_pressed_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_check_off_disabled_focused_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_check_off_disabled_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_check_off_focused_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_check_off_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_check_off_pressed_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_check_on_disabled_focused_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_check_on_disabled_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_check_on_focused_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_check_on_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_check_on_pressed_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_default_disabled_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_default_disabled_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_default_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_default_normal_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_default_pressed_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_radio_off_disabled_focused_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_radio_off_disabled_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_radio_off_focused_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_radio_off_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_radio_off_pressed_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_radio_on_disabled_focused_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_radio_on_disabled_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_radio_on_focused_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_radio_on_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_radio_on_pressed_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_toggle_off_disabled_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_toggle_off_disabled_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_toggle_off_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_toggle_off_normal_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_toggle_off_pressed_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_toggle_on_disabled_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_toggle_on_disabled_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_toggle_on_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_toggle_on_normal_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_toggle_on_pressed_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_fastscroll_thumb_default_holo.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_fastscroll_thumb_pressed_holo.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_ic_navigation_drawer.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_list_activated_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_list_focused_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_list_longpressed_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_list_pressed_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_list_selector_disabled_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_progress_bg_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_progress_primary_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_progress_secondary_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_progressbar_indeterminate_holo1.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_progressbar_indeterminate_holo2.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_progressbar_indeterminate_holo3.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_progressbar_indeterminate_holo4.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_progressbar_indeterminate_holo5.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_progressbar_indeterminate_holo6.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_progressbar_indeterminate_holo7.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_progressbar_indeterminate_holo8.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_spinner_default_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_spinner_disabled_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_spinner_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_spinner_pressed_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_tab_selected_focused_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_tab_selected_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_tab_selected_pressed_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_tab_unselected_focused_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_tab_unselected_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_tab_unselected_pressed_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_text_select_handle_left.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_text_select_handle_middle.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_text_select_handle_right.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_textfield_activated_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_textfield_default_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_textfield_disabled_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_textfield_disabled_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/buddhism_textfield_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/cab_background_bottom_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/cab_background_top_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_accounts.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_accounts_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_brightness_low.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_brightness_low_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_chat.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_chat_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_downcloud.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_downcloud_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_flash_on.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_flash_on_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_forward.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_forward_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_full_screen.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_full_screen_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_go_to_today.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_go_to_today_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_group.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_group_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_info.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_info_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_network_cell.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_network_cell_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_new.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_new_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_next_item.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_next_item_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_not_important.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_not_important_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_pause.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_person.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_person_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_previous_item.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_previous_item_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_refresh.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_refresh_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_ring_volume.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_ring_volume_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_settings.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_settings_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_share.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_share_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_sign_out.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_sign_out_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_sort_by_size.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_sort_by_size_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_stop.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_time.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_time_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_upcloud.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_upcloud_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_view_as_list.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_view_as_list_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_volume_on.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_volume_on_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_website.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_action_website_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/ic_notification.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/list_focused_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/list_focused_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/list_longpressed_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/list_pressed_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/list_pressed_holo_dark.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/list_pressed_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/list_selector_disabled_holo_dark.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/list_selector_disabled_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/menu_dropdown_panel_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/np_numberpicker_selection_divider.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/progress_bg_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/progress_primary_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/progress_secondary_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/spinner_ab_default_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/spinner_ab_disabled_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/spinner_ab_focused_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/spinner_ab_pressed_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/tab_selected_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/tab_selected_focused_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/tab_selected_pressed_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/tab_unselected_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/tab_unselected_focused_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-hdpi/tab_unselected_pressed_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_accounts.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_accounts_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_brightness_low.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_brightness_low_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_chat.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_chat_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_downcloud.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_downcloud_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_flash_on.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_flash_on_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_forward.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_forward_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_full_screen.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_full_screen_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_go_to_today.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_go_to_today_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_group.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_group_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_info.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_info_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_network_cell.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_network_cell_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_new.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_new_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_next_item.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_next_item_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_not_important.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_not_important_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_pause.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_person.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_person_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_previous_item.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_previous_item_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_refresh.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_refresh_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_ring_volume.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_ring_volume_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_settings.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_settings_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_share.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_share_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_sign_out.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_sign_out_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_sort_by_size.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_sort_by_size_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_stop.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_time.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_time_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_upcloud.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_upcloud_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_view_as_list.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_view_as_list_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_volume_on.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_volume_on_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_website.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_action_website_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-ldpi/ic_notification.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ab_bottom_solid_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ab_solid_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ab_stacked_solid_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ab_texture_tile_buddhism.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ab_transparent_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/btn_cab_done_default_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/btn_cab_done_focused_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/btn_cab_done_pressed_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_check_off_disabled_focused_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_check_off_disabled_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_check_off_focused_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_check_off_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_check_off_pressed_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_check_on_disabled_focused_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_check_on_disabled_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_check_on_focused_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_check_on_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_check_on_pressed_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_default_disabled_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_default_disabled_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_default_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_default_normal_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_default_pressed_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_radio_off_disabled_focused_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_radio_off_disabled_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_radio_off_focused_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_radio_off_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_radio_off_pressed_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_radio_on_disabled_focused_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_radio_on_disabled_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_radio_on_focused_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_radio_on_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_radio_on_pressed_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_toggle_off_disabled_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_toggle_off_disabled_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_toggle_off_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_toggle_off_normal_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_toggle_off_pressed_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_toggle_on_disabled_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_toggle_on_disabled_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_toggle_on_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_toggle_on_normal_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_toggle_on_pressed_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_fastscroll_thumb_default_holo.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_fastscroll_thumb_pressed_holo.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_ic_navigation_drawer.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_list_activated_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_list_focused_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_list_longpressed_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_list_pressed_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_list_selector_disabled_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_progress_bg_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_progress_primary_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_progress_secondary_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_progressbar_indeterminate_holo1.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_progressbar_indeterminate_holo2.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_progressbar_indeterminate_holo3.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_progressbar_indeterminate_holo4.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_progressbar_indeterminate_holo5.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_progressbar_indeterminate_holo6.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_progressbar_indeterminate_holo7.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_progressbar_indeterminate_holo8.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_spinner_default_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_spinner_disabled_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_spinner_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_spinner_pressed_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_tab_selected_focused_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_tab_selected_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_tab_selected_pressed_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_tab_unselected_focused_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_tab_unselected_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_tab_unselected_pressed_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_text_select_handle_left.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_text_select_handle_middle.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_text_select_handle_right.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_textfield_activated_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_textfield_default_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_textfield_disabled_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_textfield_disabled_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/buddhism_textfield_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/cab_background_bottom_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/cab_background_top_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_accounts.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_accounts_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_brightness_low.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_brightness_low_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_chat.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_chat_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_downcloud.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_downcloud_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_flash_on.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_flash_on_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_forward.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_forward_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_full_screen.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_full_screen_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_go_to_today.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_go_to_today_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_group.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_group_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_info.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_info_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_network_cell.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_network_cell_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_new.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_new_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_next_item.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_next_item_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_not_important.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_not_important_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_pause.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_person.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_person_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_previous_item.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_previous_item_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_refresh.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_refresh_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_ring_volume.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_ring_volume_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_settings.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_settings_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_share.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_share_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_sign_out.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_sign_out_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_sort_by_size.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_sort_by_size_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_stop.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_time.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_time_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_upcloud.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_upcloud_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_view_as_list.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_view_as_list_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_volume_on.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_volume_on_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_website.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_action_website_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/ic_notification.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/list_focused_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/list_focused_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/list_longpressed_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/list_pressed_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/list_pressed_holo_dark.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/list_pressed_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/list_selector_disabled_holo_dark.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/list_selector_disabled_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/menu_dropdown_panel_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/np_numberpicker_selection_divider.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/progress_bg_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/progress_primary_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/progress_secondary_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/spinner_ab_default_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/spinner_ab_disabled_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/spinner_ab_focused_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/spinner_ab_pressed_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/tab_selected_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/tab_selected_focused_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/tab_selected_pressed_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/tab_unselected_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/tab_unselected_focused_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-mdpi/tab_unselected_pressed_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/.directory create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ab_bottom_solid_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ab_solid_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ab_stacked_solid_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ab_texture_tile_buddhism.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ab_transparent_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/btn_cab_done_default_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/btn_cab_done_focused_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/btn_cab_done_pressed_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_check_off_disabled_focused_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_check_off_disabled_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_check_off_focused_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_check_off_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_check_off_pressed_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_check_on_disabled_focused_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_check_on_disabled_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_check_on_focused_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_check_on_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_check_on_pressed_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_default_disabled_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_default_disabled_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_default_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_default_normal_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_default_pressed_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_radio_off_disabled_focused_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_radio_off_disabled_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_radio_off_focused_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_radio_off_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_radio_off_pressed_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_radio_on_disabled_focused_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_radio_on_disabled_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_radio_on_focused_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_radio_on_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_radio_on_pressed_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_toggle_off_disabled_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_toggle_off_disabled_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_toggle_off_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_toggle_off_normal_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_toggle_off_pressed_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_toggle_on_disabled_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_toggle_on_disabled_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_toggle_on_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_toggle_on_normal_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_btn_toggle_on_pressed_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_fastscroll_thumb_default_holo.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_fastscroll_thumb_pressed_holo.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_ic_navigation_drawer.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_list_activated_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_list_focused_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_list_longpressed_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_list_pressed_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_list_selector_disabled_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_progress_bg_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_progress_primary_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_progress_secondary_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_progressbar_indeterminate_holo1.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_progressbar_indeterminate_holo2.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_progressbar_indeterminate_holo3.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_progressbar_indeterminate_holo4.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_progressbar_indeterminate_holo5.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_progressbar_indeterminate_holo6.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_progressbar_indeterminate_holo7.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_progressbar_indeterminate_holo8.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_spinner_default_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_spinner_disabled_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_spinner_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_spinner_pressed_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_tab_selected_focused_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_tab_selected_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_tab_selected_pressed_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_tab_unselected_focused_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_tab_unselected_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_tab_unselected_pressed_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_text_select_handle_left.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_text_select_handle_middle.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_text_select_handle_right.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_textfield_activated_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_textfield_default_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_textfield_disabled_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_textfield_disabled_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/buddhism_textfield_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/cab_background_bottom_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/cab_background_top_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_accounts.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_accounts_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_brightness_low.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_brightness_low_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_chat.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_chat_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_downcloud.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_downcloud_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_flash_on.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_flash_on_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_forward.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_forward_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_full_screen.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_full_screen_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_go_to_today.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_go_to_today_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_group.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_group_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_info.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_info_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_network_cell.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_network_cell_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_new.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_new_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_next_item.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_next_item_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_not_important.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_not_important_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_pause.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_person.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_person_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_previous_item.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_previous_item_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_refresh.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_refresh_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_ring_volume.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_ring_volume_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_settings.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_settings_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_share.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_share_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_sign_out.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_sign_out_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_sort_by_size.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_sort_by_size_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_stop.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_time.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_time_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_upcloud.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_upcloud_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_view_as_list.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_view_as_list_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_volume_on.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_volume_on_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_website.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_action_website_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/ic_notification.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/list_focused_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/list_focused_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/list_longpressed_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/list_pressed_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/list_pressed_holo_dark.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/list_pressed_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/list_selector_disabled_holo_dark.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/list_selector_disabled_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/menu_dropdown_panel_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/np_numberpicker_selection_divider.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/progress_bg_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/progress_primary_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/progress_secondary_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/spinner_ab_default_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/spinner_ab_disabled_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/spinner_ab_focused_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/spinner_ab_pressed_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/tab_selected_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/tab_selected_focused_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/tab_selected_pressed_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/tab_unselected_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/tab_unselected_focused_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xhdpi/tab_unselected_pressed_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ab_bottom_solid_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ab_solid_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ab_stacked_solid_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ab_texture_tile_buddhism.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ab_transparent_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/btn_cab_done_default_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/btn_cab_done_focused_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/btn_cab_done_pressed_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_check_off_disabled_focused_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_check_off_disabled_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_check_off_focused_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_check_off_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_check_off_pressed_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_check_on_disabled_focused_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_check_on_disabled_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_check_on_focused_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_check_on_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_check_on_pressed_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_default_disabled_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_default_disabled_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_default_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_default_normal_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_default_pressed_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_radio_off_disabled_focused_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_radio_off_disabled_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_radio_off_focused_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_radio_off_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_radio_off_pressed_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_radio_on_disabled_focused_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_radio_on_disabled_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_radio_on_focused_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_radio_on_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_radio_on_pressed_holo_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_toggle_off_disabled_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_toggle_off_disabled_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_toggle_off_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_toggle_off_normal_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_toggle_off_pressed_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_toggle_on_disabled_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_toggle_on_disabled_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_toggle_on_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_toggle_on_normal_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_btn_toggle_on_pressed_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_fastscroll_thumb_default_holo.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_fastscroll_thumb_pressed_holo.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_ic_navigation_drawer.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_list_activated_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_list_focused_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_list_longpressed_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_list_pressed_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_list_selector_disabled_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_progress_bg_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_progress_primary_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_progress_secondary_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_progressbar_indeterminate_holo1.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_progressbar_indeterminate_holo2.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_progressbar_indeterminate_holo3.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_progressbar_indeterminate_holo4.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_progressbar_indeterminate_holo5.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_progressbar_indeterminate_holo6.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_progressbar_indeterminate_holo7.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_progressbar_indeterminate_holo8.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_spinner_default_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_spinner_disabled_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_spinner_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_spinner_pressed_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_tab_selected_focused_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_tab_selected_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_tab_selected_pressed_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_tab_unselected_focused_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_tab_unselected_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_tab_unselected_pressed_holo.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_text_select_handle_left.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_text_select_handle_middle.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_text_select_handle_right.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_textfield_activated_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_textfield_default_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_textfield_disabled_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_textfield_disabled_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/buddhism_textfield_focused_holo_light.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/cab_background_bottom_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/cab_background_top_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ic_action_brightness_low.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ic_action_brightness_low_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ic_action_flash_on.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ic_action_flash_on_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ic_action_full_screen.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ic_action_full_screen_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ic_action_info.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ic_action_info_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ic_action_new.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ic_action_new_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ic_action_not_important.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ic_action_not_important_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ic_action_person.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ic_action_person_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ic_action_refresh.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ic_action_refresh_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ic_action_ring_volume.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ic_action_ring_volume_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ic_action_settings.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ic_action_settings_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ic_action_share.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ic_action_share_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ic_action_sort_by_size.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ic_action_sort_by_size_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ic_action_stop.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ic_action_time.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ic_action_time_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ic_action_volume_on.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ic_action_volume_on_light.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/ic_notification.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/list_focused_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/list_pressed_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/menu_dropdown_panel_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/progress_bg_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/progress_primary_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/progress_secondary_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/spinner_ab_default_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/spinner_ab_disabled_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/spinner_ab_focused_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/spinner_ab_pressed_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/tab_selected_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/tab_selected_focused_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/tab_selected_pressed_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/tab_unselected_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/tab_unselected_focused_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxhdpi/tab_unselected_pressed_buddhism.9.png create mode 100644 MeditationAssistant/src/main/res/drawable-xxxhdpi/ic_notification.png create mode 100644 MeditationAssistant/src/main/res/drawable/ab_background_textured_buddhism.xml create mode 100644 MeditationAssistant/src/main/res/drawable/btn_cab_done_buddhism.xml create mode 100644 MeditationAssistant/src/main/res/drawable/buddhism_activated_background_holo_light.xml create mode 100644 MeditationAssistant/src/main/res/drawable/buddhism_btn_check_holo_light.xml create mode 100644 MeditationAssistant/src/main/res/drawable/buddhism_btn_default_holo_light.xml create mode 100644 MeditationAssistant/src/main/res/drawable/buddhism_btn_radio_holo_light.xml create mode 100644 MeditationAssistant/src/main/res/drawable/buddhism_btn_toggle_holo_light.xml create mode 100644 MeditationAssistant/src/main/res/drawable/buddhism_edit_text_holo_light.xml create mode 100644 MeditationAssistant/src/main/res/drawable/buddhism_fastscroll_thumb_holo.xml create mode 100644 MeditationAssistant/src/main/res/drawable/buddhism_item_background_holo_light.xml create mode 100644 MeditationAssistant/src/main/res/drawable/buddhism_list_selector_background_transition_holo_light.xml create mode 100644 MeditationAssistant/src/main/res/drawable/buddhism_list_selector_holo_light.xml create mode 100644 MeditationAssistant/src/main/res/drawable/buddhism_progress_horizontal_holo_light.xml create mode 100644 MeditationAssistant/src/main/res/drawable/buddhism_progress_indeterminate_horizontal_holo_light.xml create mode 100644 MeditationAssistant/src/main/res/drawable/buddhism_spinner_background_holo_light.xml create mode 100644 MeditationAssistant/src/main/res/drawable/buddhism_tab_indicator_holo.xml create mode 100644 MeditationAssistant/src/main/res/drawable/charis.png create mode 100644 MeditationAssistant/src/main/res/drawable/item_background_holo_dark.xml create mode 100644 MeditationAssistant/src/main/res/drawable/item_background_holo_light.xml create mode 100644 MeditationAssistant/src/main/res/drawable/list_selector_background_transition_holo_dark.xml create mode 100644 MeditationAssistant/src/main/res/drawable/list_selector_background_transition_holo_light.xml create mode 100644 MeditationAssistant/src/main/res/drawable/logo_aol.png create mode 100644 MeditationAssistant/src/main/res/drawable/logo_aol_light.png create mode 100644 MeditationAssistant/src/main/res/drawable/logo_facebook.png create mode 100644 MeditationAssistant/src/main/res/drawable/logo_facebook_light.png create mode 100644 MeditationAssistant/src/main/res/drawable/logo_google.png create mode 100644 MeditationAssistant/src/main/res/drawable/logo_google_light.png create mode 100644 MeditationAssistant/src/main/res/drawable/logo_live.png create mode 100644 MeditationAssistant/src/main/res/drawable/logo_live_light.png create mode 100644 MeditationAssistant/src/main/res/drawable/logo_openid.png create mode 100644 MeditationAssistant/src/main/res/drawable/logo_openid_light.png create mode 100644 MeditationAssistant/src/main/res/drawable/logo_twitter.png create mode 100644 MeditationAssistant/src/main/res/drawable/logo_twitter_light.png create mode 100644 MeditationAssistant/src/main/res/drawable/progress_horizontal_buddhism.xml create mode 100644 MeditationAssistant/src/main/res/drawable/selectable_background_buddhism.xml create mode 100644 MeditationAssistant/src/main/res/drawable/spinner_background_ab_buddhism.xml create mode 100644 MeditationAssistant/src/main/res/drawable/tab_indicator_ab_buddhism.xml create mode 100644 MeditationAssistant/src/main/res/layout/activity_about.xml create mode 100644 MeditationAssistant/src/main/res/layout/activity_complete.xml create mode 100644 MeditationAssistant/src/main/res/layout/activity_main.xml create mode 100644 MeditationAssistant/src/main/res/layout/activity_medinet.xml create mode 100644 MeditationAssistant/src/main/res/layout/activity_progress.xml create mode 100644 MeditationAssistant/src/main/res/layout/activity_sessions_item.xml create mode 100644 MeditationAssistant/src/main/res/layout/buddhism_tab_indicator_holo.xml create mode 100644 MeditationAssistant/src/main/res/layout/fragment_progress_stats.xml create mode 100644 MeditationAssistant/src/main/res/layout/medinet_signin.xml create mode 100644 MeditationAssistant/src/main/res/layout/number_picker_with_selector_wheel.xml create mode 100644 MeditationAssistant/src/main/res/layout/session_add.xml create mode 100644 MeditationAssistant/src/main/res/layout/session_details.xml create mode 100644 MeditationAssistant/src/main/res/layout/set_preset.xml create mode 100644 MeditationAssistant/src/main/res/layout/time_picker_dialog.xml create mode 100644 MeditationAssistant/src/main/res/layout/time_picker_holo.xml create mode 100644 MeditationAssistant/src/main/res/layout/widget_layout.xml create mode 100644 MeditationAssistant/src/main/res/layout/widget_layout_1.xml create mode 100644 MeditationAssistant/src/main/res/menu/about.xml create mode 100644 MeditationAssistant/src/main/res/menu/complete.xml create mode 100644 MeditationAssistant/src/main/res/menu/main.xml create mode 100644 MeditationAssistant/src/main/res/menu/medinet.xml create mode 100644 MeditationAssistant/src/main/res/menu/progress.xml create mode 100644 MeditationAssistant/src/main/res/menu/settings.xml create mode 100644 MeditationAssistant/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 MeditationAssistant/src/main/res/mipmap-ldpi/ic_launcher.png create mode 100644 MeditationAssistant/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 MeditationAssistant/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 MeditationAssistant/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 MeditationAssistant/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 MeditationAssistant/src/main/res/raw/bell_indian.mp3 create mode 100644 MeditationAssistant/src/main/res/raw/bell_temple.ogg create mode 100644 MeditationAssistant/src/main/res/raw/gong.ogg create mode 100644 MeditationAssistant/src/main/res/raw/gong_burmese.mp3 create mode 100644 MeditationAssistant/src/main/res/raw/gong_heavy.ogg create mode 100644 MeditationAssistant/src/main/res/raw/gong_metal.ogg create mode 100644 MeditationAssistant/src/main/res/raw/tinsha.ogg create mode 100644 MeditationAssistant/src/main/res/values-ca-rES/strings.xml create mode 100644 MeditationAssistant/src/main/res/values-de/strings.xml create mode 100644 MeditationAssistant/src/main/res/values-es-rMX/strings.xml create mode 100644 MeditationAssistant/src/main/res/values-es/strings.xml create mode 100644 MeditationAssistant/src/main/res/values-et/strings.xml create mode 100644 MeditationAssistant/src/main/res/values-fr/strings.xml create mode 100644 MeditationAssistant/src/main/res/values-he/strings.xml create mode 100644 MeditationAssistant/src/main/res/values-it/strings.xml create mode 100644 MeditationAssistant/src/main/res/values-iw/strings.xml create mode 100644 MeditationAssistant/src/main/res/values-ms/strings.xml create mode 100644 MeditationAssistant/src/main/res/values-nl/strings.xml create mode 100644 MeditationAssistant/src/main/res/values-pl/strings.xml create mode 100644 MeditationAssistant/src/main/res/values-pt-rBR/strings.xml create mode 100644 MeditationAssistant/src/main/res/values-pt/strings.xml create mode 100644 MeditationAssistant/src/main/res/values-ru/strings.xml create mode 100644 MeditationAssistant/src/main/res/values-uk/strings.xml create mode 100644 MeditationAssistant/src/main/res/values-w820dp/dimens.xml create mode 100644 MeditationAssistant/src/main/res/values/arrays.xml create mode 100644 MeditationAssistant/src/main/res/values/attrs.xml create mode 100644 MeditationAssistant/src/main/res/values/colors_buddhism.xml create mode 100644 MeditationAssistant/src/main/res/values/dimens.xml create mode 100644 MeditationAssistant/src/main/res/values/dimens_buddhism.xml create mode 100644 MeditationAssistant/src/main/res/values/ids.xml create mode 100644 MeditationAssistant/src/main/res/values/strings.xml create mode 100644 MeditationAssistant/src/main/res/values/strings_extra.xml create mode 100644 MeditationAssistant/src/main/res/values/styles.xml create mode 100644 MeditationAssistant/src/main/res/values/styles_buddhism.xml create mode 100644 MeditationAssistant/src/main/res/values/styles_numberpicker.xml create mode 100644 MeditationAssistant/src/main/res/values/themes_buddhism.xml create mode 100644 MeditationAssistant/src/main/res/xml/analytics.xml create mode 100644 MeditationAssistant/src/main/res/xml/analytics_tracker.xml create mode 100644 MeditationAssistant/src/main/res/xml/pref_headers.xml create mode 100644 MeditationAssistant/src/main/res/xml/pref_medinet.xml create mode 100644 MeditationAssistant/src/main/res/xml/pref_meditation.xml create mode 100644 MeditationAssistant/src/main/res/xml/pref_miscellaneous.xml create mode 100644 MeditationAssistant/src/main/res/xml/pref_reminder.xml create mode 100644 MeditationAssistant/src/main/res/xml/pref_session.xml create mode 100644 MeditationAssistant/src/main/res/xml/widget_1.xml create mode 100644 MeditationAssistant/src/main/res/xml/widget_2.xml create mode 100644 MeditationAssistant/src/main/res/xml/widget_3.xml create mode 100644 MeditationAssistantFull/.gitignore create mode 100644 MeditationAssistantFull/google-services.json create mode 100644 MeditationAssistantFull/lint.xml create mode 100644 MeditationAssistantFull/proguard-project.txt create mode 100644 MeditationAssistantFull/proguard-rules.txt create mode 100644 MeditationAssistantFull/src/main/AndroidManifest.xml create mode 100644 MeditationAssistantWear/.gitignore create mode 100644 MeditationAssistantWear/build.gradle create mode 100644 MeditationAssistantWear/lint.xml create mode 100644 MeditationAssistantWear/proguard-rules.pro create mode 100644 MeditationAssistantWear/src/main/AndroidManifest.xml create mode 100644 MeditationAssistantWear/src/main/java/sh/ftp/rocketninelabs/meditationassistant/WearEditDurationActivity.java create mode 100644 MeditationAssistantWear/src/main/java/sh/ftp/rocketninelabs/meditationassistant/WearMainActivity.java create mode 100644 MeditationAssistantWear/src/main/java/sh/ftp/rocketninelabs/meditationassistant/WearMeditationAssistant.java create mode 100644 MeditationAssistantWear/src/main/res/layout/wear_editduration.xml create mode 100644 MeditationAssistantWear/src/main/res/layout/wear_editduration_rect.xml create mode 100644 MeditationAssistantWear/src/main/res/layout/wear_editduration_round.xml create mode 100644 MeditationAssistantWear/src/main/res/layout/wear_main.xml create mode 100644 MeditationAssistantWear/src/main/res/layout/wear_main_rect.xml create mode 100644 MeditationAssistantWear/src/main/res/layout/wear_main_round.xml create mode 100644 MeditationAssistantWear/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 MeditationAssistantWear/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 MeditationAssistantWear/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 MeditationAssistantWear/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 MeditationAssistantWear/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 MeditationAssistantWear/src/main/res/values/strings.xml create mode 100644 MeditationAssistantWear/src/main/res/values/styles.xml create mode 100644 build.gradle create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4edfb05 --- /dev/null +++ b/.gitignore @@ -0,0 +1,42 @@ +build/ +captures/ +*/captures/ + +# built application files +*.apk +*.ap_ +*.bar +*.wrn + + +# files for the dex VM +*.dex + +# Java class files +*.class + +# generated files +bin/ +gen/ + +# Local configuration file (sdk path, etc) +local.properties + +# Eclipse project files +.classpath +.project + +# Android Studio +.idea/ +.gradle +/*/local.properties +/*/out +/*/*/build +*/build +/*/*/production +*.iml +*.iws +*.ipr +*~ +*.swp + diff --git a/MeditationAssistant/.gitignore b/MeditationAssistant/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/MeditationAssistant/.gitignore @@ -0,0 +1 @@ +/build diff --git a/MeditationAssistant/google-services.json b/MeditationAssistant/google-services.json new file mode 100644 index 0000000..e1a464f --- /dev/null +++ b/MeditationAssistant/google-services.json @@ -0,0 +1 @@ +{"project_info":{"project_id":"api-project-163346957857","project_number":"163346957857","name":"Meditation Assistant Free"},"client":[{"client_info":{"client_id":"android:sh.ftp.rocketninelabs.meditationassistant","client_type":1,"android_client_info":{"package_name":"sh.ftp.rocketninelabs.meditationassistant"}},"oauth_client":[{"client_id":"163346957857.apps.googleusercontent.com","client_type":1,"android_info":{"package_name":"sh.ftp.rocketninelabs.meditationassistant","certificate_hash":"f5f29854d4bac9d7ccf5d98a8a4b88f3beca47ff"}}],"services":{"analytics_service":{"status":2,"analytics_property":{"tracking_id":"UA-71983-51"}},"cloud_messaging_service":{"status":1,"apns_config":[]},"appinvite_service":{"status":2,"other_platform_oauth_client":[]},"google_signin_service":{"status":2},"ads_service":{"status":1}}}],"ARTIFACT_VERSION":"1"} \ No newline at end of file diff --git a/MeditationAssistant/lint.xml b/MeditationAssistant/lint.xml new file mode 100644 index 0000000..287f5a2 --- /dev/null +++ b/MeditationAssistant/lint.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/MeditationAssistant/proguard-project.txt b/MeditationAssistant/proguard-project.txt new file mode 100644 index 0000000..f46bf01 --- /dev/null +++ b/MeditationAssistant/proguard-project.txt @@ -0,0 +1,216 @@ +-verbose + +# Begin optimizeproguard-optimize.txt: + +-optimizations !code/simplification/cast,!field/*,!class/merging/* +-optimizationpasses 25 +-allowaccessmodification +-dontpreverify + +-dontwarn android.webkit.** + +-keep class com.google.android.gms.analytics.** +-keep class com.google.analytics.tracking.** +-dontwarn com.google.android.gms.analytics.** +-dontwarn com.google.analytics.tracking.** + +-dontwarn com.google.android.gms.** + +-keep class android.support.** { *; } + +-keep interface android.support.** { *; } + +-keep class com.actionbarsherlock.** { *; } + +-keep interface com.actionbarsherlock.** { *; } + +-keep class com.actionbarsherlock.** {*;} +-keep class org.holoeverywhere.** {*;} + +-keep class * extends java.util.ListResourceBundle { + protected Object[][] getContents(); +} + +-keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable { + public static final *** NULL; +} + +-keepnames @com.google.android.gms.common.annotation.KeepName class * +-keepclassmembernames class * { + @com.google.android.gms.common.annotation.KeepName *; +} + +-keepnames class * implements android.os.Parcelable { + public static final ** CREATOR; +} +-keepclassmembers class * extends com.actionbarsherlock.ActionBarSherlock { + (android.app.Activity, int); +} + + + +# Keep line numbers to alleviate debugging stack traces + +# -renamesourcefileattribute SourceFile + +-keepattributes SourceFile,LineNumberTable + +# The remainder of this file is identical to the non-optimized version +# of the Proguard configuration file (except that the other file has +# flags to turn off optimization). + +-dontusemixedcaseclassnames +-dontskipnonpubliclibraryclasses + +-keepattributes *Annotation* +-keep public class com.google.vending.licensing.ILicensingService +-keep public class com.android.vending.licensing.ILicensingService + +# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native +-keepclasseswithmembernames class * { + native ; +} + +# keep setters in Views so that animations can still work. +# see http://proguard.sourceforge.net/manual/examples.html#beans +-keepclassmembers public class * extends android.view.View { + void set*(***); + *** get*(); +} + +# We want to keep methods in Activity that could be used in the XML attribute onClick +-keepclassmembers class * extends android.app.Activity { + public void *(android.view.View); +} + +# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +-keep class * implements android.os.Parcelable { + public static final android.os.Parcelable$Creator *; +} + +-keepclassmembers class **.R$* { + public static ; +} + +# The support library contains references to newer platform versions. +# Don't warn about those in case this app is linking against an older +# platform version. We know about them, and they are safe. +-dontwarn android.support.** + + +# End optimize + + +-keepattributes JavascriptInterface +-overloadaggressively +-allowaccessmodification + +-keep public class sh.ftp.rocketninelabs.meditationassistant.JavascriptCallback +-keep public class * implements sh.ftp.rocketninelabs.meditationassistant.JavascriptCallback +-keepclassmembers class * implements sh.ftp.rocketninelabs.meditationassistant.JavascriptCallback { + ; +} + +-keep class android.support.v4.app.** { *; } +-keep interface android.support.v4.app.** { *; } +-keep class com.actionbarsherlock.** { *; } +-keep interface com.actionbarsherlock.** { *; } + +-keep public class com.crittercism.** +-keepclassmembers public class com.crittercism.* { *; } + +# HoloEverywhere +-keep,allowshrinking,allowoptimization public class * extends ListView + +-keep,allowoptimization class org.holoeverywhere.** { + public *; + protected *; +} + +-keepclasseswithmembernames class org.holoeverywhere.internal.** { + public *; + protected *; +} + +-keepclasseswithmembernames class org.holoeverywhere.internal.AlertController +-keep public class org.holoeverywhere.internal.AlertController.RecycleListView { *; } + +-keep,allowshrinking,allowoptimization class org.holoeverywhere.** { *; } +-keep,allowshrinking,allowoptimization interface org.holoeverywhere.** { *; } + + + + +-keep,allowshrinking,allowoptimization public class * extends android.app.Application +-keep,allowshrinking,allowoptimization public class * extends android.app.Service +-keep,allowshrinking,allowoptimization public class * extends android.content.BroadcastReceiver +-keep,allowshrinking,allowoptimization public class * extends android.content.ContentProvider +-keep,allowshrinking,allowoptimization public class * extends android.app.backup.BackupAgentHelper +-keep,allowshrinking,allowoptimization public class * extends android.preference.Preference +-keep,allowshrinking,allowoptimization public class com.android.vending.licensing.ILicensingService + +-keepclasseswithmembernames class * { + native ; +} + +-keepclasseswithmembers class * { + public (android.content.Context, android.util.AttributeSet); +} + +-keepclasseswithmembers class * { + public (android.content.Context, android.util.AttributeSet, int); +} + +-keepclassmembers class * extends android.app.Activity { + public void *(android.view.View); +} + +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +-keep class * implements android.os.Parcelable { + public static final android.os.Parcelable$Creator *; +} + +-keep,allowshrinking,allowoptimization class * { ; } + +-keepclasseswithmembernames,allowshrinking class * { + native ; +} + +-keepclasseswithmembers,allowshrinking class * { + public (android.content.Context,android.util.AttributeSet); + public (android.content.Context,android.util.AttributeSet,int); +} + +-keepclassmembers class * { + public (android.content.Context,android.util.AttributeSet); + public (android.content.Context,android.util.AttributeSet,int); +} + + + +# Google API Client + +-keepattributes Signature,RuntimeVisibleAnnotations,AnnotationDefault + +-keepclassmembers class * { + @com.google.api.client.util.Key ; +} + +# Needed by google-http-client-android when linking against an older platform version + +-dontwarn com.google.api.client.extensions.android.** + +# Needed by google-api-client-android when linking against an older platform version + +-dontwarn com.google.api.client.googleapis.extensions.android.** + +# End Google API Client \ No newline at end of file diff --git a/MeditationAssistant/src/main/AndroidManifest.xml b/MeditationAssistant/src/main/AndroidManifest.xml new file mode 100644 index 0000000..ce97886 --- /dev/null +++ b/MeditationAssistant/src/main/AndroidManifest.xml @@ -0,0 +1,187 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/AboutActivity.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/AboutActivity.java new file mode 100644 index 0000000..f2fc714 --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/AboutActivity.java @@ -0,0 +1,157 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +import android.app.Activity; +import android.content.Intent; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.Bundle; +import android.support.v4.app.NavUtils; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.animation.AnimationUtils; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.google.android.gms.analytics.GoogleAnalytics; +import com.google.android.gms.appinvite.AppInviteInvitation; + +public class AboutActivity extends Activity { + + public String license = ""; + private MeditationAssistant ma = null; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setTheme(getMeditationAssistant().getMATheme()); + getActionBar().setDisplayHomeAsUpEnabled(true); + setContentView(R.layout.activity_about); + + TextView txtAboutAppName = (TextView) findViewById(R.id.txtAboutAppName); + TextView txtAboutAppVersion = (TextView) findViewById(R.id.txtAboutAppVersion); + + if (getPackageName().equals( + "sh.ftp.rocketninelabs.meditationassistant")) { + txtAboutAppName.setText(getString(R.string.appName)); + } else { + txtAboutAppName.setText(getString(R.string.appNameShort)); + } + + PackageInfo pInfo; + try { + pInfo = getPackageManager().getPackageInfo(getPackageName(), 0); + txtAboutAppVersion.setText(String.format(getString(R.string.version), pInfo.versionName)); + } catch (PackageManager.NameNotFoundException e) { + txtAboutAppVersion.setVisibility(View.GONE); + e.printStackTrace(); + } + + LinearLayout layAbout = (LinearLayout) findViewById(R.id.layAbout); + layAbout.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View arg0) { + ImageView charis = (ImageView) findViewById(R.id.charis); + charis.setVisibility(View.VISIBLE); + charis.startAnimation(AnimationUtils.loadAnimation( + getApplicationContext(), R.anim.spin)); + return true; + } + }); + + if (getMeditationAssistant().sendUsageReports()) { + getMeditationAssistant().getTracker(MeditationAssistant.TrackerName.APP_TRACKER); + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.about, menu); + + if (getMeditationAssistant().getIsBB() || !MeditationAssistant.getMarketName().equals("google")) { + MenuItem share = menu.findItem(R.id.action_share_app); + share.setVisible(false); + invalidateOptionsMenu(); + } + + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + int i = item.getItemId(); + if (i == android.R.id.home) { + NavUtils.navigateUpFromSameTask(this); + return true; + } else if (i == R.id.action_share_app) { + Intent intent = new AppInviteInvitation.IntentBuilder(getString(R.string.appNameShort)) + .setMessage(getString(R.string.invitationBlurb)) + .build(); + startActivityForResult(intent, 1337); + } else if (i == R.id.action_rate) { + getMeditationAssistant().askToRateApp(); + return true; + } + + return super.onOptionsItemSelected(item); + } + + @Override + public void onStart() { + super.onStart(); + if (getMeditationAssistant().sendUsageReports()) { + GoogleAnalytics.getInstance(this).reportActivityStart(this); + } + } + + @Override + protected void onStop() { + super.onStop(); + if (getMeditationAssistant().sendUsageReports()) { + GoogleAnalytics.getInstance(this).reportActivityStop(this); + } + } + + public void sendMeEmail(View view) { + Log.d("MeditationAssistant", "Open about"); + Intent intent = new Intent(Intent.ACTION_SEND); + intent.setType("plain/text"); + intent.putExtra(Intent.EXTRA_EMAIL, + new String[]{"tslocum@gmail.com"}); + try { + PackageInfo pInfo = getPackageManager().getPackageInfo( + getPackageName(), 0); + intent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.appNameShort) + " " + + pInfo.versionName); + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + intent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.appNameShort)); + } + intent.putExtra(android.content.Intent.EXTRA_TEXT, ""); + + startActivity(Intent.createChooser(intent, getString(R.string.sendEmail))); + } + + public void openHowToMeditate(View view) { + startActivity(new Intent( + Intent.ACTION_VIEW, + Uri.parse("http://medinet.ftp.sh/howtomeditate")).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); + } + + public void openTranslate(View view) { + startActivity(new Intent( + Intent.ACTION_VIEW, + Uri.parse("http://medinet.ftp.sh/translate")).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); + } + + public MeditationAssistant getMeditationAssistant() { + if (ma == null) { + ma = (MeditationAssistant) this.getApplication(); + } + return ma; + } +} diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/CalendarFragment.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/CalendarFragment.java new file mode 100644 index 0000000..a2a4b1c --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/CalendarFragment.java @@ -0,0 +1,304 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +import android.content.Context; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.text.TextUtils; +import android.util.DisplayMetrics; +import android.util.Log; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; +import android.widget.GridView; +import android.widget.ImageButton; +import android.widget.LinearLayout; +import android.widget.TableLayout; +import android.widget.TextView; + +import java.util.Calendar; +import java.util.Locale; + +public class CalendarFragment extends Fragment { + GridView gridCalendar = null; + TextView txtCurrentMonth = null; + TextView txtCurrentYear = null; + MonthAdapter monthadapter = null; + Calendar mCalendar = null; + ImageButton nextMonth = null; + private MeditationAssistant ma = null; + SharedPreferences.OnSharedPreferenceChangeListener sharedPrefslistener = new SharedPreferences.OnSharedPreferenceChangeListener() { + public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { + if (key.equals("sessionsupdate")) { + Log.d("MeditationAssistant", "Got sessions update, refreshing CalendarFragment"); + refreshMonthDisplay(); + } + } + }; + + public MeditationAssistant getMeditationAssistant() { + if (ma == null) { + ma = (MeditationAssistant) getActivity().getApplication(); + } + return ma; + } + + private MonthAdapter getMonthAdapter() { + final DisplayMetrics metrics = new DisplayMetrics(); + getActivity().getWindowManager().getDefaultDisplay() + .getMetrics(metrics); + updatecurrentDate(); + + return new MonthAdapter(getActivity(), mCalendar.get(Calendar.MONTH), + mCalendar.get(Calendar.YEAR), metrics, (ProgressActivity) getActivity(), getMeditationAssistant()); + } + + public void refreshMonthDisplay() { + gridCalendar.setAdapter(getMonthAdapter()); + } + + @SuppressWarnings("deprecation") + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getMeditationAssistant().getPrefs().registerOnSharedPreferenceChangeListener(sharedPrefslistener); + + int color_primary = getResources().getColor(getMeditationAssistant().getMATextColor(true)); + int color_primary_disabled = getResources().getColor(getMeditationAssistant().getMATextColor(false)); + + /* Getting resource not found errors here */ + try { + color_primary = getResources().getColor( + getMeditationAssistant() + .getTheme() + .obtainStyledAttributes( + getMeditationAssistant().getMATheme(), + new int[]{android.R.attr.textColorPrimary}) + .getResourceId(0, 0) + ); + color_primary_disabled = getResources() + .getColor( + getMeditationAssistant() + .getTheme() + .obtainStyledAttributes( + getMeditationAssistant() + .getMATheme(), + new int[]{android.R.attr.textColorPrimaryDisableOnly} + ) + .getResourceId(0, 0) + ); + } catch (Exception e) { + Log.d("MeditationAssistant", "Unable to get color resources in CalendarFragment:"); + e.printStackTrace(); + } + + txtCurrentMonth = new TextView(getActivity()); + txtCurrentYear = new TextView(getActivity()); + mCalendar = Calendar.getInstance(); + + txtCurrentMonth.setTextSize(22); + txtCurrentYear.setTextSize(12); + + txtCurrentMonth.setTextColor(color_primary); + txtCurrentMonth + .setTextColor(color_primary_disabled); + + txtCurrentMonth.setSingleLine(true); + txtCurrentMonth.setEllipsize(TextUtils.TruncateAt.END); + + txtCurrentYear.setSingleLine(true); + txtCurrentYear.setEllipsize(TextUtils.TruncateAt.END); + + gridCalendar = new GridView(getActivity()); + gridCalendar.setNumColumns(7); + gridCalendar.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, + LayoutParams.FILL_PARENT)); + gridCalendar.setVerticalSpacing(2); + gridCalendar.setHorizontalSpacing(2); + gridCalendar.setAdapter(getMonthAdapter()); + } + + @SuppressWarnings("deprecation") + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + Context ctx = getActivity().getApplicationContext(); + + LinearLayout lcontainer = new LinearLayout(ctx); + lcontainer.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, + LayoutParams.FILL_PARENT)); + lcontainer.setOrientation(LinearLayout.VERTICAL); + + LinearLayout lmain = new LinearLayout(ctx); + lmain.setOrientation(LinearLayout.VERTICAL); + lmain.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, + LayoutParams.FILL_PARENT)); + + lmain.setWeightSum(0.5f); + + LinearLayout lhoriz = new LinearLayout(ctx); + lhoriz.setOrientation(LinearLayout.HORIZONTAL); + lhoriz.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, + LayoutParams.WRAP_CONTENT)); + + lmain.addView(gridCalendar); + + ImageButton prevMonth = new ImageButton(getActivity()); + prevMonth.setImageDrawable(getResources().getDrawable( + getMeditationAssistant() + .getTheme() + .obtainStyledAttributes( + getMeditationAssistant().getMATheme(), + new int[]{R.attr.actionIconPreviousItem}) + .getResourceId(0, 0) + )); + + nextMonth = new ImageButton(getActivity()); + nextMonth.setImageDrawable(getResources().getDrawable( + getMeditationAssistant() + .getTheme() + .obtainStyledAttributes( + getMeditationAssistant().getMATheme(), + new int[]{R.attr.actionIconNextItem}) + .getResourceId(0, 0) + )); + + /*TableLayout.LayoutParams monthbuttonslp = new TableLayout.LayoutParams( + LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT, 1f);*/ + TableLayout.LayoutParams monthbuttonslp = new TableLayout.LayoutParams( + LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT, 1f); + monthbuttonslp.setMargins(0, MeditationAssistant.dpToPixels(7, ctx), 0, + MeditationAssistant.dpToPixels(7, ctx)); + prevMonth.setLayoutParams(monthbuttonslp); + nextMonth.setLayoutParams(monthbuttonslp); + + prevMonth.setBackgroundColor(getActivity().getResources().getColor( + android.R.color.transparent)); + nextMonth.setBackgroundColor(getActivity().getResources().getColor( + android.R.color.transparent)); + + prevMonth.setBackgroundResource(getMeditationAssistant() + .getTheme() + .obtainStyledAttributes( + getMeditationAssistant().getMATheme(), + new int[]{android.R.attr.selectableItemBackground}) + .getResourceId(0, 0)); + nextMonth.setBackgroundResource(getMeditationAssistant() + .getTheme() + .obtainStyledAttributes( + getMeditationAssistant().getMATheme(), + new int[]{android.R.attr.selectableItemBackground}) + .getResourceId(0, 0)); + + prevMonth.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + mCalendar.add(Calendar.MONTH, -1); + gridCalendar.setAdapter(getMonthAdapter()); + + updateMonthScroll(); + } + }); + + nextMonth.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + mCalendar.add(Calendar.MONTH, 1); + gridCalendar.setAdapter(getMonthAdapter()); + + updateMonthScroll(); + } + }); + + LinearLayout ldate = new LinearLayout(ctx); + ldate.setOrientation(LinearLayout.VERTICAL); + + LinearLayout.LayoutParams lp_horiz = new LinearLayout.LayoutParams( + LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT, 1f); + prevMonth.setLayoutParams(lp_horiz); + ldate.setLayoutParams(lp_horiz); + nextMonth.setLayoutParams(lp_horiz); + + ldate.setGravity(Gravity.CENTER | Gravity.CENTER_VERTICAL); + txtCurrentMonth.setGravity(Gravity.CENTER | Gravity.CENTER_VERTICAL); + txtCurrentYear.setGravity(Gravity.CENTER | Gravity.CENTER_VERTICAL); + + ldate.addView(txtCurrentMonth); + ldate.addView(txtCurrentYear); + + lhoriz.setMinimumHeight(MeditationAssistant.dpToPixels(48, ctx)); + lhoriz.addView(prevMonth); + lhoriz.addView(ldate); + lhoriz.addView(nextMonth); + + LinearLayout lbottom = new LinearLayout(ctx); + lmain.setOrientation(LinearLayout.VERTICAL); + lbottom.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, + LayoutParams.WRAP_CONTENT)); + lbottom.setWeightSum(0.5f); + lbottom.setMinimumHeight(MeditationAssistant.dpToPixels(48, ctx)); + lbottom.addView(lhoriz); + + lmain.setGravity(Gravity.BOTTOM); + + View divBottom = new View(ctx); + + LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( + LayoutParams.FILL_PARENT, + MeditationAssistant.dpToPixels(1, ctx)); + lp.setMargins(MeditationAssistant.dpToPixels(7, ctx), 0, + MeditationAssistant.dpToPixels(7, ctx), 0); + divBottom.setLayoutParams(lp); + + divBottom.setPadding(7, 0, 7, 0); + divBottom.setBackgroundDrawable(getResources().getDrawable( + getMeditationAssistant() + .getTheme() + .obtainStyledAttributes( + getMeditationAssistant().getMATheme(), + new int[]{android.R.attr.listDividerAlertDialog}) + .getResourceId(0, 0) + )); + + lcontainer.addView(lbottom); + lcontainer.addView(divBottom); + lcontainer.addView(lmain); + + updateMonthScroll(); + return lcontainer; + } + + public void updatecurrentDate() { + txtCurrentMonth.setText(String.format(Locale.getDefault(), "%tB", mCalendar)); + txtCurrentYear.setText(String.format(Locale.getDefault(), "%tY", mCalendar)); + } + + private void updateMonthScroll() { + Calendar nowCalendar = Calendar.getInstance(); + if (mCalendar.get(Calendar.MONTH) == nowCalendar.get(Calendar.MONTH) + && mCalendar.get(Calendar.YEAR) == nowCalendar + .get(Calendar.YEAR)) { + nextMonth.setClickable(false); + nextMonth.setVisibility(View.INVISIBLE); + } else { + nextMonth.setClickable(true); + nextMonth.setVisibility(View.VISIBLE); + } + } + + @Override + public void onPause() { + getMeditationAssistant().getPrefs().unregisterOnSharedPreferenceChangeListener(sharedPrefslistener); + super.onPause(); + } + + @Override + public void onResume() { + getMeditationAssistant().getPrefs().registerOnSharedPreferenceChangeListener(sharedPrefslistener); + super.onResume(); + } +} \ No newline at end of file diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/CompleteActivity.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/CompleteActivity.java new file mode 100644 index 0000000..d41d1ee --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/CompleteActivity.java @@ -0,0 +1,421 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.content.SharedPreferences; +import android.media.AudioManager; +import android.media.MediaPlayer; +import android.net.Uri; +import android.os.Bundle; +import android.os.Handler; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.WindowManager; +import android.widget.EditText; +import android.widget.TextView; + +import com.google.android.gms.ads.AdView; +import com.google.android.gms.analytics.GoogleAnalytics; + +public class CompleteActivity extends Activity { + private AdView av = null; + private MediaPlayer mMediaPlayer; + private MeditationAssistant ma; + private Handler handler = new Handler(); + private Runnable runnable = new Runnable() { + @Override + public void run() { + handler.removeCallbacks(this); + + if (getMeditationAssistant().getMediNET().result.equals("posted")) { + getMeditationAssistant() + .shortToast(getString(R.string.sessionPosted)); + finish(); + } else if (getMeditationAssistant().getMediNET().result + .equals("alreadyposted")) { + getMeditationAssistant().longToast(getString(R.string.sessionAlreadyPosted)); + } else if (getMeditationAssistant().getMediNET().status + .equals("failure") + && getMeditationAssistant().getMediNET().result + .equals("corrupt")) { + getMeditationAssistant() + .longToast( + getString(R.string.sessionNotPosted)); + } else { + handler.postDelayed(this, 2000); + } + } + }; + private Runnable clearWakeLock = new Runnable() { + public void run() { + handler.removeCallbacks(clearWakeLock); + + WakeLocker.release(); + } + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setTheme(getMeditationAssistant().getMATheme()); + setContentView(R.layout.activity_complete); + + getMeditationAssistant().hideNotification(); // Called twice because it seems to help + + long timestamp = System.currentTimeMillis() / 1000; + if (getMeditationAssistant().getTimeStartMeditate() == 0 + || (timestamp - getMeditationAssistant().getTimeStartMeditate()) <= 0) { + // Reset timestamps for current session + getMeditationAssistant().setTimeStartMeditate(0); + getMeditationAssistant().setTimeToStopMeditate(0); + + finish(); + return; + } + + setTheme(getMeditationAssistant().getMATheme()); + /*if (getMeditationAssistant().getMATheme() != R.style.MADark) { + getWindow().setBackgroundDrawable( + getResources().getDrawable( + android.R.drawable.screen_background_light)); + }*/ + + setContentView(R.layout.activity_complete); + + getWindow().setWindowAnimations(0); + + getWindow().addFlags( + WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD + | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON + ); + + Boolean manual = false; + if (getIntent().hasExtra("manual")) { + if (getIntent().getBooleanExtra("manual", false)) { + manual = true; + } + } + + getMeditationAssistant().unsetNotificationControl(); + getMeditationAssistant().hideNotification(); // Called twice because it seems to help + + if (getPackageName().equals("sh.ftp.rocketninelabs.meditationassistant")) { + Log.d("MeditationAssistant", "Fetching ad"); + + av = (AdView) findViewById(R.id.adViewSessionComplete); + av.setVisibility(View.VISIBLE); + com.google.android.gms.ads.AdRequest adRequest = new com.google.android.gms.ads.AdRequest.Builder() + .addTestDevice(com.google.android.gms.ads.AdRequest.DEVICE_ID_EMULATOR) + .build(); + av.loadAd(adRequest); + } + + EditText editSessionMessage = (EditText) findViewById(R.id.editSessionMessage); + if (editSessionMessage.getText().toString().equals("") + && getMeditationAssistant().getPrefs().getBoolean("pref_remembermessage", false)) { + editSessionMessage.setText(getMeditationAssistant().getPrefs().getString("lastmessage", "")); + } + + editSessionMessage + .setOnFocusChangeListener(new View.OnFocusChangeListener() { + @Override + public void onFocusChange(View v, boolean hasFocus) { + EditText editSessionMessage = (EditText) findViewById(R.id.editSessionMessage); + TextView editSessionMessageInfo = (TextView) findViewById(R.id.editSessionMessageInfo); + if (hasFocus) { + editSessionMessageInfo.setText(String + .valueOf(editSessionMessage.getText() + .length()) + + " / 160"); + editSessionMessageInfo.setVisibility(View.VISIBLE); + } else { + editSessionMessageInfo.setVisibility(View.GONE); + } + } + }); + editSessionMessage.addTextChangedListener(new TextWatcher() { + @Override + public void afterTextChanged(Editable s) { + TextView editSessionMessageInfo = (TextView) findViewById(R.id.editSessionMessageInfo); + editSessionMessageInfo.setText(String.valueOf(s.length()) + + " / 160"); + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, + int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, + int count) { + + } + }); + + if (getMeditationAssistant() + .getTimeStartMeditate() == 0) { + /* Getting null pointers on getTimeStartMeditate() */ + Log.d("MeditationAssistant", "getTimeStartMeditate() was 0! Exiting AlarmReceiverActivity..."); + finish(); + return; + } + + // Meditation Session + getMeditationAssistant().getMediNET().resetSession(); + getMeditationAssistant().getMediNET().session.started = getMeditationAssistant() + .getTimeStartMeditate(); + if (getMeditationAssistant().getTimerMode().equals("endat")) { + Log.d("MeditationAssistant", String.valueOf(Math.min(timestamp, getMeditationAssistant().getTimeToStopMeditate())) + " - " + + String.valueOf(getMeditationAssistant().getTimeStartMeditate()) + " - " + String.valueOf(getMeditationAssistant().pausetime)); + getMeditationAssistant().getMediNET().session.length = Math.min(timestamp, getMeditationAssistant().getTimeToStopMeditate()) + - getMeditationAssistant().getTimeStartMeditate() - getMeditationAssistant().pausetime; + } else { + Log.d("MeditationAssistant", String.valueOf(timestamp) + " - " + + String.valueOf(getMeditationAssistant().getTimeStartMeditate()) + " - " + String.valueOf(getMeditationAssistant().pausetime)); + getMeditationAssistant().getMediNET().session.length = timestamp + - getMeditationAssistant().getTimeStartMeditate() - getMeditationAssistant().pausetime; + } + getMeditationAssistant().getMediNET().session.length += 7; // Add seven seconds to account for slow wake-ups + getMeditationAssistant().getMediNET().session.completed = timestamp; + + // Reset timestamps for current session + getMeditationAssistant().setTimeStartMeditate(0); + getMeditationAssistant().setTimeToStopMeditate(0); + + Log.d("MeditationAssistant", + "Session length: " + + String.valueOf(getMeditationAssistant().getMediNET().session.length) + ); + if (getMeditationAssistant().getMediNET().session.length > 0) { + TextView txtDuration = (TextView) findViewById(R.id.txtDuration); + txtDuration.setText(MediNET + .durationToTimerString(getMeditationAssistant() + .getMediNET().session.length, false)); + + String text_size = getMeditationAssistant().getPrefs().getString("pref_text_size", "normal"); + if (text_size.equals("tiny")) { + txtDuration.setTextSize(85); + } else if (text_size.equals("small")) { + txtDuration.setTextSize(115); + } else if (text_size.equals("large")) { + txtDuration.setTextSize(175); + } else if (text_size.equals("extralarge")) { + txtDuration.setTextSize(200); + } else { // Normal + txtDuration.setTextSize(153); + } + + if (!manual + && !getMeditationAssistant().getPrefs().getString("pref_meditation_sound_finish", "") + .equals("none")) { + + mMediaPlayer = null; + if (getMeditationAssistant().getPrefs().getString("pref_meditation_sound_finish", "").equals( + "custom")) { + String soundpath = getMeditationAssistant().getPrefs().getString( + "pref_meditation_sound_finish_custom", ""); + if (!soundpath.equals("")) { + try { + mMediaPlayer = MediaPlayer.create(this, + Uri.parse(soundpath)); + } catch (Exception e) { + e.printStackTrace(); + } + } + } else { + mMediaPlayer = MediaPlayer.create(this, MeditationSounds + .getMeditationSound(getMeditationAssistant().getPrefs().getString( + "pref_meditation_sound_finish", ""))); + } + + if (mMediaPlayer != null) { + mMediaPlayer + .setOnCompletionListener(new MediaPlayer.OnCompletionListener() { + + @Override + public void onCompletion(MediaPlayer mp) { + WakeLocker.release(); + mp.release(); + } + }); + mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); + mMediaPlayer + .setOnPreparedListener(new MediaPlayer.OnPreparedListener() { + @Override + public void onPrepared( + MediaPlayer mp) { + mp.start(); + } + }); + //mMediaPlayer.prepareAsync(); + } else { + handler.postDelayed(clearWakeLock, 5000); + } + } + } + + if (getMeditationAssistant().sendUsageReports()) { + getMeditationAssistant().getTracker(MeditationAssistant.TrackerName.APP_TRACKER); + } + + if (!manual) { + getMeditationAssistant().vibrateDevice(); + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + + // Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.complete, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + // Handle action bar item clicks here. The action bar will + // automatically handle clicks on the Home/Up button, so long + // as you specify a parent activity in AndroidManifest.xml. + if (item.getItemId() == R.id.action_settings) { + return true; + } + return super.onOptionsItemSelected(item); + } + + public void askDismiss() { + new AlertDialog.Builder(this) + .setIcon(android.R.drawable.ic_dialog_alert) + .setMessage(getString(R.string.askDiscardText)) + .setPositiveButton(getString(R.string.discard), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, + int which) { + finish(); + } + } + ).setNegativeButton(getString(R.string.cancel), null) + .show(); + } + + public void dismiss(View view) { + if (getMeditationAssistant().getPrefs().getBoolean("pref_askdismiss", true)) { + askDismiss(); + } else { + finish(); + } + } + + public MeditationAssistant getMeditationAssistant() { + if (ma == null) { + ma = (MeditationAssistant) this.getApplication(); + } + return ma; + } + + private String getSessionMessage() { + EditText editSessionMessage = (EditText) findViewById(R.id.editSessionMessage); + return editSessionMessage.getText().toString().trim(); + } + + @Override + public void onBackPressed() { + if (getMeditationAssistant().getPrefs().getBoolean("pref_askdismiss", true)) { + askDismiss(); + } else { + super.onBackPressed(); + } + } + + @Override + public void onDestroy() { + if (av != null) { + av.destroy(); + } + if (mMediaPlayer != null) { + try { + mMediaPlayer.release(); + } catch (Exception e) { + e.printStackTrace(); + } + } + try { + WakeLocker.release(); + } catch (Exception e) { + e.printStackTrace(); + } + + handler.removeCallbacks(runnable); + super.onDestroy(); + } + + @Override + public void onPause() { + if (av != null) { + av.pause(); + } + super.onPause(); + } + + @Override + public void onResume() { + super.onResume(); + if (av != null) { + av.resume(); + } + } + + @Override + public void onStart() { + super.onStart(); + if (getMeditationAssistant().sendUsageReports()) { + GoogleAnalytics.getInstance(this).reportActivityStart(this); + } + } + + @Override + protected void onStop() { + super.onStop(); + if (getMeditationAssistant().sendUsageReports()) { + GoogleAnalytics.getInstance(this).reportActivityStop(this); + } + } + + public void postMediNET(View view) { + if (getMeditationAssistant().getMediNETKey() == "") { + getMeditationAssistant().showSignInDialog(this); + return; + } + + saveLastMessage(); + + getMeditationAssistant().shortToast(getString(R.string.sessionPosting)); + getMeditationAssistant().getMediNET().session.message = getSessionMessage(); + getMeditationAssistant().getMediNET().postSession(); + + handler.removeCallbacks(runnable); + handler.postDelayed(runnable, 5); + } + + private void saveLastMessage() { + SharedPreferences.Editor editor = getMeditationAssistant().getPrefs().edit(); + editor.putString("lastmessage", getSessionMessage()); + editor.apply(); + } + + public void saveMediNET(View view) { + saveLastMessage(); + + getMeditationAssistant().getMediNET().session.message = getSessionMessage(); + getMeditationAssistant().getMediNET().saveSession(false, false); + getMeditationAssistant().shortToast(getString(R.string.sessionSaved)); + finish(); + } +} diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/Crypt.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/Crypt.java new file mode 100644 index 0000000..4806800 --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/Crypt.java @@ -0,0 +1,123 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +import java.security.NoSuchAlgorithmException; + +import javax.crypto.Cipher; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +//import org.apache.commons.codec.binary.Base64; + +public class Crypt { + + private IvParameterSpec ivspec; + private SecretKeySpec keyspec; + private Cipher cipher; + + public Crypt() { + ivspec = new IvParameterSpec("fzsznzsjh2asdr7e".getBytes()); + + keyspec = new SecretKeySpec("jqx82h4ad6fzb4dk".getBytes(), "AES"); + + try { + cipher = Cipher.getInstance("AES/CBC/NoPadding"); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } catch (NoSuchPaddingException e) { + e.printStackTrace(); + } + } + + public static String bytesToHex(byte[] data) { + if (data == null) { + return null; + } + + int len = data.length; + String str = ""; + for (int i = 0; i < len; i++) { + if ((data[i] & 0xFF) < 16) + str = str + "0" + java.lang.Integer.toHexString(data[i] & 0xFF); + else + str = str + java.lang.Integer.toHexString(data[i] & 0xFF); + } + return str; + } + + public static byte[] hexToBytes(String str) { + if (str == null) { + return null; + } else if (str.length() < 2) { + return null; + } else { + int len = str.length() / 2; + byte[] buffer = new byte[len]; + for (int i = 0; i < len; i++) { + buffer[i] = (byte) Integer.parseInt( + str.substring(i * 2, i * 2 + 2), 16); + } + return buffer; + } + } + + private static String padString(String source) { + char paddingChar = ' '; + int size = 16; + int x = source.length() % size; + int padLength = size - x; + + for (int i = 0; i < padLength; i++) { + source += paddingChar; + } + + return source; + } + + public byte[] decrypt(String code) throws Exception { + if (code == null || code.length() == 0) + throw new Exception("Empty string"); + + byte[] decrypted = null; + + try { + cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec); + + decrypted = cipher.doFinal(hexToBytes(code)); + } catch (Exception e) { + throw new Exception("[decrypt] " + e.getMessage()); + } + return decrypted; + } + + public String decryptToString(String code) throws Exception { + if (code == null || code.length() == 0) + throw new Exception("Empty string"); + + String decryptedstr = null; + + try { + decryptedstr = new String(decrypt(code)).trim(); + } catch (Exception e) { + throw new Exception("[decrypt] " + e.getMessage()); + } + return decryptedstr; + } + + public byte[] encrypt(String text) throws Exception { + if (text == null || text.length() == 0) + throw new Exception("Empty string"); + + byte[] encrypted = null; + + try { + cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec); + + encrypted = cipher.doFinal(padString(text).getBytes()); + } catch (Exception e) { + throw new Exception("[encrypt] " + e.getMessage()); + } + + return encrypted; + } +} \ No newline at end of file diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/DailyNotification.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/DailyNotification.java new file mode 100644 index 0000000..6dbd14d --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/DailyNotification.java @@ -0,0 +1,163 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +import android.app.AlarmManager; +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.os.Build; +import android.provider.Settings; +import android.support.v4.app.NotificationCompat; +import android.support.v4.app.TaskStackBuilder; +import android.util.Log; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Locale; + +public class DailyNotification extends BroadcastReceiver { + MeditationAssistant ma = null; + + @Override + public void onReceive(Context context, Intent intent) { + try { + ma = (MeditationAssistant) context.getApplicationContext(); + } catch (Exception e) { + e.printStackTrace(); + return; + } + + if (!getMeditationAssistant().getPrefs().getBoolean("pref_daily_reminder", false)) { + cancelReminder(context); + return; // The user has not enabled the daily reminder + } + Log.d("MeditationAssistant", "onReceive in DailyNotification"); + + if (intent != null && intent.getAction() != null && intent.getAction().equals(MeditationAssistant.ACTION_REMINDER)) { // otherwise, it was just an update + Log.d("MeditationAssistant", "Daily notification intent!"); + + SimpleDateFormat sdf = new SimpleDateFormat("d-M-yyyy", Locale.US); + if (getMeditationAssistant().getTimeToStopMeditate() != 0) { + Log.d("MeditationAssistant", "Skipping daily notification today, session in progress..."); + } else if (getMeditationAssistant().db.numSessionsByDate(sdf.format(Calendar.getInstance().getTime())) > 0) { + Log.d("MeditationAssistant", "Skipping daily notification today, there has already been a session recorded..."); + } else { + long last_reminder = getMeditationAssistant().getPrefs().getLong("last_reminder", 0); + if (last_reminder == 0 || getMeditationAssistant().getTimestamp() - last_reminder > 120) { + getMeditationAssistant().getPrefs().edit().putLong("last_reminder", getMeditationAssistant().getTimestamp()).apply(); + + String reminderText = getMeditationAssistant().getPrefs().getString("pref_daily_reminder_text", "").trim(); + if (reminderText.equals("")) { + reminderText = context.getString(R.string.reminderText); + } + + NotificationCompat.Builder notificationBuilder = + new NotificationCompat.Builder(context) + .setSmallIcon(R.drawable.ic_notification) + .setContentTitle(context.getString(R.string.meditate)) + .setContentText(reminderText) + .setTicker(reminderText) + .setAutoCancel(true); + + if (getMeditationAssistant().getPrefs().getBoolean("pref_vibrate_reminder", true)) { + long[] vibrationPattern = {0, 200, 500, 200, 500}; + notificationBuilder.setVibrate(vibrationPattern); + } else { + long[] vibrationPattern = {0, 0}; + notificationBuilder.setVibrate(vibrationPattern); + } + + if (getMeditationAssistant().getPrefs().getBoolean("pref_sound_reminder", true)) { + notificationBuilder.setSound(Settings.System.DEFAULT_NOTIFICATION_URI); + } + + Intent notificationIntent = new Intent(context, MainActivity.class); + TaskStackBuilder stackBuilder = TaskStackBuilder.create(context); + stackBuilder.addParentStack(MainActivity.class); + stackBuilder.addNextIntent(notificationIntent); + PendingIntent resultPendingIntent = + stackBuilder.getPendingIntent( + 0, + PendingIntent.FLAG_UPDATE_CURRENT + ); + + //Intent launchMain = new Intent(context, MainActivity.class); + //PendingIntent launchNotification = PendingIntent.getActivity(context, 1008, launchMain, PendingIntent.FLAG_UPDATE_CURRENT); + notificationBuilder.setContentIntent(resultPendingIntent); + + Notification notification = notificationBuilder.build(); + + NotificationManager notificationManager = + (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + notificationManager.notify(1946, notification); + } + } + } + + String reminderTime = ma.getPrefs().getString("pref_daily_reminder_time", "19:00"); + String[] reminderTimeSplit = ((reminderTime != null && reminderTime != "") ? reminderTime : "19:00").split(":"); + Integer reminderHour = Integer.valueOf(reminderTimeSplit[0]); + Integer reminderMinute = Integer.valueOf(reminderTimeSplit[1]); + + Calendar calendar = Calendar.getInstance(); + calendar.set(Calendar.HOUR_OF_DAY, reminderHour); + calendar.set(Calendar.MINUTE, reminderMinute); + calendar.set(Calendar.SECOND, 0); + + if (Calendar.getInstance().getTimeInMillis() > calendar.getTimeInMillis()) { + calendar.add(Calendar.DATE, 1); // Tomorrow + } + + cancelReminder(context); + + getMeditationAssistant().reminderPendingIntent = PendingIntent + .getBroadcast( + context, + 1946, + new Intent( + MeditationAssistant.ACTION_REMINDER), + PendingIntent.FLAG_CANCEL_CURRENT + ); + + if (Build.VERSION.SDK_INT >= 19) { + getMeditationAssistant().reminderAlarmManager.setExact(AlarmManager.RTC_WAKEUP, + calendar.getTimeInMillis(), + getMeditationAssistant().reminderPendingIntent); + } else { + getMeditationAssistant().reminderAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP, + calendar.getTimeInMillis(), 1000, + getMeditationAssistant().reminderPendingIntent); + } + + Log.d("MeditationAssistant", "Set daily reminder alarm for " + calendar.toString()); + } + + private void cancelReminder(Context context) { + if (getMeditationAssistant().reminderPendingIntent != null) { + try { + getMeditationAssistant().reminderAlarmManager.cancel(getMeditationAssistant().reminderPendingIntent); + } catch (Exception e) { + Log.e("MeditationAssistant", "AlarmManager update was not canceled. " + e.toString()); + } + try { + PendingIntent.getBroadcast(context, 0, new Intent( + MeditationAssistant.ACTION_REMINDER), + PendingIntent.FLAG_CANCEL_CURRENT + ).cancel(); + } catch (Exception e) { + Log.e("MeditationAssistant", "PendingIntent broadcast was not canceled. " + e.toString()); + } + try { + getMeditationAssistant().reminderPendingIntent.cancel(); + } catch (Exception e) { + Log.e("MeditationAssistant", "PendingIntent was not canceled. " + e.toString()); + } + } + } + + public MeditationAssistant getMeditationAssistant() { + return ma; + } +} \ No newline at end of file diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/DatabaseHandler.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/DatabaseHandler.java new file mode 100644 index 0000000..3eb8123 --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/DatabaseHandler.java @@ -0,0 +1,374 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.util.Log; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.Locale; + +public class DatabaseHandler extends SQLiteOpenHelper { + private static final int DATABASE_VERSION = 4; + private static final String DATABASE_NAME = "meditationassistant"; + private static final String TABLE_SESSIONS = "sessions"; + + // Column names + private static final String KEY_ID = "id"; + private static final String KEY_ACCOUNT = "account"; + private static final String KEY_STARTED = "started"; + private static final String KEY_COMPLETED = "completed"; + private static final String KEY_LENGTH = "length"; + private static final String KEY_MESSAGE = "message"; + private static final String KEY_DATE = "date"; + private static final String KEY_ISPOSTED = "isposted"; + private static final String KEY_STREAKDAY = "streakday"; + private static DatabaseHandler databaseHandler; + + private SQLiteDatabase db = null; + private MeditationAssistant ma = null; + + public DatabaseHandler(Context context) { + super(context, DATABASE_NAME, null, DATABASE_VERSION); + ma = (MeditationAssistant) context; + db = this.getWritableDatabase(); + } + + public static synchronized DatabaseHandler getInstance(Context context) { + if (databaseHandler == null) { + databaseHandler = new DatabaseHandler(context.getApplicationContext()); + } + return databaseHandler; + } + + void addSession(SessionSQL session) { + ContentValues values = new ContentValues(); + values.put(KEY_STARTED, session._started); + values.put(KEY_COMPLETED, session._completed); + values.put(KEY_LENGTH, session._length); + values.put(KEY_MESSAGE, session._message); + values.put(KEY_DATE, sessionToAPIDate(session)); + values.put(KEY_ISPOSTED, session._isposted); + values.put(KEY_STREAKDAY, session._streakday); + + db.insert(TABLE_SESSIONS, null, values); + + getMeditationAssistant().recalculateMeditationStreak(); + getMeditationAssistant().notifySessionsUpdated(); + } + + public String sessionToAPIDate(SessionSQL session) { + if (session._completed != null) { + return timestampToAPIDate(session._completed * 1000); + } else { + return timestampToAPIDate((session._started + session._length) * 1000); + } + } + + public String timestampToAPIDate(long timestamp) { + SimpleDateFormat sdf = new SimpleDateFormat("d-M-yyyy", Locale.US); + + Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(timestamp); + Date api_date = cal.getTime(); + + return sdf.format(api_date); + } + + public MeditationAssistant getMeditationAssistant() { + return ma; + } + + public void deleteSession(SessionSQL session) { + db.delete(TABLE_SESSIONS, KEY_ID + " = ?", + new String[]{String.valueOf(session.getID())}); + + getMeditationAssistant().notifySessionsUpdated(); + } + + public ArrayList getAllSessions() { + ArrayList sessionList = new ArrayList(); + + String selectQuery = "SELECT * FROM `" + TABLE_SESSIONS + "` ORDER BY " + + "`" + KEY_COMPLETED + "` DESC"; + + Cursor cursor = db.rawQuery(selectQuery, null); + + if (cursor.moveToFirst()) { + do { + SessionSQL session = new SessionSQL(cursor.getLong(cursor + .getColumnIndex(KEY_ID)), cursor.getLong(cursor + .getColumnIndex(KEY_STARTED)), cursor.getLong(cursor + .getColumnIndex(KEY_COMPLETED)), cursor.getLong(cursor + .getColumnIndex(KEY_LENGTH)), cursor.getString(cursor + .getColumnIndex(KEY_MESSAGE)), cursor.getLong(cursor + .getColumnIndex(KEY_ISPOSTED)), cursor.getLong(cursor + .getColumnIndex(KEY_STREAKDAY))); + + sessionList.add(session); + } while (cursor.moveToNext()); + } + + cursor.close(); + return sessionList; + } + + public ArrayList getAllLocalSessions() { + ArrayList sessionList = new ArrayList(); + + String selectQuery = "SELECT * FROM `" + TABLE_SESSIONS + "` WHERE `" + KEY_ISPOSTED + "` = 0"; + + Cursor cursor = db.rawQuery(selectQuery, null); + + if (cursor.moveToFirst()) { + do { + SessionSQL session = new SessionSQL(cursor.getLong(cursor + .getColumnIndex(KEY_ID)), cursor.getLong(cursor + .getColumnIndex(KEY_STARTED)), cursor.getLong(cursor + .getColumnIndex(KEY_COMPLETED)), cursor.getLong(cursor + .getColumnIndex(KEY_LENGTH)), cursor.getString(cursor + .getColumnIndex(KEY_MESSAGE)), cursor.getLong(cursor + .getColumnIndex(KEY_ISPOSTED)), cursor.getLong(cursor + .getColumnIndex(KEY_STREAKDAY))); + + sessionList.add(session); + } while (cursor.moveToNext()); + } + + cursor.close(); + return sessionList; + } + + public int getNumSessions() { + String countQuery = "SELECT COUNT(*) FROM `" + TABLE_SESSIONS + "`"; + + Cursor cursor = db.rawQuery(countQuery, null); + cursor.moveToFirst(); + int numsessions = cursor.getInt(0); + cursor.close(); + + return numsessions; + } + + public int getTotalTimeSpentMeditating() { + int time_meditating = 0; + Cursor cursor = db.rawQuery("SELECT SUM(`" + KEY_LENGTH + "`) FROM `" + TABLE_SESSIONS + "`", null); + if (cursor.moveToFirst()) { + time_meditating = cursor.getInt(0); + } + cursor.close(); + + return time_meditating; + } + + int numSessionsByDate(String date) { + Cursor cursor = db.rawQuery("SELECT COUNT(*) FROM `" + TABLE_SESSIONS + "` WHERE `" + KEY_DATE + "`=?", new String[]{date}); + cursor.moveToFirst(); + int numsessions = cursor.getInt(0); + cursor.close(); + + return numsessions; + } + + int getLongestSessionLength() { + int longestsessionlength = 0; + Cursor cursor = db.rawQuery("SELECT MAX(`" + KEY_LENGTH + "`) FROM `" + TABLE_SESSIONS + "`", null); + if (cursor.moveToFirst()) { + longestsessionlength = cursor.getInt(0); + } + cursor.close(); + + return longestsessionlength; + } + + SessionSQL getSessionByStarted(long started) { + SessionSQL session = null; + + Cursor cursor = db.query(TABLE_SESSIONS, new String[]{KEY_ID, + KEY_STARTED, KEY_COMPLETED, KEY_LENGTH, KEY_MESSAGE, KEY_ISPOSTED, KEY_STREAKDAY}, + KEY_STARTED + "=?", new String[]{String.valueOf(started)}, + null, null, null, "1" + ); + if (cursor != null) { + if (cursor.getCount() > 0) { + cursor.moveToFirst(); + + session = new SessionSQL(cursor.getLong(cursor + .getColumnIndex(KEY_ID)), cursor.getLong(cursor + .getColumnIndex(KEY_STARTED)), cursor.getLong(cursor + .getColumnIndex(KEY_COMPLETED)), cursor.getLong(cursor + .getColumnIndex(KEY_LENGTH)), cursor.getString(cursor + .getColumnIndex(KEY_MESSAGE)), cursor.getLong(cursor + .getColumnIndex(KEY_ISPOSTED)), cursor.getLong(cursor + .getColumnIndex(KEY_STREAKDAY))); + } + + cursor.close(); + } + + return session; + } + + @Override + public void onCreate(SQLiteDatabase db) { + Log.d("MeditationAssistant", "CREATING DATABASE VERSION " + String.valueOf(DATABASE_VERSION)); + db.execSQL("CREATE TABLE `" + TABLE_SESSIONS + "` (" + + "`" + KEY_ID + "` INTEGER PRIMARY KEY, " + + "`" + KEY_STARTED + "` INTEGER, `" + KEY_COMPLETED + "` INTEGER, " + + "`" + KEY_LENGTH + "` INTEGER, `" + KEY_MESSAGE + "` STRING, " + + "`" + KEY_DATE + "` STRING, `" + KEY_ISPOSTED + "` INTEGER, `" + KEY_STREAKDAY + "` INTEGER" + ")"); + + db.execSQL("CREATE INDEX `" + KEY_STARTED + "_idx` ON `" + TABLE_SESSIONS + "` (`" + KEY_STARTED + "`)"); + db.execSQL("CREATE INDEX `" + KEY_COMPLETED + "_idx` ON `" + TABLE_SESSIONS + "` (`" + KEY_COMPLETED + "`)"); + db.execSQL("CREATE INDEX `" + KEY_DATE + "_idx` ON `" + TABLE_SESSIONS + "` (`" + KEY_DATE + "`)"); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + Log.d("MeditationAssistant", "DATABASE UPGRADE INITIATED - Old: " + String.valueOf(oldVersion) + " New: " + String.valueOf(newVersion)); + int curVer = oldVersion; + while (curVer < newVersion) { + curVer++; + switch (curVer) { + case 2: + Log.d("MeditationAssistant", "UPGRADING DATABASE to " + String.valueOf(curVer)); + + db.execSQL("ALTER TABLE `" + TABLE_SESSIONS + "` ADD COLUMN `" + KEY_STREAKDAY + "` INTEGER"); + break; + case 3: + Log.d("MeditationAssistant", "UPGRADING DATABASE to " + String.valueOf(curVer)); + + /* Fix for incorrect upgrade code */ + try { + db.execSQL("ALTER TABLE `" + TABLE_SESSIONS + "` ADD COLUMN `" + KEY_DATE + "` STRING"); + } catch (Exception e) { + // Column already exists + } + db.execSQL("CREATE INDEX `" + KEY_STARTED + "_idx` ON `" + TABLE_SESSIONS + "` (`" + KEY_STARTED + "`)"); + db.execSQL("CREATE INDEX `" + KEY_DATE + "_idx` ON `" + TABLE_SESSIONS + "` (`" + KEY_DATE + "`)"); + break; + case 4: + Log.d("MeditationAssistant", "UPGRADING DATABASE to " + String.valueOf(curVer)); + + /* Fix for incorrect upgrade code */ + try { + db.execSQL("ALTER TABLE `" + TABLE_SESSIONS + "` ADD COLUMN `" + KEY_STREAKDAY + "` INTEGER"); + } catch (Exception e) { + // Column already exists + } + try { + db.execSQL("ALTER TABLE `" + TABLE_SESSIONS + "` ADD COLUMN `" + KEY_DATE + "` STRING"); + db.execSQL("CREATE INDEX `" + KEY_DATE + "_idx` ON `" + TABLE_SESSIONS + "` (`" + KEY_DATE + "`)"); + db.execSQL("CREATE INDEX `" + KEY_STARTED + "_idx` ON `" + TABLE_SESSIONS + "` (`" + KEY_STARTED + "`)"); + } catch (Exception e) { + // Column already exists + } + + db.execSQL("ALTER TABLE `" + TABLE_SESSIONS + "` ADD COLUMN `" + KEY_COMPLETED + "` INTEGER"); + db.execSQL("CREATE INDEX `" + KEY_COMPLETED + "_idx` ON `" + TABLE_SESSIONS + "` (`" + KEY_COMPLETED + "`)"); + + Cursor cursor = db.rawQuery("SELECT * FROM `" + TABLE_SESSIONS + "`", null); + if (cursor.moveToFirst()) { + long session_completed; + + do { + try { + session_completed = cursor.getLong(cursor.getColumnIndex(KEY_COMPLETED)); + } catch (Exception e) { + session_completed = 0; + Log.d("MeditationAssistant", "Error fetching completed:"); + e.printStackTrace(); + } + + if (session_completed == 0) { + Log.d("MeditationAssistant", "UPDATE `" + TABLE_SESSIONS + "` SET `" + KEY_COMPLETED + + "`='" + (cursor.getLong(cursor.getColumnIndex(KEY_STARTED)) + cursor.getLong(cursor.getColumnIndex(KEY_LENGTH))) + "' WHERE `" + KEY_ID + "`='" + + cursor.getLong(cursor.getColumnIndex(KEY_ID)) + "'"); + db.rawQuery("UPDATE `" + TABLE_SESSIONS + "` SET `" + KEY_COMPLETED + + "`='" + (cursor.getLong(cursor.getColumnIndex(KEY_STARTED)) + cursor.getLong(cursor.getColumnIndex(KEY_LENGTH))) + "' WHERE `" + KEY_ID + "`='" + + cursor.getLong(cursor.getColumnIndex(KEY_ID)) + "'", null); + } + } while (cursor.moveToNext()); + } + cursor.close(); + + break; + } + } + } + + public int updateSession(SessionSQL session) { + ContentValues values = new ContentValues(); + values.put(KEY_STARTED, session._started); + values.put(KEY_COMPLETED, session._completed); + values.put(KEY_LENGTH, session._length); + values.put(KEY_MESSAGE, session._message); + values.put(KEY_ISPOSTED, session._isposted); + values.put(KEY_STREAKDAY, session._streakday); + + int result = db.update(TABLE_SESSIONS, values, KEY_ID + " = ?", + new String[]{String.valueOf(session.getID())}); + + getMeditationAssistant().notifySessionsUpdated(); + return result; + } + + public SessionSQL getSessionByDate(String date) { + Log.d("MeditationAssistant", "SQL: get session by date " + date); + SessionSQL session = null; + + Cursor cursor = db.query(TABLE_SESSIONS, new String[]{KEY_ID, + KEY_STARTED, KEY_COMPLETED, KEY_LENGTH, KEY_MESSAGE, KEY_ISPOSTED, KEY_STREAKDAY}, + KEY_DATE + "=?", new String[]{date}, + null, null, null, "1" + ); + if (cursor != null) { + if (cursor.getCount() > 0) { + cursor.moveToFirst(); + + session = new SessionSQL(cursor.getLong(cursor + .getColumnIndex(KEY_ID)), cursor.getLong(cursor + .getColumnIndex(KEY_STARTED)), cursor.getLong(cursor + .getColumnIndex(KEY_COMPLETED)), cursor.getLong(cursor + .getColumnIndex(KEY_LENGTH)), cursor.getString(cursor + .getColumnIndex(KEY_MESSAGE)), cursor.getLong(cursor + .getColumnIndex(KEY_ISPOSTED)), cursor.getLong(cursor + .getColumnIndex(KEY_STREAKDAY))); + } + + cursor.close(); + } + + return session; + } + + public ArrayList getSessionsByDate(String date) { + ArrayList sessionList = new ArrayList(); + + Cursor cursor = db.rawQuery("SELECT * FROM `" + TABLE_SESSIONS + "` WHERE `" + KEY_DATE + "`=? ORDER BY `" + KEY_STARTED + "` ASC", new String[]{date}); + + if (cursor.moveToFirst()) { + do { + SessionSQL session = new SessionSQL(cursor.getLong(cursor + .getColumnIndex(KEY_ID)), cursor.getLong(cursor + .getColumnIndex(KEY_STARTED)), cursor.getLong(cursor + .getColumnIndex(KEY_COMPLETED)), cursor.getLong(cursor + .getColumnIndex(KEY_LENGTH)), cursor.getString(cursor + .getColumnIndex(KEY_MESSAGE)), cursor.getLong(cursor + .getColumnIndex(KEY_ISPOSTED)), cursor.getLong(cursor + .getColumnIndex(KEY_STREAKDAY))); + + sessionList.add(session); + } while (cursor.moveToNext()); + } + + cursor.close(); + + return sessionList; + } +} \ No newline at end of file diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/FadeOutAnimationListener.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/FadeOutAnimationListener.java new file mode 100644 index 0000000..994c30e --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/FadeOutAnimationListener.java @@ -0,0 +1,27 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +import android.view.View; +import android.view.animation.Animation; + +public class FadeOutAnimationListener implements Animation.AnimationListener { + View view; + + @Override + public void onAnimationEnd(Animation animation) { + view.setVisibility(View.GONE); + } + + @Override + public void onAnimationRepeat(Animation animation) { + + } + + @Override + public void onAnimationStart(Animation animation) { + + } + + public void setView(View v) { + view = v; + } +} \ No newline at end of file diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/FileUtils.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/FileUtils.java new file mode 100644 index 0000000..9931a8f --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/FileUtils.java @@ -0,0 +1,503 @@ +package sh.ftp.rocketninelabs.meditationassistant; +/* + * Copyright (C) 2007-2008 OpenIntents.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import android.annotation.TargetApi; +import android.content.ContentResolver; +import android.content.ContentUris; +import android.content.Context; +import android.content.Intent; +import android.database.Cursor; +import android.database.DatabaseUtils; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.Build; +import android.os.Environment; +import android.provider.DocumentsContract; +import android.provider.MediaStore; +import android.util.Log; +import android.webkit.MimeTypeMap; + +import java.io.File; +import java.io.FileFilter; +import java.text.DecimalFormat; +import java.util.Comparator; + +/** + * @author Peli + * @author paulburke (ipaulpro) + * @version 2013-12-11 + */ +public class FileUtils { + public static final String MIME_TYPE_AUDIO = "audio/*"; + public static final String MIME_TYPE_TEXT = "text/*"; + public static final String MIME_TYPE_IMAGE = "image/*"; + public static final String MIME_TYPE_VIDEO = "video/*"; + public static final String MIME_TYPE_APP = "application/*"; + public static final String HIDDEN_PREFIX = "."; + /** + * TAG for log messages. + */ + static final String TAG = "FileUtils"; + private static final boolean DEBUG = false; // Set to true to enable logging + /** + * File and folder comparator. + * + * @author paulburke + */ + public static Comparator sComparator = new Comparator() { + @Override + public int compare(File f1, File f2) { + // Sort alphabetically by lower case, which is much cleaner + return f1.getName().toLowerCase().compareTo( + f2.getName().toLowerCase()); + } + }; + /** + * File (not directories) filter. + * + * @author paulburke + */ + public static FileFilter sFileFilter = new FileFilter() { + @Override + public boolean accept(File file) { + final String fileName = file.getName(); + // Return files only (not directories) and skip hidden files + return file.isFile() && !fileName.startsWith(HIDDEN_PREFIX); + } + }; + /** + * Folder (directories) filter. + * + * @author paulburke + */ + public static FileFilter sDirFilter = new FileFilter() { + @Override + public boolean accept(File file) { + final String fileName = file.getName(); + // Return directories only and skip hidden directories + return file.isDirectory() && !fileName.startsWith(HIDDEN_PREFIX); + } + }; + + private FileUtils() { + } //private constructor to enforce Singleton pattern + + /** + * Gets the extension of a file name, like ".png" or ".jpg". + * + * @param uri + * @return Extension including the dot("."); "" if there is no extension; + * null if uri was null. + */ + public static String getExtension(String uri) { + if (uri == null) { + return null; + } + + int dot = uri.lastIndexOf("."); + if (dot >= 0) { + return uri.substring(dot); + } else { + // No extension. + return ""; + } + } + + /** + * @return Whether the URI is a local one. + */ + public static boolean isLocal(String url) { + return (url != null && !url.startsWith("http://") && !url.startsWith("https://")); + } + + /** + * @return True if Uri is a MediaStore Uri. + * @author paulburke + */ + public static boolean isMediaUri(Uri uri) { + return "media".equalsIgnoreCase(uri.getAuthority()); + } + + /** + * Convert File into Uri. + * + * @param file + * @return uri + */ + public static Uri getUri(File file) { + if (file != null) { + return Uri.fromFile(file); + } + return null; + } + + /** + * Returns the path only (without file name). + * + * @param file + * @return + */ + public static File getPathWithoutFilename(File file) { + if (file != null) { + if (file.isDirectory()) { + // no file to be split off. Return everything + return file; + } else { + String filename = file.getName(); + String filepath = file.getAbsolutePath(); + + // Construct path without file name. + String pathwithoutname = filepath.substring(0, + filepath.length() - filename.length()); + if (pathwithoutname.endsWith("/")) { + pathwithoutname = pathwithoutname.substring(0, pathwithoutname.length() - 1); + } + return new File(pathwithoutname); + } + } + return null; + } + + /** + * @return The MIME type for the given file. + */ + public static String getMimeType(File file) { + + String extension = getExtension(file.getName()); + + if (extension.length() > 0) + return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.substring(1)); + + return "application/octet-stream"; + } + + /** + * @return The MIME type for the give Uri. + */ + public static String getMimeType(Context context, Uri uri) { + File file = new File(getPath(context, uri)); + return getMimeType(file); + } + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is ExternalStorageProvider. + * @author paulburke + */ + public static boolean isExternalStorageDocument(Uri uri) { + return "com.android.externalstorage.documents".equals(uri.getAuthority()); + } + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is DownloadsProvider. + * @author paulburke + */ + public static boolean isDownloadsDocument(Uri uri) { + return "com.android.providers.downloads.documents".equals(uri.getAuthority()); + } + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is MediaProvider. + * @author paulburke + */ + public static boolean isMediaDocument(Uri uri) { + return "com.android.providers.media.documents".equals(uri.getAuthority()); + } + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is Google Photos. + */ + public static boolean isGooglePhotosUri(Uri uri) { + return "com.google.android.apps.photos.content".equals(uri.getAuthority()); + } + + /** + * Get the value of the data column for this Uri. This is useful for + * MediaStore Uris, and other file-based ContentProviders. + * + * @param context The context. + * @param uri The Uri to query. + * @param selection (Optional) Filter used in the query. + * @param selectionArgs (Optional) Selection arguments used in the query. + * @return The value of the _data column, which is typically a file path. + * @author paulburke + */ + public static String getDataColumn(Context context, Uri uri, String selection, + String[] selectionArgs) { + + Cursor cursor = null; + final String column = "_data"; + final String[] projection = { + column + }; + + try { + cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, + null); + if (cursor != null && cursor.moveToFirst()) { + if (DEBUG) + DatabaseUtils.dumpCursor(cursor); + + final int column_index = cursor.getColumnIndexOrThrow(column); + return cursor.getString(column_index); + } + } finally { + if (cursor != null) + cursor.close(); + } + return null; + } + + /** + * Get a file path from a Uri. This will get the the path for Storage Access + * Framework Documents, as well as the _data field for the MediaStore and + * other file-based ContentProviders.
+ *
+ * Callers should check whether the path is local before assuming it + * represents a local file. + * + * @param context The context. + * @param uri The Uri to query. + * @author paulburke + * @see #isLocal(String) + * @see #getFile(Context, Uri) + */ + @TargetApi(Build.VERSION_CODES.KITKAT) + public static String getPath(final Context context, final Uri uri) { + + if (DEBUG) + Log.d(TAG + " File -", + "Authority: " + uri.getAuthority() + + ", Fragment: " + uri.getFragment() + + ", Port: " + uri.getPort() + + ", Query: " + uri.getQuery() + + ", Scheme: " + uri.getScheme() + + ", Host: " + uri.getHost() + + ", Segments: " + uri.getPathSegments().toString() + ); + + final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; + + // DocumentProvider + if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { + if (isExternalStorageDocument(uri)) { + final String docId = DocumentsContract.getDocumentId(uri); + final String[] split = docId.split(":"); + final String type = split[0]; + + if ("primary".equalsIgnoreCase(type)) { + return Environment.getExternalStorageDirectory() + "/" + split[1]; + } + } + // DownloadsProvider + else if (isDownloadsDocument(uri)) { + + final String id = DocumentsContract.getDocumentId(uri); + final Uri contentUri = ContentUris.withAppendedId( + Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); + + return getDataColumn(context, contentUri, null, null); + } + // MediaProvider + else if (isMediaDocument(uri)) { + final String docId = DocumentsContract.getDocumentId(uri); + final String[] split = docId.split(":"); + final String type = split[0]; + + Uri contentUri = null; + if ("image".equals(type)) { + contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; + } else if ("video".equals(type)) { + contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; + } else if ("audio".equals(type)) { + contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; + } + + final String selection = "_id=?"; + final String[] selectionArgs = new String[]{ + split[1] + }; + + return getDataColumn(context, contentUri, selection, selectionArgs); + } + } + // MediaStore (and general) + else if ("content".equalsIgnoreCase(uri.getScheme())) { + + // Return the remote address + if (isGooglePhotosUri(uri)) + return uri.getLastPathSegment(); + + return getDataColumn(context, uri, null, null); + } + // File + else if ("file".equalsIgnoreCase(uri.getScheme())) { + return uri.getPath(); + } + + return null; + } + + /** + * Convert Uri into File, if possible. + * + * @return file A local file that the Uri was pointing to, or null if the + * Uri is unsupported or pointed to a remote resource. + * @author paulburke + * @see #getPath(Context, Uri) + */ + public static File getFile(Context context, Uri uri) { + if (uri != null) { + String path = getPath(context, uri); + if (path != null && isLocal(path)) { + return new File(path); + } + } + return null; + } + + /** + * Get the file size in a human-readable string. + * + * @param size + * @return + * @author paulburke + */ + public static String getReadableFileSize(int size) { + final int BYTES_IN_KILOBYTES = 1024; + final DecimalFormat dec = new DecimalFormat("###.#"); + final String KILOBYTES = " KB"; + final String MEGABYTES = " MB"; + final String GIGABYTES = " GB"; + float fileSize = 0; + String suffix = KILOBYTES; + + if (size > BYTES_IN_KILOBYTES) { + fileSize = size / BYTES_IN_KILOBYTES; + if (fileSize > BYTES_IN_KILOBYTES) { + fileSize = fileSize / BYTES_IN_KILOBYTES; + if (fileSize > BYTES_IN_KILOBYTES) { + fileSize = fileSize / BYTES_IN_KILOBYTES; + suffix = GIGABYTES; + } else { + suffix = MEGABYTES; + } + } + } + return String.valueOf(dec.format(fileSize) + suffix); + } + + /** + * Attempt to retrieve the thumbnail of given File from the MediaStore. This + * should not be called on the UI thread. + * + * @param context + * @param file + * @return + * @author paulburke + */ + public static Bitmap getThumbnail(Context context, File file) { + return getThumbnail(context, getUri(file), getMimeType(file)); + } + + /** + * Attempt to retrieve the thumbnail of given Uri from the MediaStore. This + * should not be called on the UI thread. + * + * @param context + * @param uri + * @return + * @author paulburke + */ + public static Bitmap getThumbnail(Context context, Uri uri) { + return getThumbnail(context, uri, getMimeType(context, uri)); + } + + /** + * Attempt to retrieve the thumbnail of given Uri from the MediaStore. This + * should not be called on the UI thread. + * + * @param context + * @param uri + * @param mimeType + * @return + * @author paulburke + */ + public static Bitmap getThumbnail(Context context, Uri uri, String mimeType) { + if (DEBUG) + Log.d(TAG, "Attempting to get thumbnail"); + + if (!isMediaUri(uri)) { + Log.e(TAG, "You can only retrieve thumbnails for images and videos."); + return null; + } + + Bitmap bm = null; + if (uri != null) { + final ContentResolver resolver = context.getContentResolver(); + Cursor cursor = null; + try { + cursor = resolver.query(uri, null, null, null, null); + if (cursor.moveToFirst()) { + final int id = cursor.getInt(0); + if (DEBUG) + Log.d(TAG, "Got thumb ID: " + id); + + if (mimeType.contains("video")) { + bm = MediaStore.Video.Thumbnails.getThumbnail( + resolver, + id, + MediaStore.Video.Thumbnails.MINI_KIND, + null); + } else if (mimeType.contains(FileUtils.MIME_TYPE_IMAGE)) { + bm = MediaStore.Images.Thumbnails.getThumbnail( + resolver, + id, + MediaStore.Images.Thumbnails.MINI_KIND, + null); + } + } + } catch (Exception e) { + if (DEBUG) + Log.e(TAG, "getThumbnail", e); + } finally { + if (cursor != null) + cursor.close(); + } + } + return bm; + } + + /** + * Get the Intent for selecting content to be used in an Intent Chooser. + * + * @return The intent for opening a file with Intent.createChooser() + * @author paulburke + */ + public static Intent createGetContentIntent() { + // Implicitly allow the user to select a particular kind of data + final Intent intent = new Intent(Intent.ACTION_GET_CONTENT); + // The MIME data type filter + intent.setType("*/*"); + // Only return URIs that can be opened with ContentResolver + intent.addCategory(Intent.CATEGORY_OPENABLE); + return intent; + } +} \ No newline at end of file diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/JavaScriptInterface.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/JavaScriptInterface.java new file mode 100644 index 0000000..1fe58ac --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/JavaScriptInterface.java @@ -0,0 +1,47 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +import android.content.Context; +import android.util.Log; +import android.webkit.JavascriptInterface; +import android.widget.Toast; + +public class JavaScriptInterface implements JavascriptCallback { + Context context; + MediNETActivity activity; + + public JavaScriptInterface(MediNETActivity mediNETActivity, + Context applicationContext) { + context = applicationContext; + activity = mediNETActivity; + } + + @JavascriptInterface + public void askToSignIn() { + MeditationAssistant ma = (MeditationAssistant) this.activity + .getApplication(); + this.activity.finish(); + ma.getMediNET().askToSignIn(); + } + + @JavascriptInterface + public void setKey(String key, String provider) { + Log.d("MeditationAssistant", "Setting key" + key); + MeditationAssistant ma = (MeditationAssistant) this.activity + .getApplication(); + ma.setMediNETKey(key, provider); + ma.getMediNET().provider = provider; + ma.getMediNET().connect(); + /* + * Bundle bundle = new Bundle(); bundle.putString("action", + * "changekey"); Intent mIntent = new Intent(); + * mIntent.putExtras(bundle); + * this.activity.setResult(this.activity.RESULT_OK, mIntent); + */ + this.activity.finish(); + } + + @JavascriptInterface + public void showToast(String toast) { + Toast.makeText(context, toast, Toast.LENGTH_SHORT).show(); + } +} diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/JavascriptCallback.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/JavascriptCallback.java new file mode 100644 index 0000000..d6f115e --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/JavascriptCallback.java @@ -0,0 +1,5 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +public interface JavascriptCallback { + +} \ No newline at end of file diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/ListPreferenceSound.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/ListPreferenceSound.java new file mode 100644 index 0000000..a157502 --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/ListPreferenceSound.java @@ -0,0 +1,309 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.res.AssetFileDescriptor; +import android.content.res.TypedArray; +import android.media.AudioManager; +import android.media.MediaPlayer; +import android.os.Parcel; +import android.os.Parcelable; +import android.preference.ListPreference; +import android.util.AttributeSet; +import android.util.Log; + +import java.io.IOException; + +public class ListPreferenceSound extends ListPreference { + private int mClickedDialogEntryIndex; + private CharSequence[] mEntries; + private CharSequence[] mEntryValues; + private CharSequence mSummary; + private String mValue; + private MediaPlayer mMediaPlayer = null; + private Context ctx = null; + + public ListPreferenceSound(Context context) { + this(context, null); + } + + public ListPreferenceSound(Context context, AttributeSet attrs) { + super(context, attrs); + ctx = context; + + if (mMediaPlayer == null) { + mMediaPlayer = new MediaPlayer(); + } + + TypedArray a = context.obtainStyledAttributes(attrs, + R.styleable.ListPreference, 0, 0); + // mEntries = a.getTextArray(R.styleable.ListPreference_entries); + // mEntryValues = a.getTextArray(R.styleable.ListPreference_entryValues); + setEntries(a.getTextArray(R.styleable.ListPreference_entries)); + setEntryValues(a.getTextArray(R.styleable.ListPreference_entryValues)); + + a.recycle(); + mSummary = super.getSummary(); + } + + public int findIndexOfValue(String value) { + if (value != null && mEntryValues != null) { + for (int i = mEntryValues.length - 1; i >= 0; i--) { + if (mEntryValues[i].equals(value)) { + return i; + } + } + } + return -1; + } + + public CharSequence[] getEntries() { + return mEntries; + } + + public void setEntries(int entriesResId) { + setEntries(getContext().getResources().getTextArray(entriesResId)); + } + + public void setEntries(CharSequence[] entries) { + mEntries = entries; + } + + public CharSequence getEntry() { + int index = getValueIndex(); + return index >= 0 && mEntries != null ? mEntries[index] : null; + } + + public CharSequence[] getEntryValues() { + return mEntryValues; + } + + public void setEntryValues(int entryValuesResId) { + setEntryValues(getContext().getResources().getTextArray( + entryValuesResId)); + } + + public void setEntryValues(CharSequence[] entryValues) { + mEntryValues = entryValues; + } + + @Override + public CharSequence getSummary() { + final CharSequence entry = getEntry(); + if (mSummary == null || entry == null) { + return super.getSummary(); + } else { + //Log.d("MeditationAssistant", "getsummary(): " + String.valueOf(mSummary) + " " + String.valueOf(entry)); + try { + return String.format(mSummary.toString(), entry); + } catch (Exception e) { + e.printStackTrace(); + return mSummary.toString(); + } + } + } + + @Override + public void setSummary(CharSequence summary) { + super.setSummary(summary); + if (summary == null && mSummary != null) { + mSummary = null; + } else if (summary != null && !summary.equals(mSummary)) { + mSummary = summary; + } + } + + public String getValue() { + return mValue; + } + + public void setValue(String value) { + mValue = value; + persistString(value); + } + + private int getValueIndex() { + return findIndexOfValue(mValue); + } + + public void setValueIndex(int index) { + if (mEntryValues != null) { + setValue(mEntryValues[index].toString()); + } + } + + @Override + protected void onDialogClosed(boolean positiveResult) { + super.onDialogClosed(positiveResult); + if (mMediaPlayer != null) { + try { + if (mMediaPlayer.isPlaying()) { + mMediaPlayer.stop(); + mMediaPlayer.reset(); + } + } catch (Exception e) { + Log.d("MeditationAssistant", "Got exception while stopping and resetting sound in ListPreferenceSound"); + e.printStackTrace(); + } + } + if (positiveResult && mClickedDialogEntryIndex >= 0 + && mEntryValues != null) { + String value = mEntryValues[mClickedDialogEntryIndex].toString(); + if (callChangeListener(value)) { + setValue(value); + } + } + } + + @Override + protected Object onGetDefaultValue(TypedArray a, int index) { + return a.getString(index); + } + + @Override + protected void onPrepareDialogBuilder(AlertDialog.Builder builder) { + super.onPrepareDialogBuilder(builder); + if (mEntries == null || mEntryValues == null) { + throw new IllegalStateException( + "ListPreference requires an entries array and an entryValues array."); + } + mClickedDialogEntryIndex = getValueIndex(); + builder.setSingleChoiceItems(mEntries, mClickedDialogEntryIndex, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + mClickedDialogEntryIndex = which; + String itemSelected = mEntryValues[mClickedDialogEntryIndex] + .toString(); + + Log.d("MeditationAssistant", + "Selected: " + String.valueOf(which) + " - " + + itemSelected + ); + + if (itemSelected.equals("custom")) { + ListPreferenceSound.this.onClick(dialog, + DialogInterface.BUTTON_POSITIVE); + dialog.dismiss(); + } else if (!itemSelected.equals("none")) { + if (mMediaPlayer != null) { + try { + if (mMediaPlayer.isPlaying()) { + mMediaPlayer.stop(); + mMediaPlayer.reset(); + } + } catch (Exception e) { + Log.d("MeditationAssistant", "Got exception while stopping and resetting sound in ListPreferenceSound"); + e.printStackTrace(); + } + } + + AssetFileDescriptor afd = ctx + .getResources() + .openRawResourceFd( + MeditationSounds + .getMeditationSound(itemSelected) + ); + try { + mMediaPlayer = new MediaPlayer(); + mMediaPlayer.setDataSource( + afd.getFileDescriptor(), + afd.getStartOffset(), + afd.getDeclaredLength()); + mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); + mMediaPlayer.prepareAsync(); + // mMediaPlayer.prepare(); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalStateException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + if (mMediaPlayer != null) { + mMediaPlayer + .setOnCompletionListener(new MediaPlayer.OnCompletionListener() { + + @Override + public void onCompletion( + MediaPlayer mp) { + mp.release(); + } + }); + mMediaPlayer + .setOnPreparedListener(new MediaPlayer.OnPreparedListener() { + @Override + public void onPrepared( + MediaPlayer mp) { + mp.start(); + } + }); + } + } + } + } + ); + builder.setPositiveButton( + builder.getContext().getString(R.string.set), + new DialogInterface.OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int which) { + Log.d("MeditationAssistant", "Set clicked"); + ListPreferenceSound.this.onClick(dialog, + DialogInterface.BUTTON_POSITIVE); + dialog.dismiss(); + } + } + ); + } + + @Override + protected void onRestoreInstanceState(Parcelable state) { + if (state == null || !state.getClass().equals(SavedState.class)) { + super.onRestoreInstanceState(state); + return; + } + SavedState myState = (SavedState) state; + super.onRestoreInstanceState(myState.getSuperState()); + setValue(myState.value); + } + + @Override + protected Parcelable onSaveInstanceState() { + final Parcelable superState = super.onSaveInstanceState(); + if (isPersistent()) { + return superState; + } + final SavedState myState = new SavedState(superState); + myState.value = getValue(); + return myState; + } + + @Override + protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { + mValue = restoreValue ? getPersistedString(mValue) + : (String) defaultValue; + } + + private static class SavedState extends BaseSavedState { + String value; + + public SavedState(Parcel source) { + super(source); + value = source.readString(); + } + + public SavedState(Parcelable superState) { + super(superState); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + dest.writeString(value); + } + } +} diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MainActivity.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MainActivity.java new file mode 100644 index 0000000..eeb3383 --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MainActivity.java @@ -0,0 +1,2546 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +import android.app.Activity; +import android.app.AlarmManager; +import android.app.AlertDialog; +import android.app.PendingIntent; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.pm.ActivityInfo; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.media.AudioManager; +import android.media.MediaPlayer; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.text.InputType; +import android.util.Log; +import android.view.Gravity; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; +import android.widget.Button; +import android.widget.EditText; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.RadioGroup; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.ViewSwitcher; + +import com.crittercism.app.Crittercism; +import com.github.amlcurran.showcaseview.OnShowcaseEventListener; +import com.github.amlcurran.showcaseview.ShowcaseView; +import com.github.amlcurran.showcaseview.targets.ViewTarget; +import com.google.android.gms.ads.AdRequest; +import com.google.android.gms.ads.AdView; +import com.google.android.gms.analytics.GoogleAnalytics; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Date; +import java.util.HashSet; +import java.util.Locale; +import java.util.Random; +import java.util.Set; + +public class MainActivity extends Activity implements OnShowcaseEventListener { + public static String BROADCAST_ACTION_ALARM = "sh.ftp.rocketninelabs.meditationassistant.ALARM"; + public static int ID_DELAY = 77702; + public static int ID_INTERVAL = 77701; + public static int ID_END = 77703; + + public MeditationAssistant ma = null; + SharedPreferences.OnSharedPreferenceChangeListener sharedPrefslistener = new SharedPreferences.OnSharedPreferenceChangeListener() { + public void onSharedPreferenceChanged(SharedPreferences newprefs, String key) { + Log.d("MeditationAssistant", + key + " changed to " + getMeditationAssistant().getPrefs().getAll().get(key).toString()); + if (getMeditationAssistant().getTimeToStopMeditate() < 1 + && (key.equals("timerHours") || key.equals("timerMinutes"))) { + TextView txtTimer = (TextView) findViewById(R.id.txtTimer); + txtTimer.setText(getMeditationAssistant().getPrefs().getString("timerHours", "0") + + ":" + + String.format("%02d", Integer.valueOf(getMeditationAssistant().getPrefs().getString( + "timerMinutes", "15")))); + } else if (key.equals("pref_meditation_sound_finish") + || key.equals("pref_meditation_sound_finish_custom") + || key.equals("pref_meditation_sound_start") + || key.equals("pref_meditation_sound_start_custom")) { + updateTexts(); + } else if (key.equals("pref_text_size")) { + updateTextSize(); + } else if (key.equals("keyupdate")) { + if (!getMeditationAssistant().getMediNETKey().equals("")) { + getMeditationAssistant().getMediNET().connect(); + } + } + } + }; + private AdView av = null; + private Handler handler; + private Runnable meditateRunnable = null; + private Runnable screenDimRunnable = null; + private Runnable screenOffRunnable = null; + private MediaPlayer mMediaPlayer = null; + private AlarmManager am = null; + private PendingIntent pendingintent = null; + private AlarmManager am_delay = null; + private PendingIntent pendingintent_delay = null; + private AlarmManager am_interval = null; + private PendingIntent pendingintent_interval = null; + private Runnable intervalRunnable = new Runnable() { + @Override + public void run() { + Log.d("MeditationAssistant", "Interval running"); + handler.removeCallbacks(this); + if (getMeditationAssistant().getTimeStartMeditate() > 0) { + if (getMeditationAssistant().getTimeToStopMeditate() != 0 + && getMeditationAssistant().getTimeToStopMeditate() + - (System.currentTimeMillis() / 1000) < 30) { + return; // No interval sounds during the final 30 seconds + } + + if (!getMeditationAssistant().getPrefs().getString("pref_meditation_sound_interval", "") + .equals("none") || getMeditationAssistant().vibrationEnabled()) { + if (!getMeditationAssistant().getPrefs().getString("pref_meditation_sound_interval", "") + .equals("none")) { + stopMediaPlayer(); + mMediaPlayer = null; + if (getMeditationAssistant().getPrefs().getString("pref_meditation_sound_interval", "") + .equals("custom")) { + String soundpath = getMeditationAssistant().getPrefs().getString( + "pref_meditation_sound_interval_custom", ""); + if (!soundpath.equals("")) { + try { + mMediaPlayer = MediaPlayer.create( + getApplicationContext(), + Uri.parse(soundpath)); + } catch (Exception e) { + e.printStackTrace(); + } + } + } else { + mMediaPlayer = MediaPlayer + .create(getApplicationContext(), + MeditationSounds.getMeditationSound(getMeditationAssistant().getPrefs().getString( + "pref_meditation_sound_interval", + "")) + ); + } + + if (mMediaPlayer != null) { + mMediaPlayer + .setOnCompletionListener(new MediaPlayer.OnCompletionListener() { + + @Override + public void onCompletion(MediaPlayer mp) { + mp.release(); + WakeLocker.release(); + } + }); + + WakeLocker.acquire(getApplicationContext(), false); + mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); + mMediaPlayer + .setOnPreparedListener(new MediaPlayer.OnPreparedListener() { + @Override + public void onPrepared( + MediaPlayer mp) { + mp.start(); + } + }); + //mMediaPlayer.prepareAsync(); + } + } + + getMeditationAssistant().vibrateDevice(); + + long interval = Math.max( + getMeditationAssistant().timePreferenceValueToSeconds(getMeditationAssistant().getPrefs().getString("pref_session_interval", "00:00"), "00:00"), 0); + Log.d("MeditationAssistant", "Interval is set to " + String.valueOf(interval) + " seconds"); + + if (interval > 0 && (getMeditationAssistant().getTimeToStopMeditate() == -1 + || getMeditationAssistant().getTimeToStopMeditate() + - (System.currentTimeMillis() / 1000) > (interval + 30) || getMeditationAssistant().getPrefs().getBoolean("pref_softfinish", false))) { + Calendar cal = Calendar.getInstance(); + cal.add(Calendar.SECOND, (int) interval); + + Log.d("MeditationAssistant", "Setting INTERVAL WAKEUP alarm for " + + String.valueOf(cal.getTimeInMillis()) + " (Now: " + + System.currentTimeMillis() + ", in: " + String.valueOf((cal.getTimeInMillis() - System.currentTimeMillis()) / 1000) + ")"); + + Intent intent_interval = new Intent( + getApplicationContext(), MainActivity.class); + intent_interval.putExtra("wakeup", true); + intent_interval.putExtra("wakeupinterval", true); + intent_interval.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); + intent_interval.setAction(BROADCAST_ACTION_ALARM); + pendingintent_interval = PendingIntent.getActivity( + getApplicationContext(), ID_INTERVAL, + intent_interval, PendingIntent.FLAG_CANCEL_CURRENT); + am_interval = (AlarmManager) getSystemService(Context.ALARM_SERVICE); + if (Build.VERSION.SDK_INT >= 19) { + am_interval.setExact(AlarmManager.RTC_WAKEUP, + cal.getTimeInMillis(), pendingintent_interval); + } else { + am_interval.set(AlarmManager.RTC_WAKEUP, + cal.getTimeInMillis(), pendingintent_interval); + } + handler.postDelayed(this, interval * 1000); + } + } + } + } + }; + private String lastKey = ""; + private Boolean skipDelay = false; + private String previous_timermode = "timed"; + private Boolean usetimepicker = true; + private ShowcaseView sv = null; + private String next_tutorial = ""; + private int intervals = 0; + private Runnable clearWakeLock = new Runnable() { + @Override + public void run() { + WakeLocker.release(); + } + }; + private Boolean finishedTutorial = null; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Crittercism.initialize(getApplicationContext(), "51d51a5ea7928a6b4a000005"); + + setTheme(getMeditationAssistant().getMATheme()); + setContentView(R.layout.activity_main); + + if (getMeditationAssistant().sendUsageReports()) { + getMeditationAssistant().getTracker(MeditationAssistant.TrackerName.APP_TRACKER); + } + + handler = new Handler(); + + lastKey = getMeditationAssistant().getPrefs().getString("key", ""); + + if (getMeditationAssistant().getMediNET() == null) { + getMeditationAssistant().setMediNET(new MediNET(this)); + Log.d("MeditationAssistant", "New instance of MediNET created"); + } else { + getMeditationAssistant().getMediNET().activity = this; + } + + getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD); + + findViewById(R.id.btnMeditate).setLongClickable(true); + final View btnMeditate = findViewById(R.id.btnMeditate); + btnMeditate.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + return longPressMeditate(v); + } + }); + + /*CheckBox chkUseTimer = (CheckBox) findViewById(R.id.chkUseTimer); + chkUseTimer.setChecked(getMeditationAssistant().getUseTimer()); + changeUseTimer(null);*/ + + usetimepicker = getMeditationAssistant().getPrefs().getBoolean("pref_usetimepicker", false); + + final EditText editDuration = (EditText) findViewById(R.id.editDuration); + final TimePicker timepickerDuration = (TimePicker) findViewById(R.id.timepickerDuration); + timepickerDuration.setIs24HourView(true); + if (usetimepicker) { + editDuration.setVisibility(View.GONE); + timepickerDuration.setVisibility(View.VISIBLE); + /*EditText newEditDuration = new EditText(this); + newEditDuration.setId(R.id.editDuration); + FrameLayout.LayoutParams editDurationLayoutParams = new FrameLayout.LayoutParams( + android.view.ViewGroup.LayoutParams.FILL_PARENT, + android.view.ViewGroup.LayoutParams.WRAP_CONTENT); + editDurationLayoutParams.gravity = Gravity.CENTER; + editDurationLayoutParams.setMargins(0, 0, 0, 0); + newEditDuration.setLayoutParams(editDurationLayoutParams); + newEditDuration.setIncludeFontPadding(false); + newEditDuration.setInputType(InputType.TYPE_DATETIME_VARIATION_TIME); + newEditDuration.setSingleLine(true); + newEditDuration.imeOp + RelativeLayout layEditDuration = (RelativeLayout) findViewById(R.id.layEditDuration); + layEditDuration.addView(newEditDuration);*/ + } else { + timepickerDuration.setVisibility(View.GONE); + editDuration.setVisibility(View.VISIBLE); + } + + updateTextSize(); + updateMeditate(false, false); + updateTexts(); + updatePresets(); + getMeditationAssistant().setRunnableStopped(true); + startRunnable(); + + editDuration + .setOnEditorActionListener(new EditText.OnEditorActionListener() { + @Override + public boolean onEditorAction(android.widget.TextView v, + int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_DONE) { + ViewSwitcher switchTimer = (ViewSwitcher) findViewById(R.id.switchTimer); + RelativeLayout layEditDuration = (RelativeLayout) findViewById(R.id.layEditDuration); + + if (switchTimer.getCurrentView().equals( + layEditDuration)) { + setDuration(null); + } + return true; + } + + return false; + } + }); + editDuration.setOnKeyListener(new EditText.OnKeyListener() { + @Override + public boolean onKey(View v, int keyCode, KeyEvent event) { + if (event.getAction() == KeyEvent.ACTION_UP + && keyCode == KeyEvent.KEYCODE_ENTER) { + ViewSwitcher switchTimer = (ViewSwitcher) findViewById(R.id.switchTimer); + RelativeLayout layEditDuration = (RelativeLayout) findViewById(R.id.layEditDuration); + if (switchTimer.getCurrentView().equals(layEditDuration)) { + setDuration(null); + } + + return true; + } + + return false; + } + }); + + Button btnPreset1 = (Button) findViewById(R.id.btnPreset1); + Button btnPreset2 = (Button) findViewById(R.id.btnPreset2); + Button btnPreset3 = (Button) findViewById(R.id.btnPreset3); + + View.OnLongClickListener presetListener = new View.OnLongClickListener() { + @Override + public boolean onLongClick(final View view) { + if (getMeditationAssistant().getTimerMode().equals("endat")) { + ArrayList duration_formatted = new ArrayList(); + if (usetimepicker) { + duration_formatted.add(String.valueOf(timepickerDuration.getCurrentHour())); + duration_formatted.add(String.format("%02d", + timepickerDuration.getCurrentMinute())); + } else { + duration_formatted = getMeditationAssistant().formatDurationEndAt(editDuration.getText().toString().trim()); + } + + if (duration_formatted == null || duration_formatted.size() != 2) { + getMeditationAssistant().shortToast(MainActivity.this, getString(R.string.setPresetHintBlank)); + return true; + } + } else if (!getMeditationAssistant().getTimerMode().equals("untimed")) { + ArrayList duration_formatted = new ArrayList(); + if (usetimepicker) { + duration_formatted.add(String.valueOf(timepickerDuration.getCurrentHour())); + duration_formatted.add(String.format("%02d", + timepickerDuration.getCurrentMinute())); + } else { + duration_formatted = getMeditationAssistant().formatDuration(editDuration.getText().toString().trim()); + } + + if (duration_formatted == null || duration_formatted.size() != 2) { + getMeditationAssistant().shortToast(MainActivity.this, getString(R.string.setPresetHintBlank)); + return true; + } + } + + final String preset_key; + if (view.getId() == R.id.btnPreset1) { + preset_key = "pref_preset_1"; + } else if (view.getId() == R.id.btnPreset2) { + preset_key = "pref_preset_2"; + } else if (view.getId() == R.id.btnPreset3) { + preset_key = "pref_preset_3"; + } else { + return false; + } + + LayoutInflater presetInflater = getLayoutInflater(); + View presetLayout = presetInflater.inflate(R.layout.set_preset, null); + final EditText editPresetTitle = (EditText) presetLayout.findViewById(R.id.editPresetTitle); + editPresetTitle.setText(getPresetDefaultLabel()); + editPresetTitle.setSelection(editPresetTitle.getText().length()); + editPresetTitle.setInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); + + AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); + + builder.setIcon( + getResources() + .getDrawable( + getTheme() + .obtainStyledAttributes( + getMeditationAssistant() + .getMATheme(), + new int[]{R.attr.actionIconForward} + ) + .getResourceId(0, 0) + ) + ) + .setTitle(getString(R.string.setPreset)) + .setView(presetLayout) + .setPositiveButton(getString(R.string.set), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + getMeditationAssistant().getPrefs().edit().putString(preset_key + "_label", editPresetTitle.getText().toString().trim()).apply(); + savePreset(preset_key); + updatePresets(); + } + }) + .setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + // Do nothing + } + }).show(); + + return true; + } + }; + + btnPreset1.setOnLongClickListener(presetListener); + btnPreset2.setOnLongClickListener(presetListener); + btnPreset3.setOnLongClickListener(presetListener); + + updateVisibleViews(false); + + if (getMeditationAssistant().getEditingDuration()) { + changeDuration(null); + } + + // String pass = "br[qs$jQ>$_rr1~ bu')5\1]fw| }"; + + /*RelativeLayout.LayoutParams lps = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + lps.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); + lps.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); + int margin = ((Number) (getResources().getDisplayMetrics().density * 24)).intValue(); + lps.setMargins(margin, margin, margin, margin);*/ + + //sv.setButtonPosition(lps); + + if (getMeditationAssistant().getPrefs().getBoolean("pref_autosignin", false)) { + getMeditationAssistant().connectOnce(); + } else { + getMeditationAssistant().getMediNET().updated(); + } + + if (getPackageName() + .equals("sh.ftp.rocketninelabs.meditationassistant")) { + Log.d("MeditationAssistant", "Fetching ad"); + + // AdView av = new AdView(this, AdSize.SMART_BANNER, + // "a15110a172d3cff"); + av = (AdView) findViewById(R.id.adViewMain); + av.setVisibility(View.VISIBLE); + AdRequest adRequest = new AdRequest.Builder() + .addTestDevice(AdRequest.DEVICE_ID_EMULATOR) + .build(); + av.loadAd(adRequest); + } + + onNewIntent(getIntent()); + + Object language = Locale.getDefault().getLanguage(); + if (language != null && !language.equals("en") && getMeditationAssistant().getPrefs().getInt("applaunches", 0) >= 5 && !getMeditationAssistant().getPrefs().getBoolean("askedtotranslate", false)) { + getMeditationAssistant().getPrefs().edit().putBoolean("askedtotranslate", true).apply(); + + DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + switch (which) { + case DialogInterface.BUTTON_POSITIVE: + startActivity(new Intent( + Intent.ACTION_VIEW, + Uri.parse("http://medinet.ftp.sh/translate")).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); + + break; + + case DialogInterface.BUTTON_NEGATIVE: + break; + } + } + }; + + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setIcon( + getResources() + .getDrawable( + getTheme() + .obtainStyledAttributes( + getMeditationAssistant() + .getMATheme(), + new int[]{R.attr.actionIconNotImportant} + ) + .getResourceId(0, 0) + ) + ) + .setTitle(getString(R.string.translate)) + .setMessage( + getString(R.string.translateMeditationAssistantText)) + .setPositiveButton(getString(R.string.yes), + dialogClickListener) + .setNegativeButton(getString(R.string.no), + dialogClickListener).show(); + } + + showNextTutorial(); + getMeditationAssistant().recalculateMeditationStreak(); + + long pref_delay = Integer.valueOf(getMeditationAssistant().getPrefs().getString("pref_delay", "-1")); + long pref_interval = Integer.valueOf(getMeditationAssistant().getPrefs().getString("pref_interval", "-1")); + if (pref_delay >= 0 || pref_interval >= 0) { + getMeditationAssistant().getPrefs().edit().putString("pref_delay", "-1").putString("pref_interval", "-1").apply(); + + getMeditationAssistant().getMediNET().announcement = getString(R.string.helpUpgradeDelayInterval); + runOnUiThread(new Runnable() { + @Override + public void run() { + getMeditationAssistant() + .showAnnouncementDialog(getString(R.string.pref_notification)); + } + }); + } + + getMeditationAssistant().setupGoogleClient(MainActivity.this); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.main, menu); + return super.onCreateOptionsMenu(menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + // Handle action bar item clicks here. The action bar will + // automatically handle clicks on the Home/Up button, so long + // as you specify a parent activity in AndroidManifest.xml. + if (sv != null && sv.isShown()) { + try { + sv.hide(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + if (item.getItemId() == R.id.action_settings) { + Intent intent = new Intent(this, SettingsActivity.class); + startActivity(intent); + return true; + } + return super.onOptionsItemSelected(item); + } + + public void cancelSetDuration(View view) { + ViewSwitcher switchTimer = (ViewSwitcher) findViewById(R.id.switchTimer); + InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(switchTimer.getWindowToken(), 0); + getMeditationAssistant().setEditingDuration(false); + getMeditationAssistant().setTimerMode(previous_timermode); + changeDuration(null); + updateVisibleViews(false); + } + + public void updateEditDuration() { + if (usetimepicker) { + TimePicker timepickerDuration = (TimePicker) findViewById(R.id.timepickerDuration); + + if (getMeditationAssistant().getTimerMode().equals("timed")) { + timepickerDuration.setEnabled(true); + timepickerDuration.setCurrentHour(Integer.valueOf(getMeditationAssistant().getPrefs().getString("timerHours", "0"))); + timepickerDuration.setCurrentMinute(Integer.valueOf(String.format("%02d", Integer.valueOf(getMeditationAssistant().getPrefs().getString("timerMinutes", "15"))))); + } else if (getMeditationAssistant().getTimerMode().equals("endat")) { + timepickerDuration.setEnabled(true); + timepickerDuration.setCurrentHour(Integer.valueOf(getMeditationAssistant().getPrefs().getString("timerHoursEndAt", "0"))); + timepickerDuration.setCurrentMinute(Integer.valueOf(String.format("%02d", Integer.valueOf(getMeditationAssistant().getPrefs().getString("timerMinutesEndAt", "0"))))); + } else { + timepickerDuration.setEnabled(false); + } + } else { + EditText editDuration = (EditText) findViewById(R.id.editDuration); + //FrameLayout.LayoutParams editDurationLayoutParams = new FrameLayout.LayoutParams( + // android.view.ViewGroup.LayoutParams.FILL_PARENT, + // android.view.ViewGroup.LayoutParams.WRAP_CONTENT); + //editDurationLayoutParams.gravity = Gravity.CENTER; + + if (getMeditationAssistant().getTimerMode().equals("timed")) { + editDuration.setText(getMeditationAssistant().getPrefs().getString("timerHours", "0") + + ":" + + String.format("%02d", Integer.valueOf(getMeditationAssistant().getPrefs().getString( + "timerMinutes", "15")))); + //editDurationLayoutParams.setMargins(0, -23, 0, -11); + } else if (getMeditationAssistant().getTimerMode().equals("endat")) { + editDuration.setText(getMeditationAssistant().getPrefs().getString("timerHoursEndAt", "0") + + ":" + + String.format("%02d", Integer.valueOf(getMeditationAssistant().getPrefs().getString( + "timerMinutesEndAt", "0")))); + + //editDurationLayoutParams.setMargins(0, -23, 0, -11); + } else { + editDuration.setText(getString(R.string.ignore_om)); + //editDurationLayoutParams.setMargins(0, 0, 0, 0); + } + } + + updateMeditate(false, false); + //editDuration.setLayoutParams(editDurationLayoutParams); + } + + public void setDuration(View view) { + ViewSwitcher switchTimer = (ViewSwitcher) findViewById(R.id.switchTimer); + + if (usetimepicker) { + TimePicker timepickerDuration = (TimePicker) findViewById(R.id.timepickerDuration); + + if (getMeditationAssistant().getTimerMode().equals("timed")) { + getMeditationAssistant().getPrefs().edit().putString("timerHours", String.valueOf(timepickerDuration.getCurrentHour())).putString("timerMinutes", String.valueOf(timepickerDuration.getCurrentMinute())).apply(); + } else if (getMeditationAssistant().getTimerMode().equals("endat")) { + getMeditationAssistant().getPrefs().edit().putString("timerHoursEndAt", String.valueOf(timepickerDuration.getCurrentHour())).putString("timerMinutesEndAt", String.valueOf(timepickerDuration.getCurrentMinute())).apply(); + } + } else { + EditText editDuration = (EditText) findViewById(R.id.editDuration); + + if (getMeditationAssistant().getTimerMode().equals("timed")) { + ArrayList duration_formatted = getMeditationAssistant().formatDuration(editDuration.getText().toString().trim()); + if (duration_formatted != null && duration_formatted.size() == 2) { + SharedPreferences.Editor editor = getMeditationAssistant().getPrefs().edit(); + editor.putString("timerHours", duration_formatted.get(0)); + editor.putString("timerMinutes", duration_formatted.get(1)); + editor.apply(); + } else { + getMeditationAssistant().shortToast(this, getString(R.string.setTimerDurationHint)); + return; + } + } else if (getMeditationAssistant().getTimerMode().equals("endat")) { + ArrayList duration_formatted = getMeditationAssistant().formatDurationEndAt(editDuration.getText().toString().trim()); + if (duration_formatted != null && duration_formatted.size() == 2) { + SharedPreferences.Editor editor = getMeditationAssistant().getPrefs().edit(); + editor.putString("timerHoursEndAt", duration_formatted.get(0)); + editor.putString("timerMinutesEndAt", duration_formatted.get(1)); + editor.apply(); + } else { + getMeditationAssistant().shortToast(this, getString(R.string.setTimerEndAtHint)); + return; + } + } + + InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(switchTimer.getWindowToken(), 0); + } + + getMeditationAssistant().setEditingDuration(false); + changeDuration(null); + } + + /* Called when the duration is clicked */ + public void changeDuration(View view) { + ViewSwitcher switcher = (ViewSwitcher) findViewById(R.id.switchTimer); + RelativeLayout layEditDuration = (RelativeLayout) findViewById(R.id.layEditDuration); + EditText editDuration = (EditText) findViewById(R.id.editDuration); + + if (getMeditationAssistant().getTimeStartMeditate() > 0) { + if (!switcher.getCurrentView().equals(layEditDuration)) { + return; // Don't switch during a meditation session + } + } + + if (getMeditationAssistant().getEditingDuration()) { + return; // Don't switch back while editing, must use buttons + } + + if (sv != null && sv.isShown()) { + try { + sv.hide(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + // RelativeLayout layRememberDurationOuter = (RelativeLayout) + // findViewById(R.id.layRememberDurationOuter); + + switcher.showNext(); + Boolean wasEditing = false; + if (switcher.getCurrentView().equals(layEditDuration)) { + if (view != null) { + getMeditationAssistant().setEditingDuration(true); + Boolean previous_rememberduration = getMeditationAssistant() + .getRememberDuration(); + previous_timermode = getMeditationAssistant().getTimerMode(); + } + + updateEditDuration(); + + if (getMeditationAssistant().getTimerMode().equals("timed") || getMeditationAssistant().getTimerMode().equals("endat")) { + editDuration.requestFocus(); + InputMethodManager imm = (InputMethodManager) this + .getSystemService(Context.INPUT_METHOD_SERVICE); + imm.showSoftInput(editDuration, + InputMethodManager.SHOW_IMPLICIT); + editDuration.setSelection(0, editDuration.getText().length()); + } + } else { + getMeditationAssistant().setEditingDuration(false); + + wasEditing = true; + } + + updateMeditate(false, false); + updateVisibleViews(false); + + if (wasEditing) { + showNextTutorial(); + } + } + + private void showNextTutorial() { + if (finishedTutorial == null) { + finishedTutorial = getMeditationAssistant().getPrefs().getBoolean("finishedTutorial", false); + + if (!finishedTutorial && getMeditationAssistant().db.getNumSessions() > 0) { // Already recorded a session + getMeditationAssistant().getPrefs().edit().putBoolean("finishedTutorial", true).apply(); + finishedTutorial = true; + } + } + + if (!finishedTutorial) { + if (!getMeditationAssistant().getPrefs().getBoolean("finishedTutorial", false)) { + getMeditationAssistant().getPrefs().edit().putBoolean("finishedTutorial", true).apply(); // Commit early because of crashes + } + + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + if (sv != null) { + return; // Tutorial still visible + } + + if (next_tutorial.equals("")) { + if (!getMeditationAssistant().getEditingDuration()) { + View txtTimer = findViewById(R.id.txtTimer); + if (txtTimer == null) { + return; + } + next_tutorial = "settings"; + + ViewTarget target = new ViewTarget(R.id.txtTimer, this); + try { + sv = new ShowcaseView.Builder(this, true) + .setTarget(target) + .setContentTitle(R.string.timer) + .setContentText(R.string.timerHelp) + .setShowcaseEventListener(this) + .setStyle(R.style.MeditationShowcaseTheme) + .build(); + sv.hideButton(); + sv.setHideOnTouchOutside(false); + } catch (Exception e) { + e.printStackTrace(); + } + } + } else if (next_tutorial.equals("settings")) { + if (!getMeditationAssistant().getEditingDuration()) { + View actionSettings = findViewById(R.id.action_settings); + if (actionSettings == null) { + return; + } + next_tutorial = "medinet"; + + ViewTarget target = new ViewTarget(R.id.action_settings, this); + try { + sv = new ShowcaseView.Builder(this, true) + .setTarget(target) + .setContentTitle(R.string.settings) + .setContentText(R.string.settingsHelp) + .setShowcaseEventListener(this) + .setStyle(R.style.MeditationShowcaseTheme) + .build(); + sv.hideButton(); + sv.setHideOnTouchOutside(false); + } catch (Exception e) { + e.printStackTrace(); + } + } + } else if (next_tutorial.equals("medinet")) { + if (!getMeditationAssistant().getEditingDuration()) { + View btnMeditationStreak = findViewById(R.id.btnMeditationStreak); + if (btnMeditationStreak == null) { + return; + } + next_tutorial = "none"; + finishedTutorial = true; + + ViewTarget target = new ViewTarget(R.id.btnMeditationStreak, this); + try { + sv = new ShowcaseView.Builder(this, true) + .setTarget(target) + .setContentTitle(R.string.mediNET) + .setShowcaseEventListener(this) + .setStyle(R.style.MeditationShowcaseTheme) + .build(); + sv.setContentText(getString(R.string.medinetHelp) + "\n\nनमस्ते"); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + } else { + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); + } + } + + public void showViewMA(View view, boolean fadeView) { + if (view == null) { + return; + } + if (view.getVisibility() != View.VISIBLE && fadeView) { + Animation animation = AnimationUtils.loadAnimation(this, + R.anim.fadeinma); + view.startAnimation(animation); + } + view.setVisibility(View.VISIBLE); + } + + public void hideViewMA(View view, boolean fadeView) { + if (view == null) { + return; + } + if (view.getVisibility() == View.VISIBLE && fadeView) { + Log.d("MeditationAssistant", "Visible, fading out..."); + FadeOutAnimationListener listener = new FadeOutAnimationListener(); + listener.setView(view); + Animation animation = AnimationUtils.loadAnimation(this, + R.anim.fadeoutma); + animation.setAnimationListener(listener); + view.startAnimation(animation); + } else { + view.setVisibility(View.GONE); + } + } + + public void updateVisibleViews(boolean fadeViews) { + // Log.d("MeditationAssistant", "updateVisibleViews"); + RadioGroup radgMainTimerMode = (RadioGroup) findViewById(R.id.radgMainTimerMode); + + RelativeLayout layLowerViews = (RelativeLayout) findViewById(R.id.layLowerViews); + LinearLayout layLowerViewsEditing = (LinearLayout) findViewById(R.id.layLowerViewsEditing); + + if (getMeditationAssistant().getEditingDuration()) { + hideViewMA(layLowerViews, false); + showViewMA(layLowerViewsEditing, false); + } else { + showViewMA(layLowerViews, false); + hideViewMA(layLowerViewsEditing, false); + } + + EditText editDuration = (EditText) findViewById(R.id.editDuration); + + if (getMeditationAssistant().getEditingDuration()) { + if (getMeditationAssistant().getTimerMode().equals("timed") || getMeditationAssistant().getTimerMode().equals("endat")) { + InputMethodManager imm = (InputMethodManager) this + .getSystemService(Context.INPUT_METHOD_SERVICE); + imm.showSoftInput(editDuration, + InputMethodManager.SHOW_IMPLICIT); + + editDuration.setSelection(0, editDuration.getText().length()); + editDuration.setEnabled(true); + } else { + editDuration.setSelection(0, 0); + editDuration.setEnabled(false); + } + } else { + editDuration.setSelection(0, 0); + editDuration.setEnabled(false); + } + + /* Update radio buttons */ + if (getMeditationAssistant().getTimerMode().equals("untimed")) { + radgMainTimerMode.check(R.id.radMainUntimed); + } else if (getMeditationAssistant().getTimerMode().equals("endat")) { + radgMainTimerMode.check(R.id.radMainEndAt); + } else { + radgMainTimerMode.check(R.id.radMainTimed); + } + } + + public void updateTextSize() { + TextView txtTimer = (TextView) findViewById(R.id.txtTimer); + EditText editDuration = (EditText) findViewById(R.id.editDuration); + String text_size = getMeditationAssistant().getPrefs().getString("pref_text_size", "normal"); + if (text_size.equals("tiny")) { + txtTimer.setTextSize(85); + editDuration.setTextSize(85); + } else if (text_size.equals("small")) { + txtTimer.setTextSize(115); + editDuration.setTextSize(115); + } else if (text_size.equals("large")) { + txtTimer.setTextSize(175); + editDuration.setTextSize(175); + } else if (text_size.equals("extralarge")) { + txtTimer.setTextSize(200); + editDuration.setTextSize(200); + } else { // Normal + txtTimer.setTextSize(153); + editDuration.setTextSize(153); + } + } + + public void updatePresets() { + Button btnPreset1 = (Button) findViewById(R.id.btnPreset1); + Button btnPreset2 = (Button) findViewById(R.id.btnPreset2); + Button btnPreset3 = (Button) findViewById(R.id.btnPreset3); + + btnPreset1.setText(getMeditationAssistant().getPrefs().getString("pref_preset_1_label", getString(R.string.setPreset))); + btnPreset2.setText(getMeditationAssistant().getPrefs().getString("pref_preset_2_label", getString(R.string.setPreset))); + btnPreset3.setText(getMeditationAssistant().getPrefs().getString("pref_preset_3_label", getString(R.string.setPreset))); + } + + public String getPresetDefaultLabel() { + EditText editDuration = (EditText) findViewById(R.id.editDuration); + TimePicker timepickerDuration = (TimePicker) findViewById(R.id.timepickerDuration); + + if (getMeditationAssistant().getTimerMode().equals("untimed")) { + return "Untimed"; + } else if (getMeditationAssistant().getTimerMode().equals("endat")) { + ArrayList duration_formatted = new ArrayList(); + if (usetimepicker) { + duration_formatted.add(String.valueOf(timepickerDuration.getCurrentHour())); + duration_formatted.add(String.format("%02d", + timepickerDuration.getCurrentMinute())); + } else { + duration_formatted = getMeditationAssistant().formatDurationEndAt(editDuration.getText().toString().trim()); + } + + if (duration_formatted != null && duration_formatted.size() == 2) { + return String.format(getString(R.string.presetLabelEndAt), duration_formatted.get(0) + ":" + duration_formatted.get(1)); + } + } else { // timed + ArrayList duration_formatted = new ArrayList(); + if (usetimepicker) { + duration_formatted.add(String.valueOf(timepickerDuration.getCurrentHour())); + duration_formatted.add(String.format("%02d", + timepickerDuration.getCurrentMinute())); + } else { + duration_formatted = getMeditationAssistant().formatDuration(editDuration.getText().toString().trim()); + } + + if (duration_formatted != null && duration_formatted.size() == 2) { + return duration_formatted.get(0) + ":" + duration_formatted.get(1); + } + } + + return ""; + } + + public void pressPreset(View view) { + final EditText editDuration = (EditText) findViewById(R.id.editDuration); + + String preset_key; + if (view.getId() == R.id.btnPreset1) { + preset_key = "pref_preset_1"; + } else if (view.getId() == R.id.btnPreset2) { + preset_key = "pref_preset_2"; + } else if (view.getId() == R.id.btnPreset3) { + preset_key = "pref_preset_3"; + } else { + return; + } + + String preset_value = getMeditationAssistant().getPrefs().getString(preset_key, ""); + Boolean successfulRestore = false; + + if (!preset_value.equals("")) { + try { + Set presetSettings = getMeditationAssistant().getPrefs().getStringSet("pref_presetsettings", new HashSet(Arrays.asList(getResources().getStringArray(R.array.presetsettings_default)))); + JSONObject preset = new JSONObject(preset_value); + Log.d("MeditationAssistant", "Restore preset settings: " + presetSettings.toString() + " - Values: " + preset_value); + + // Mode and duration + if (presetSettings.contains("modeandduration")) { + if (preset.getString("modeandduration").equals("untimed")) { + getMeditationAssistant().setTimerMode("untimed"); + + setDuration(null); + } else if (preset.getString("modeandduration").startsWith("e") && preset.getString("modeandduration").length() > 1) { + getMeditationAssistant().setTimerMode("endat"); + + if (usetimepicker) { + String[] preset_split = preset.getString("modeandduration").substring(1).split(":"); + if (preset_split.length == 2) { + TimePicker timepickerDuration = (TimePicker) findViewById(R.id.timepickerDuration); + timepickerDuration.setCurrentHour(Integer.valueOf(preset_split[0])); + timepickerDuration.setCurrentMinute(Integer.valueOf(preset_split[1])); + } + } else { + editDuration.setText(preset.getString("modeandduration").substring(1)); + } + setDuration(null); + } else if (!preset.getString("modeandduration").equals("")) { + getMeditationAssistant().setTimerMode("timed"); + + if (usetimepicker) { + String[] preset_split = preset.getString("modeandduration").split(":"); + if (preset_split.length == 2) { + TimePicker timepickerDuration = (TimePicker) findViewById(R.id.timepickerDuration); + timepickerDuration.setCurrentHour(Integer.valueOf(preset_split[0])); + timepickerDuration.setCurrentMinute(Integer.valueOf(preset_split[1])); + } + } else { + editDuration.setText(preset.getString("modeandduration")); + } + setDuration(null); + } + } + + // Delay + if (presetSettings.contains("delay")) { + getMeditationAssistant().getPrefs().edit().putString("pref_session_delay", preset.getString("delay")).apply(); + } + + // Start sound + if (presetSettings.contains("startsound")) { + getMeditationAssistant().getPrefs().edit().putString("pref_meditation_sound_start", preset.getString("startsound")).apply(); + if (preset.getString("startsound").equals("custom")) { + getMeditationAssistant().getPrefs().edit().putString("pref_meditation_sound_start_custom", preset.getString("startsoundcustom")).apply(); + } + } + + // Interval duration + if (presetSettings.contains("intervalduration")) { + getMeditationAssistant().getPrefs().edit().putString("pref_session_interval", preset.getString("intervalduration")).apply(); + } + + // Interval sound + if (presetSettings.contains("intervalsound")) { + getMeditationAssistant().getPrefs().edit().putString("pref_meditation_sound_interval", preset.getString("intervalsound")).apply(); + if (preset.getString("intervalsound").equals("custom")) { + getMeditationAssistant().getPrefs().edit().putString("pref_meditation_sound_interval_custom", preset.getString("intervalsoundcustom")).apply(); + } + } + + // Interval count + if (presetSettings.contains("intervalcount")) { + getMeditationAssistant().getPrefs().edit().putString("pref_interval_count", preset.getString("intervalcount")).apply(); + } + + // Complete sound + if (presetSettings.contains("completesound")) { + getMeditationAssistant().getPrefs().edit().putString("pref_meditation_sound_finish", preset.getString("completesound")).apply(); + if (preset.getString("completesound").equals("custom")) { + getMeditationAssistant().getPrefs().edit().putString("pref_meditation_sound_finish_custom", preset.getString("completesoundcustom")).apply(); + } + } + + // Ringtone and notifications + if (presetSettings.contains("ringtone")) { + getMeditationAssistant().getPrefs().edit().putString("pref_notificationcontrol", preset.getString("ringtone")).apply(); + } + + // Endless + if (presetSettings.contains("endless")) { + getMeditationAssistant().getPrefs().edit().putBoolean("pref_softfinish", preset.getBoolean("endless")).apply(); + } + + // Vibrate + if (presetSettings.contains("vibrate")) { + getMeditationAssistant().getPrefs().edit().putBoolean("pref_vibrate", preset.getBoolean("vibrate")).apply(); + } + + successfulRestore = true; + } catch (JSONException e) { + e.printStackTrace(); + } + } + + if (successfulRestore) { + Intent presetIntent = new Intent(); + presetIntent.setAction(MeditationAssistant.ACTION_PRESET); + sendBroadcast(presetIntent); + } else { + getMeditationAssistant().shortToast(this, getString(R.string.setPresetHint)); + } + } + + public void openProgress(View view) { + if (sv != null && sv.isShown()) { + try { + sv.hide(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + Intent intent = new Intent(this, ProgressActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + startActivity(intent); + } + + public void savePreset(String preset_key) { + EditText editDuration = (EditText) findViewById(R.id.editDuration); + TimePicker timepickerDuration = (TimePicker) findViewById(R.id.timepickerDuration); + + Preset preset = new Preset(); + if (getMeditationAssistant().getTimerMode().equals("untimed")) { + preset.modeandduration = "untimed"; + } else if (getMeditationAssistant().getTimerMode().equals("endat")) { + ArrayList duration_formatted = new ArrayList(); + if (usetimepicker) { + duration_formatted.add(String.valueOf(timepickerDuration.getCurrentHour())); + duration_formatted.add(String.format("%02d", + timepickerDuration.getCurrentMinute())); + } else { + duration_formatted = getMeditationAssistant().formatDurationEndAt(editDuration.getText().toString().trim()); + } + + if (duration_formatted != null && duration_formatted.size() == 2) { + preset.modeandduration = "e" + duration_formatted.get(0) + ":" + duration_formatted.get(1); + } + } else { // timed + ArrayList duration_formatted = new ArrayList(); + if (usetimepicker) { + duration_formatted.add(String.valueOf(timepickerDuration.getCurrentHour())); + duration_formatted.add(String.format("%02d", + timepickerDuration.getCurrentMinute())); + } else { + duration_formatted = getMeditationAssistant().formatDuration(editDuration.getText().toString().trim()); + } + + if (duration_formatted != null && duration_formatted.size() == 2) { + preset.modeandduration = duration_formatted.get(0) + ":" + duration_formatted.get(1); + } + } + + preset.delay = getMeditationAssistant().getPrefs().getString("pref_session_delay", "00:15"); + preset.startsound = getMeditationAssistant().getPrefs().getString("pref_meditation_sound_start", ""); + preset.startsoundcustom = getMeditationAssistant().getPrefs().getString("pref_meditation_sound_start_custom", ""); + preset.intervalduration = getMeditationAssistant().getPrefs().getString("pref_session_interval", "00:00"); + preset.intervalsound = getMeditationAssistant().getPrefs().getString("pref_meditation_sound_interval", ""); + preset.intervalsoundcustom = getMeditationAssistant().getPrefs().getString("pref_meditation_sound_interval_custom", ""); + preset.intervalcount = getMeditationAssistant().getPrefs().getString("pref_interval_count", ""); + preset.completesound = getMeditationAssistant().getPrefs().getString("pref_meditation_sound_finish", ""); + preset.completesoundcustom = getMeditationAssistant().getPrefs().getString("pref_meditation_sound_finish_custom", ""); + preset.ringtone = getMeditationAssistant().getPrefs().getString("pref_notificationcontrol", ""); + preset.endless = getMeditationAssistant().getPrefs().getBoolean("pref_softfinish", false); + preset.vibrate = getMeditationAssistant().getPrefs().getBoolean("pref_vibrate", false); + + String exported = preset.export().toString(); + Log.d("MeditationAssistant", "Setting preset: " + exported); + getMeditationAssistant().getPrefs().edit().putString(preset_key, exported).apply(); + } + + public void pressMeditate(View view) { + if (sv != null && sv.isShown()) { + try { + sv.hide(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + long timestamp = getMeditationAssistant().getTimestamp(); + + if (getMeditationAssistant().getTimeStartMeditate() > 0) { // session in progress + if (getMeditationAssistant().getTimeStartMeditate() > timestamp) { // currently in delay phase + Log.d("MeditationAssistant", + "PREVIOUS Timestamp: " + + String.valueOf(timestamp) + + " Stop: " + + String.valueOf(getMeditationAssistant() + .getTimeToStopMeditate()) + + " Start: " + + String.valueOf(getMeditationAssistant() + .getTimeStartMeditate()) + ); + getMeditationAssistant().setTimeStartMeditate(timestamp); + + if (getMeditationAssistant().getTimeToStopMeditate() != -1 && getMeditationAssistant().getTimerMode().equals("timed")) { // update end time for timed session + getMeditationAssistant().setTimeToStopMeditate( + timestamp + + getMeditationAssistant() + .getSessionDuration() + ); + } + + Log.d("MeditationAssistant", + "NEW Timestamp: " + + String.valueOf(timestamp) + + " Stop: " + + String.valueOf(getMeditationAssistant() + .getTimeToStopMeditate()) + + " Start: " + + String.valueOf(getMeditationAssistant() + .getTimeStartMeditate()) + ); + handler.removeCallbacks(meditateRunnable); + handler.removeCallbacks(intervalRunnable); + skipDelay = true; + if (am_delay != null && pendingintent_delay != null) { + am_delay.cancel(pendingintent_delay); + } + handler.postDelayed(meditateRunnable, 50); + } else { // Currently in meditation phase + if (!getMeditationAssistant().ispaused) { // In progress, pause the session + am = (AlarmManager) getSystemService(Context.ALARM_SERVICE); + am.cancel(pendingintent); + am.cancel(pendingintent_interval); + Log.d("MeditationAssistant", "CANCELLED MAIN WAKEUP AND INTERVAL ALARMS"); + + getMeditationAssistant().pauseSession(); + + handler.removeCallbacks(screenDimRunnable); + handler.removeCallbacks(screenOffRunnable); + WindowManager.LayoutParams params = getWindow().getAttributes(); + params.screenBrightness = -1; + getWindow().setAttributes(params); + + // Always show this notification (add to tutorial?) + //if (getMeditationAssistant().getPrefs().getBoolean("firstpause", true)) { + // getMeditationAssistant().getPrefs().edit().putBoolean("firstpause", false).apply(); + getMeditationAssistant().longToast(getString(R.string.pausedNotification)); + //} + } else { // Paused, un-pause + long pausetime = getMeditationAssistant().unPauseSession(); + + if (getMeditationAssistant().getTimerMode().equals("timed")) { + getMeditationAssistant().setTimeToStopMeditate(getMeditationAssistant().getTimeToStopMeditate() + pausetime); + } else if (getMeditationAssistant().getTimerMode().equals("endat")) { + if (getMeditationAssistant().getTimeToStopMeditate() - pausetime <= 0) { + Intent openAlarmReceiverActivity = new Intent(getApplicationContext(), CompleteActivity.class); + openAlarmReceiverActivity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + openAlarmReceiverActivity.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); + startActivity(openAlarmReceiverActivity); + + return; + } + } + + setIntervalAlarm(); + + if (getMeditationAssistant().getTimeToStopMeditate() != -1 && timestamp < getMeditationAssistant().getTimeToStopMeditate()) { + Calendar cal = Calendar.getInstance(); + cal.add(Calendar.SECOND, (int) (getMeditationAssistant() + .getTimeToStopMeditate() - getMeditationAssistant().getTimestamp())); + + Intent intent = new Intent(getApplicationContext(), + MainActivity.class); + intent.putExtra("wakeup", true); + intent.putExtra("fullwakeup", true); + intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); + intent.setAction(BROADCAST_ACTION_ALARM); + pendingintent = PendingIntent.getActivity( + getApplicationContext(), ID_END, intent, + PendingIntent.FLAG_CANCEL_CURRENT); + am = (AlarmManager) getSystemService(Context.ALARM_SERVICE); + if (Build.VERSION.SDK_INT >= 19) { + am.setExact(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), + pendingintent); + } else { + am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), + pendingintent); + } + + Log.d("MeditationAssistant", "Setting MAIN WAKEUP alarm for " + + String.valueOf(cal.getTimeInMillis()) + " (Now: " + + System.currentTimeMillis() + ", in: " + String.valueOf((cal.getTimeInMillis() - System.currentTimeMillis()) / 1000) + ")"); + } + + getMeditationAssistant().ispaused = false; + screenDimOrOff(); + } + } + + return; + } + + getMeditationAssistant().ispaused = false; + getMeditationAssistant().pausetime = 0; + skipDelay = false; + intervals = 0; + + // Context context = getApplicationContext(); + + Log.d("MeditationAssistant", "Timestamp: " + String.valueOf(timestamp)); + Integer secondsTillFinished = 0; + if (getMeditationAssistant().getTimerMode().equals("timed")) { + secondsTillFinished = Integer.parseInt(getMeditationAssistant().getPrefs().getString( + "timerHours", "0")) + * 3600 + + (Integer.parseInt(getMeditationAssistant().getPrefs().getString("timerMinutes", "15")) * 60); + } else if (getMeditationAssistant().getTimerMode().equals("endat")) { + Date now = new Date(); + + Calendar c_now = Calendar.getInstance(); + c_now.setTime(now); + + int end_at_hour = Integer.parseInt(getMeditationAssistant().getPrefs().getString("timerHoursEndAt", "0")); + int end_at_minute = Integer.parseInt(getMeditationAssistant().getPrefs().getString("timerMinutesEndAt", "0")); + + if (end_at_hour > 11) { + end_at_hour -= 12; // convert 24 to 12 hour time + } + + Calendar c_endat = Calendar.getInstance(); + c_endat.setTime(now); + + if (c_now.get(Calendar.HOUR_OF_DAY) >= 12) { // noon or later + Log.d("MeditationAssistant", "End at debug: NOON OR LATER"); + if ((end_at_hour + 12) >= c_now.get(Calendar.HOUR_OF_DAY)) { // later today + Log.d("MeditationAssistant", "End at debug: A LATER TODAY"); + if ((end_at_hour + 12) == c_now.get(Calendar.HOUR_OF_DAY) && end_at_minute <= c_now.get(Calendar.MINUTE)) { // End at is now or earlier + getMeditationAssistant().shortToast(this, getString(R.string.invalidEndAt)); + return; + } + + c_endat.set(Calendar.HOUR_OF_DAY, end_at_hour + 12); + } else { // tomorrow + Log.d("MeditationAssistant", "End at debug: A TOMORROW"); + c_endat.add(Calendar.DATE, 1); + c_endat.set(Calendar.HOUR_OF_DAY, end_at_hour); + } + } else { + Log.d("MeditationAssistant", "End at debug: BEFORE NOON"); + if (end_at_hour >= c_now.get(Calendar.HOUR_OF_DAY)) { // later today (before noon) + Log.d("MeditationAssistant", "End at debug: B LATER TODAY BEFORE NOON"); + if (end_at_hour == c_now.get(Calendar.HOUR_OF_DAY) && end_at_minute <= c_now.get(Calendar.MINUTE)) { // End at is now or earlier + getMeditationAssistant().shortToast(this, getString(R.string.invalidEndAt)); + return; + } + + c_endat.set(Calendar.HOUR_OF_DAY, end_at_hour); + } else { // later today (after noon) + Log.d("MeditationAssistant", "End at debug: B LATER TODAY AFTER NOON"); + c_endat.set(Calendar.HOUR_OF_DAY, end_at_hour + 12); + } + } + c_endat.set(Calendar.MINUTE, end_at_minute); + c_endat.set(Calendar.SECOND, 0); + + Log.d("MeditationAssistant", "NOW HOUROFDAY: " + String.valueOf(c_now.get(Calendar.HOUR_OF_DAY)) + " MINUTE: " + String.valueOf(c_now.get(Calendar.MINUTE))); + Log.d("MeditationAssistant", "END HOUROFDAY: " + String.valueOf(c_endat.get(Calendar.HOUR_OF_DAY)) + " MINUTE: " + String.valueOf(c_endat.get(Calendar.MINUTE))); + Log.d("MeditationAssistant", "-- END AT: " + String.valueOf(c_endat.getTimeInMillis() / 1000) + " NOW: " + String.valueOf(c_now.getTimeInMillis() / 1000)); + + // Add two seconds to account for partial seconds between now and the end at time for pretty durations + secondsTillFinished = (int) ((c_endat.getTimeInMillis() - c_now.getTimeInMillis()) / 1000) + 2; + + if (secondsTillFinished < 60) { + getMeditationAssistant().shortToast(this, getString(R.string.invalidEndAt)); + return; + } + } + + // debug + // secondsTillFinished = 2; + + getMeditationAssistant().setSessionDuration(secondsTillFinished); + + Log.d("MeditationAssistant", "Current delay value: " + getMeditationAssistant().getPrefs().getString("pref_session_delay", "00:15")); + + long delay = Math.max( + getMeditationAssistant().timePreferenceValueToSeconds(getMeditationAssistant().getPrefs().getString("pref_session_delay", "00:15"), "00:15"), 0); + + getMeditationAssistant().setTimeStartMeditate(timestamp + delay); + + if (getMeditationAssistant().getTimerMode().equals("timed")) { + getMeditationAssistant().setTimeToStopMeditate( + timestamp + secondsTillFinished + delay); + } else if (getMeditationAssistant().getTimerMode().equals("endat")) { + if (secondsTillFinished <= delay) { + delay = 0; + } + + getMeditationAssistant().setTimeToStopMeditate( + timestamp + secondsTillFinished); + } else { + getMeditationAssistant().setTimeToStopMeditate(-1); + } + + updateMeditate(true, false); + Log.d("MeditationAssistant", "Starting runnable from startMeditate"); + + Random rand = new Random(); + getMeditationAssistant().shortToast( + getMeditationAssistant().getStartPhrases()[rand.nextInt(getMeditationAssistant().getStartPhrases().length)]); + + meditateRunnable = new Runnable() { + @Override + public void run() { + setVolumeControlStream(AudioManager.USE_DEFAULT_STREAM_TYPE); + if (getMeditationAssistant().getTimeStartMeditate() == 0) { + return; + } + + if (getMeditationAssistant().getTimeToStopMeditate() != -1) { + Calendar cal = Calendar.getInstance(); + cal.add(Calendar.SECOND, (int) (getMeditationAssistant() + .getTimeToStopMeditate() - getMeditationAssistant() + .getTimeStartMeditate())); + + Intent intent = new Intent(getApplicationContext(), + MainActivity.class); + intent.putExtra("wakeup", true); + intent.putExtra("fullwakeup", true); + intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); + intent.setAction(BROADCAST_ACTION_ALARM); + pendingintent = PendingIntent.getActivity( + getApplicationContext(), ID_END, intent, + PendingIntent.FLAG_CANCEL_CURRENT); + am = (AlarmManager) getSystemService(Context.ALARM_SERVICE); + if (Build.VERSION.SDK_INT >= 19) { + am.setExact(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), + pendingintent); + } else { + am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), + pendingintent); + } + + Log.d("MeditationAssistant", "Setting MAIN WAKEUP alarm for " + + String.valueOf(cal.getTimeInMillis()) + " (Now: " + + System.currentTimeMillis() + ", in: " + String.valueOf((cal.getTimeInMillis() - System.currentTimeMillis()) / 1000) + ")"); + } + + if (!skipDelay) { + getMeditationAssistant().vibrateDevice(); + } + + screenDimOrOff(); + + if (!getMeditationAssistant().getPrefs().getString("pref_meditation_sound_start", "").equals( + "none")) { + mMediaPlayer = null; + if (getMeditationAssistant().getPrefs().getString("pref_meditation_sound_start", "") + .equals("custom")) { + String soundpath = getMeditationAssistant().getPrefs().getString( + "pref_meditation_sound_start_custom", ""); + if (!soundpath.equals("")) { + try { + mMediaPlayer = MediaPlayer.create( + getApplicationContext(), + Uri.parse(soundpath)); + } catch (Exception e) { + e.printStackTrace(); + } + } + } else { + mMediaPlayer = MediaPlayer.create( + getApplicationContext(), MeditationSounds + .getMeditationSound(getMeditationAssistant().getPrefs().getString( + "pref_meditation_sound_start", + "")) + ); + } + + if (mMediaPlayer != null) { + mMediaPlayer + .setOnCompletionListener(new MediaPlayer.OnCompletionListener() { + + @Override + public void onCompletion(MediaPlayer mp) { + mp.release(); + WakeLocker.release(); + } + }); + mMediaPlayer + .setOnPreparedListener(new MediaPlayer.OnPreparedListener() { + @Override + public void onPrepared( + MediaPlayer mp) { + mp.start(); + } + }); + + WakeLocker.acquire(getApplicationContext(), false); + //mMediaPlayer.prepareAsync(); + } + } + + setIntervalAlarm(); + } + }; + + startRunnable(); + + getMeditationAssistant().setNotificationControl(); + + WindowManager.LayoutParams params = getWindow().getAttributes(); + + if (getMeditationAssistant().getPrefs().getString("pref_screencontrol", "dim").equals("on")) { + getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + } + + if (getMeditationAssistant().getPrefs().getBoolean("pref_full_screen", false)) { + getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + } + + getWindow().setAttributes(params); + + if (delay > 0) { + setVolumeControlStream(AudioManager.STREAM_MUSIC); + + Calendar cal = Calendar.getInstance(); + cal.add(Calendar.SECOND, (int) delay); + + Log.d("MeditationAssistant", "Setting DELAY WAKEUP alarm for " + + String.valueOf(cal.getTimeInMillis()) + " (Now: " + + System.currentTimeMillis() + ", in: " + String.valueOf((cal.getTimeInMillis() - System.currentTimeMillis()) / 1000) + ")"); + + Intent intent_delay = new Intent(getApplicationContext(), + MainActivity.class); + intent_delay.putExtra("wakeup", true); + intent_delay.putExtra("wakeupstart", true); + intent_delay.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); + intent_delay.setAction(BROADCAST_ACTION_ALARM); + pendingintent_delay = PendingIntent.getActivity( + getApplicationContext(), ID_DELAY, intent_delay, + PendingIntent.FLAG_CANCEL_CURRENT); + am_delay = (AlarmManager) getSystemService(Context.ALARM_SERVICE); + if (Build.VERSION.SDK_INT >= 19) { + am_delay.setExact(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), + pendingintent_delay); + } else { + am_delay.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), + pendingintent_delay); + } + } else { + handler.postDelayed(meditateRunnable, 50); + } + } + + private void setIntervalAlarm() { + long interval = Math.max( + getMeditationAssistant().timePreferenceValueToSeconds(getMeditationAssistant().getPrefs().getString("pref_session_interval", "00:00"), "00:00"), 0); + Log.d("MeditationAssistant", "Interval is set to " + String.valueOf(interval) + " seconds"); + + if (interval > 0) { + Log.d("MeditationAssistant", "Reached postDelayed for interval runnable"); + Calendar cal = Calendar.getInstance(); + cal.add(Calendar.SECOND, (int) interval); + + Log.d("MeditationAssistant", "Setting INITIAL INTERVAL WAKEUP alarm for " + + String.valueOf(cal.getTimeInMillis()) + " (Now: " + + System.currentTimeMillis() + ", in: " + String.valueOf((cal.getTimeInMillis() - System.currentTimeMillis()) / 1000) + ")"); + + Intent intent_interval = new Intent( + getApplicationContext(), MainActivity.class); + intent_interval.putExtra("wakeup", true); + intent_interval.putExtra("wakeupinterval", true); + intent_interval.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); + intent_interval.setAction(BROADCAST_ACTION_ALARM); + pendingintent_interval = PendingIntent.getActivity( + getApplicationContext(), ID_INTERVAL, + intent_interval, PendingIntent.FLAG_CANCEL_CURRENT); + am_interval = (AlarmManager) getSystemService(Context.ALARM_SERVICE); + if (Build.VERSION.SDK_INT >= 19) { + Log.d("MeditationAssistant", "Using setExact() for alarm"); + am_interval.setExact(AlarmManager.RTC_WAKEUP, + cal.getTimeInMillis(), pendingintent_interval); + } else { + Log.d("MeditationAssistant", "Using set() for alarm"); + am_interval.set(AlarmManager.RTC_WAKEUP, + cal.getTimeInMillis(), pendingintent_interval); + } + } + } + + private void screenDimOrOff() { + if (getMeditationAssistant().getPrefs().getString("pref_screencontrol", "dim").equals("ondim") || getMeditationAssistant().getPrefs().getString("pref_screencontrol", "dim").equals("dim")) { + screenDimRunnable = new Runnable() { + @Override + public void run() { + if (getMeditationAssistant().getTimeStartMeditate() == 0) { + Log.d("MeditationAssistant", + "Exiting runnable for dimming screen"); + return; + } + + WindowManager.LayoutParams windowParams = getWindow() + .getAttributes(); + windowParams.screenBrightness = 0.01f; + getWindow().setAttributes(windowParams); + + if (getMeditationAssistant().getPrefs().getString("pref_screencontrol", "dim").equals("ondim")) { + getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + } else { + getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + } + } + }; + + handler.postDelayed(screenDimRunnable, 250); + } else if (getMeditationAssistant().getPrefs().getString("pref_screencontrol", "dim").equals("off")) { + WindowManager.LayoutParams windowParams = getWindow() + .getAttributes(); + windowParams.screenBrightness = 0.0f; + getWindow().setAttributes(windowParams); + getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + + screenOffRunnable = new Runnable() { + @Override + public void run() { + if (getMeditationAssistant().getTimeStartMeditate() == 0) { + Log.d("MeditationAssistant", + "Exiting runnable for turning screen off"); + return; + } + + WindowManager.LayoutParams windowParams = getWindow() + .getAttributes(); + windowParams.screenBrightness = -1; + getWindow().setAttributes(windowParams); + } + }; + + handler.postDelayed(screenOffRunnable, 5000); + } + } + + public boolean longPressMeditate(View view) { + long timestamp = System.currentTimeMillis() / 1000; + Log.d("MeditationAssistant", "stopMedidate"); + getMeditationAssistant().unPauseSession(); + + setVolumeControlStream(AudioManager.USE_DEFAULT_STREAM_TYPE); + + if (am != null && pendingintent != null) { + am.cancel(pendingintent); + Log.d("MeditationAssistant", "Cancelled main wake alarm"); + } + if (am_delay != null && pendingintent_delay != null) { + am_delay.cancel(pendingintent_delay); + Log.d("MeditationAssistant", "Cancelled delay alarm"); + } + if (am_interval != null && pendingintent_interval != null) { + am_interval.cancel(pendingintent_interval); + Log.d("MeditationAssistant", "Cancelled interval alarm"); + } + + if (getMeditationAssistant().getTimeStartMeditate() != 0) { + if (view != null + && timestamp + - getMeditationAssistant().getTimeStartMeditate() > 0) { + Intent openAlarmReceiverActivity = new Intent( + getApplicationContext(), CompleteActivity.class); + openAlarmReceiverActivity.putExtra("manual", true); + openAlarmReceiverActivity + .addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); + startActivity(openAlarmReceiverActivity); + } else { + // Reset timestamps for current session + getMeditationAssistant().setTimeStartMeditate(0); + getMeditationAssistant().setTimeToStopMeditate(0); + updateMeditate(false, false); + } + + handler.removeCallbacks(meditateRunnable); + handler.removeCallbacks(intervalRunnable); + handler.removeCallbacks(screenDimRunnable); + handler.removeCallbacks(screenOffRunnable); + getMeditationAssistant().setRunnableStopped(true); + return true; + } + + return false; + } + + public void onTimerModeSelected(View view) { + EditText editDuration = (EditText) findViewById(R.id.editDuration); + TimePicker timepickerDuration = (TimePicker) findViewById(R.id.timepickerDuration); + RelativeLayout.LayoutParams editDurationLayoutParams = new RelativeLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + android.view.ViewGroup.LayoutParams.WRAP_CONTENT); + //editDurationLayoutParams.gravity = Gravity.CENTER; + + String newTimerMode = "timed"; + if (view.getId() == R.id.radMainEndAt || view.getId() == R.id.layMainEndAt) { + newTimerMode = "endat"; + } else if (view.getId() == R.id.radMainUntimed || view.getId() == R.id.layMainUntimed) { + newTimerMode = "untimed"; + } + + getMeditationAssistant().setTimerMode(newTimerMode); + //updateEditDuration(); should the duration be reset when changing modes? + if (newTimerMode.equals("untimed")) { + if (usetimepicker) { + timepickerDuration.setEnabled(false); + } else { + editDurationLayoutParams.setMargins(0, 0, 0, 0); + editDuration.setText(getString(R.string.ignore_om)); + } + } else { + if (usetimepicker) { + timepickerDuration.setEnabled(true); + } else { + editDurationLayoutParams.setMargins(0, -23, 0, -11); + + if (editDuration.getText().toString().equals(getString(R.string.ignore_om))) { + if (newTimerMode.equals("endat")) { // Don't leave om character in edit text + editDuration.setText(getMeditationAssistant().getPrefs().getString("timerHoursEndAt", "0") + + ":" + + String.format("%02d", Integer.valueOf(getMeditationAssistant().getPrefs() + .getString("timerMinutesEndAt", "0")))); + } else { // timed + editDuration.setText(getMeditationAssistant().getPrefs().getString("timerHours", "0") + + ":" + + String.format("%02d", Integer.valueOf(getMeditationAssistant().getPrefs() + .getString("timerMinutes", "15")))); + } + editDuration.requestFocus(); + InputMethodManager imm = (InputMethodManager) this + .getSystemService(Context.INPUT_METHOD_SERVICE); + imm.showSoftInput(editDuration, + InputMethodManager.SHOW_IMPLICIT); + } + } + } + + updateVisibleViews(false); + editDuration.setLayoutParams(editDurationLayoutParams); + } + + @Override + protected void onPause() { + if (getMeditationAssistant().getTimeStartMeditate() > 0 + && getMeditationAssistant().getTimeToStopMeditate() != 0) { + getMeditationAssistant().showNotification(); + } + + if (av != null) { + av.pause(); + } + + getMeditationAssistant().setScreenOff(true); + getMeditationAssistant().getPrefs().unregisterOnSharedPreferenceChangeListener(sharedPrefslistener); + + super.onPause(); + } + + @Override + protected void onResume() { + getMeditationAssistant().hideNotification(); + + if (getIntent().getStringExtra("action") != null) { + Log.d("MeditationAssistant", "Intent for MainActivity: " + + getIntent().getStringExtra("action")); + } + getMeditationAssistant().setScreenOff(false); + WindowManager.LayoutParams params = getWindow().getAttributes(); + params.screenBrightness = -1; + getWindow().setAttributes(params); + + getMeditationAssistant().getPrefs().registerOnSharedPreferenceChangeListener(sharedPrefslistener); + if (lastKey != null && !lastKey.equals("") + && !getMeditationAssistant().getPrefs().getString("key", "").equals(lastKey)) { + Log.d("MeditationAssistant", "onResume detected key change"); + } + + usetimepicker = getMeditationAssistant().getPrefs().getBoolean("pref_usetimepicker", false); + + updateTextSize(); + updateTexts(); + startRunnable(); + + if (getMeditationAssistant().asktorate) { + getMeditationAssistant().asktorate = false; + + if (!getMeditationAssistant().getPrefs().getBoolean("askedtorate", false) && (getMeditationAssistant().getIsBB() || MeditationAssistant.getMarketName().equals("google") || MeditationAssistant.getMarketName().equals("amazon"))) { + getMeditationAssistant().getPrefs().edit().putBoolean("askedtorate", true).apply(); + + DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + switch (which) { + case DialogInterface.BUTTON_POSITIVE: + getMeditationAssistant().askToRateApp(); + + break; + + case DialogInterface.BUTTON_NEGATIVE: + break; + } + } + }; + + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setIcon( + getResources() + .getDrawable( + getTheme() + .obtainStyledAttributes( + getMeditationAssistant() + .getMATheme(), + new int[]{R.attr.actionIconNotImportant} + ) + .getResourceId(0, 0) + ) + ) + .setTitle(getString(R.string.rateMeditationAssistant)) + .setMessage( + getString(R.string.rateMeditationAssistantText)) + .setPositiveButton(getString(R.string.yes), + dialogClickListener) + .setNegativeButton(getString(R.string.no), + dialogClickListener).show(); + } + } + + showNextTutorial(); + + super.onResume(); + + if (av != null) { + av.resume(); + } + } + + @Override + public void onStart() { + if (getMeditationAssistant().sendUsageReports()) { + GoogleAnalytics.getInstance(this).reportActivityStart(this); + } + if (getMeditationAssistant().googleClient != null) { + getMeditationAssistant().googleClient.connect(); + } + + super.onStart(); + } + + @Override + protected void onStop() { + if (getMeditationAssistant().sendUsageReports()) { + GoogleAnalytics.getInstance(this).reportActivityStop(this); + } + if (getMeditationAssistant().googleClient != null && getMeditationAssistant().googleClient.isConnected()) { + getMeditationAssistant().googleClient.disconnect(); + } + + super.onStop(); + } + + @Override + public void onDestroy() { + if (!getMeditationAssistant().getPrefs().getBoolean("pref_autosignin", false) && !getMeditationAssistant().getPrefs().getString("key", "").equals("")) { + getMeditationAssistant().getPrefs().edit().putString("key", "").apply(); + } + + if (av != null) { + av.destroy(); + } + + super.onDestroy(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if ((keyCode == KeyEvent.KEYCODE_BACK) && getMeditationAssistant().getEditingDuration()) { + cancelSetDuration(null); + return true; + } + + return super.onKeyDown(keyCode, event); + } + + public void updateTexts() { + /* Log.d("MeditationAssistant", "Updating texts..."); */ + TextView txtMainStatus = (TextView) findViewById(R.id.txtMainStatus); + Button btnMeditationStreak = (Button) findViewById(R.id.btnMeditationStreak); + Resources res = getResources(); + + if (getMeditationAssistant().getTimeToStopMeditate() < 1) { + resetScreenBrightness(); + getMeditationAssistant().unsetNotificationControl(); + + WindowManager.LayoutParams params = getWindow().getAttributes(); + getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + getWindow().setAttributes(params); + } + + if (!getMeditationAssistant().getPrefs().getBoolean("pref_showstreak", true) + || getMeditationAssistant().getMeditationStreak() == null + || getMeditationAssistant().getMeditationStreak() < 1) { + + if (getMeditationAssistant().getMediNET().status.equals("success")) { + btnMeditationStreak + .setText(getString(R.string.signOutOfMediNET)); + } else { + + btnMeditationStreak.setText(getString(R.string.signInToMediNET)); + } + } else { + btnMeditationStreak.setText(res.getQuantityString( + R.plurals.daysOfMeditation, getMeditationAssistant() + .getMeditationStreak(), + getMeditationAssistant().getMeditationStreak() + )); + } + + if (getMeditationAssistant().getMediNET().status != null) { + Log.d("MeditationAssistant", "Updating texts with status " + + getMeditationAssistant().getMediNET().status); + if (getMeditationAssistant().getMediNET().status + .equals("connecting")) { + txtMainStatus.setText(getString(R.string.mediNETConnecting)); + } else if (getMeditationAssistant().getMediNET().status + .equals("success")) { + txtMainStatus.setText(getString(R.string.mediNETConnected)); + } else if (getMeditationAssistant().getMediNET().status + .equals("connectingasf")) { + txtMainStatus.setText(getString(R.string.mediNETConnecting)); + } else { + txtMainStatus.setText(""); + } + } + + btnMeditationStreak.postInvalidate(); + txtMainStatus.postInvalidate(); + } + + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + setIntent(intent); + + if (getIntent() != null) { + Log.d("MeditationAssistant", "Intent for MainActivity: " + + getIntent().toString()); + if (getIntent().getAction() != null) { + if (getIntent().getAction().equals("widgetclick")) { + if (!getMeditationAssistant().getMediNET().status + .equals("success")) { + getMeditationAssistant().getMediNET().connect(); + } + } else if (getIntent().getAction().equals("notificationPause")) { + if (getMeditationAssistant().getTimeStartMeditate() > 0 && !getMeditationAssistant().ispaused) { + updateMeditate(false, false); + pressMeditate(new View(getApplicationContext())); + } + } else if (getIntent().getAction().equals("notificationEnd")) { + if (getMeditationAssistant().getTimeStartMeditate() > 0) { + longPressMeditate(new View(getApplicationContext())); + } + } + } + + if (intent.getBooleanExtra("wakeup", false)) { + Boolean fullWakeUp = intent.getBooleanExtra("fullwakeup", false); + Boolean wakeUpStart = intent.getBooleanExtra("wakeupstart", false); + Boolean wakeUpInterval = intent.getBooleanExtra("wakeupinterval", false); + Log.d("MeditationAssistant", "ALARM RECEIVER INTEGRATED: Received broadcast - Full: " + (fullWakeUp ? "Full" : "Partial") + " - Start/interval: " + (wakeUpStart ? "Start" : (wakeUpInterval ? "Interval" : "Neither"))); + + WakeLocker.acquire(getApplicationContext(), fullWakeUp); + + handler.removeCallbacks(clearWakeLock); + handler.postDelayed(clearWakeLock, 7000); + + if (intent.getBooleanExtra("wakeupstart", false)) { + handler.postDelayed(meditateRunnable, 50); + } else if (intent.getBooleanExtra("wakeupinterval", false)) { + if (getMeditationAssistant().getTimeStartMeditate() > 0) { + if (getMeditationAssistant().getTimeToStopMeditate() != 0 + && getMeditationAssistant().getTimeToStopMeditate() + - (System.currentTimeMillis() / 1000) < 30 && !getMeditationAssistant().getPrefs().getBoolean("pref_softfinish", false)) { + Log.d("MeditationAssistant", "Interval - final 30 seconds, not firing"); + return; // No interval sounds during the final 30 seconds + } + + String interval_limit = getMeditationAssistant().getPrefs().getString("pref_interval_count", ""); + if (interval_limit.equals("")) { + interval_limit = "0"; + } + if (Integer.valueOf(interval_limit) > 0 && intervals >= Integer.valueOf(interval_limit)) { + Log.d("MeditationAssistant", "Interval - reached interval limit, not firing A"); + return; // No further intervals + } + + if (!getMeditationAssistant().getPrefs().getString("pref_meditation_sound_interval", "") + .equals("none") || getMeditationAssistant().vibrationEnabled()) { + if (getMeditationAssistant().getTimeToStopMeditate() == -1 + || ((System.currentTimeMillis() / 1000) > getMeditationAssistant().getTimeToStopMeditate() && (System.currentTimeMillis() / 1000) - getMeditationAssistant().getTimeToStopMeditate() >= 5) || getMeditationAssistant().getTimeToStopMeditate() + - (System.currentTimeMillis() / 1000) >= 5) { // Not within last 5 seconds + if (!getMeditationAssistant().getPrefs().getString("pref_meditation_sound_interval", "") + .equals("none")) { + stopMediaPlayer(); + mMediaPlayer = null; + if (getMeditationAssistant().getPrefs().getString("pref_meditation_sound_interval", "") + .equals("custom")) { + String soundpath = getMeditationAssistant().getPrefs().getString( + "pref_meditation_sound_interval_custom", ""); + if (!soundpath.equals("")) { + try { + mMediaPlayer = MediaPlayer.create( + getApplicationContext(), + Uri.parse(soundpath)); + } catch (Exception e) { + e.printStackTrace(); + } + } + } else { + mMediaPlayer = MediaPlayer + .create(getApplicationContext(), + MeditationSounds.getMeditationSound(getMeditationAssistant().getPrefs().getString( + "pref_meditation_sound_interval", + "")) + ); + } + + if (mMediaPlayer != null) { + mMediaPlayer + .setOnCompletionListener(new MediaPlayer.OnCompletionListener() { + + @Override + public void onCompletion(MediaPlayer mp) { + mp.release(); + WakeLocker.release(); + } + }); + + WakeLocker.acquire(getApplicationContext(), false); + mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); + + mMediaPlayer + .setOnPreparedListener(new MediaPlayer.OnPreparedListener() { + @Override + public void onPrepared( + MediaPlayer mp) { + mp.start(); + } + }); + //mMediaPlayer.prepareAsync(); + } + } + + getMeditationAssistant().vibrateDevice(); + } + + long interval = Math.max( + getMeditationAssistant().timePreferenceValueToSeconds(getMeditationAssistant().getPrefs().getString("pref_session_interval", "00:00"), "00:00"), 0); + Log.d("MeditationAssistant", "Interval is set to " + String.valueOf(interval) + " seconds"); + + if (interval > 0 && (getMeditationAssistant().getTimeToStopMeditate() == -1 + || ((getMeditationAssistant().getTimeToStopMeditate() + - (System.currentTimeMillis() / 1000)) > (interval + 30)) || getMeditationAssistant().getPrefs().getBoolean("pref_softfinish", false))) { + intervals++; + + if (Integer.valueOf(interval_limit) > 0 && intervals >= Integer.valueOf(interval_limit)) { + Log.d("MeditationAssistant", "Interval - reached interval limit, not firing B"); + return; // No further intervals + } + + Calendar cal = Calendar.getInstance(); + cal.add(Calendar.SECOND, (int) interval); + + Log.d("MeditationAssistant", "Setting INTERVAL WAKEUP alarm for " + + String.valueOf(cal.getTimeInMillis()) + " (Now: " + + System.currentTimeMillis() + ", in: " + String.valueOf((cal.getTimeInMillis() - System.currentTimeMillis()) / 1000) + ") - TOTAL TIME LEFT: " + String.valueOf(getMeditationAssistant().getTimeToStopMeditate() + - (System.currentTimeMillis() / 1000))); + + Intent intent_interval = new Intent( + getApplicationContext(), MainActivity.class); + intent_interval.putExtra("wakeup", true); + intent_interval.putExtra("wakeupinterval", true); + intent_interval.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); + intent_interval.setAction(BROADCAST_ACTION_ALARM); + pendingintent_interval = PendingIntent.getActivity( + getApplicationContext(), ID_INTERVAL, + intent_interval, PendingIntent.FLAG_CANCEL_CURRENT); + am_interval = (AlarmManager) getSystemService(Context.ALARM_SERVICE); + if (Build.VERSION.SDK_INT >= 19) { + am_interval.setExact(AlarmManager.RTC_WAKEUP, + cal.getTimeInMillis(), pendingintent_interval); + } else { + am_interval.set(AlarmManager.RTC_WAKEUP, + cal.getTimeInMillis(), pendingintent_interval); + } + } else { + Log.d("MeditationAssistant", "Skipping INTERVAL WAKEUP alarm"); + } + } + } + } + + if (fullWakeUp) { + if (getMeditationAssistant().getPrefs().getBoolean("pref_softfinish", false)) { + if (!getMeditationAssistant().getPrefs().getString("pref_meditation_sound_finish", "") + .equals("none")) { + stopMediaPlayer(); + mMediaPlayer = null; + if (getMeditationAssistant().getPrefs().getString("pref_meditation_sound_finish", "") + .equals("custom")) { + String soundpath = getMeditationAssistant().getPrefs().getString( + "pref_meditation_sound_finish_custom", ""); + if (!soundpath.equals("")) { + try { + mMediaPlayer = MediaPlayer.create( + getApplicationContext(), + Uri.parse(soundpath)); + } catch (Exception e) { + e.printStackTrace(); + } + } + } else { + mMediaPlayer = MediaPlayer + .create(getApplicationContext(), + MeditationSounds.getMeditationSound(getMeditationAssistant().getPrefs().getString( + "pref_meditation_sound_finish", + "")) + ); + } + + if (mMediaPlayer != null) { + mMediaPlayer + .setOnCompletionListener(new MediaPlayer.OnCompletionListener() { + + @Override + public void onCompletion(MediaPlayer mp) { + mp.release(); + WakeLocker.release(); + } + }); + + WakeLocker.acquire(getApplicationContext(), false); + mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); + mMediaPlayer + .setOnPreparedListener(new MediaPlayer.OnPreparedListener() { + @Override + public void onPrepared( + MediaPlayer mp) { + mp.start(); + } + }); + //mMediaPlayer.prepareAsync(); + } + } + + getMeditationAssistant().vibrateDevice(); + } else { + Intent openAlarmReceiverActivity = new Intent(getApplicationContext(), CompleteActivity.class); + openAlarmReceiverActivity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + openAlarmReceiverActivity.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); + startActivity(openAlarmReceiverActivity); + } + } + } + } + } + + public void updateTextsAsync() { + Log.d("MeditationAssistant", "Update texts async: begin"); + runOnUiThread(new Runnable() { + + @Override + public void run() { + Log.d("MeditationAssistant", "Update texts async: run"); + updateTexts(); + } + }); + } + + public void updateMeditate(boolean setDisabled, boolean complete) { + Button btnMeditate = (Button) findViewById(R.id.btnMeditate); + if (getMeditationAssistant().ispaused) { + btnMeditate.setText(getString(R.string.resumeOrEnd)); + return; + } + + //Log.d("MeditationAssistant", "updateMeditate: " + String.valueOf(getMeditationAssistant() .getTimeToStopMeditate())); + TextView txtTimer = (TextView) findViewById(R.id.txtTimer); + TextView txtDurationSeconds = (TextView) findViewById(R.id.txtDurationSeconds); + ViewSwitcher switchTimer = (ViewSwitcher) findViewById(R.id.switchTimer); + EditText editDuration = (EditText) findViewById(R.id.editDuration); + + FrameLayout.LayoutParams txtTimerLayoutParams = new FrameLayout.LayoutParams( + android.view.ViewGroup.LayoutParams.MATCH_PARENT, + android.view.ViewGroup.LayoutParams.WRAP_CONTENT); + txtTimerLayoutParams.setMargins(0, -23, 0, -11); + txtTimerLayoutParams.gravity = Gravity.CENTER; + + RelativeLayout.LayoutParams editDurationLayoutParams = new RelativeLayout.LayoutParams( + android.view.ViewGroup.LayoutParams.MATCH_PARENT, + android.view.ViewGroup.LayoutParams.WRAP_CONTENT); + editDurationLayoutParams.setMargins(0, -23, 0, -11); + //editDurationLayoutParams.gravity = Gravity.CENTER; not supported with RelativeLayout? + + long duration = 0; + Long timestamp = System.currentTimeMillis() / 1000; + + new Throwable().getStackTrace(); + if (getMeditationAssistant().getTimeToStopMeditate() == -1 + || getMeditationAssistant().getTimeToStopMeditate() > 0) { + if (getMeditationAssistant().getTimeToStopMeditate() != -1) { + if (getMeditationAssistant().getPrefs().getBoolean("pref_softfinish", false) && timestamp > getMeditationAssistant().getTimeToStopMeditate()) { + duration = timestamp - getMeditationAssistant() + .getTimeStartMeditate(); + } else { + duration = Math.min(getMeditationAssistant() + .getTimeToStopMeditate() - timestamp, + getMeditationAssistant().getTimeToStopMeditate() + - getMeditationAssistant() + .getTimeStartMeditate() + ); + } + } else { + duration = timestamp + - getMeditationAssistant().getTimeStartMeditate(); + } + + switchTimer.setClickable(false); + } else { + resetScreenBrightness(); + getMeditationAssistant().unsetNotificationControl(); + + switchTimer.setClickable(true); + } + + if (complete) { + Log.d("MeditationAssistant", "Session complete"); + } else if (getMeditationAssistant().getTimeToStopMeditate() == -1 || (getMeditationAssistant().getTimeToStopMeditate() > 0 && timestamp > getMeditationAssistant().getTimeToStopMeditate() && getMeditationAssistant().getPrefs().getBoolean("pref_softfinish", false))) { + duration -= getMeditationAssistant().pausetime; + + if (timestamp >= getMeditationAssistant().getTimeStartMeditate()) { + int hoursSince = (int) duration / 3600; + int minutesSince = ((int) duration % 3600) / 60; + txtTimer.setText(String.valueOf(hoursSince) + ":" + + String.format("%02d", minutesSince)); + } else { + txtTimer.setText(getString(R.string.ignore_om)); + } + } else if (duration > 0) { + int hoursLeft = (int) duration / 3600; + int minutesLeft = ((int) duration % 3600) / 60; + if (minutesLeft == 60) { + hoursLeft += 1; + minutesLeft = 0; + } + + txtTimer.setText(String.valueOf(hoursLeft) + ":" + + String.format("%02d", minutesLeft)); + } + + if (getMeditationAssistant().getTimeToStopMeditate() == -1 + || duration > 0 || (getMeditationAssistant().getTimeToStopMeditate() > 0 && getMeditationAssistant().getPrefs().getBoolean("pref_softfinish", false))) { + long delayRemaining = getMeditationAssistant() + .getTimeStartMeditate() - timestamp; + + findViewById(R.id.btnMeditate).setEnabled(true); + + if (delayRemaining > 0) { + btnMeditate.setText(getString(R.string.tapToSkip)); + getMeditationAssistant().setAlphaCompat(txtDurationSeconds, 0.75f); + + if (getMeditationAssistant().getTimerMode().equals("untimed")) { + txtTimerLayoutParams.setMargins(0, 0, 0, 0); + editDurationLayoutParams.setMargins(0, 0, 0, 0); + } + } else { + setVolumeControlStream(AudioManager.USE_DEFAULT_STREAM_TYPE); + + btnMeditate.setText(getString(R.string.pauseOrEnd)); + getMeditationAssistant().setAlphaCompat(txtDurationSeconds, 1f); + } + + if (getMeditationAssistant().getPrefs().getBoolean("pref_display_seconds", true)) { + if (getMeditationAssistant().getTimeStartMeditate() == timestamp + || getMeditationAssistant().getTimeToStopMeditate() == timestamp) { + txtDurationSeconds.setText(getString(R.string.ignore_omkara)); + } else if (getMeditationAssistant().getTimeStartMeditate() < timestamp) { + txtDurationSeconds.setText(String.valueOf(duration % 60)); + } else { + if (delayRemaining >= 60) { + txtDurationSeconds.setText(String.format("%d", + (int) delayRemaining / 60) + + ":" + + String.format("%02d", delayRemaining % 60)); + } else { + txtDurationSeconds.setText(String + .valueOf(delayRemaining % 60)); + } + } + } + } else { + txtDurationSeconds.setText(""); + findViewById(R.id.btnMeditate).setEnabled(true); + btnMeditate.setText(getString(R.string.meditate)); + getMeditationAssistant().setAlphaCompat(txtDurationSeconds, 1.0f); + + if (getMeditationAssistant().getTimerMode().equals("timed")) { + txtTimerLayoutParams.setMargins(0, -23, 0, -11); + editDurationLayoutParams.setMargins(0, -23, 0, -11); + txtTimer.setText(getMeditationAssistant().getPrefs().getString("timerHours", "0") + + ":" + + String.format("%02d", Integer.valueOf(getMeditationAssistant().getPrefs().getString("timerMinutes", "15")))); + } else if (getMeditationAssistant().getTimerMode().equals("endat")) { + txtTimerLayoutParams.setMargins(0, -23, 0, -11); + editDurationLayoutParams.setMargins(0, -23, 0, -11); + txtTimer.setText(getMeditationAssistant().getPrefs().getString("timerHoursEndAt", "0") + + ":" + + String.format("%02d", Integer.valueOf(getMeditationAssistant().getPrefs().getString("timerMinutesEndAt", "0")))); + txtDurationSeconds.setText(getString(R.string.endAt).toLowerCase()); + } else { + txtTimerLayoutParams.setMargins(0, 0, 0, 0); + editDurationLayoutParams.setMargins(0, 0, 0, 0); + txtTimer.setText(getString(R.string.ignore_om)); + } + } + + if (getMeditationAssistant().getTimeStartMeditate() > timestamp) { + if (!txtDurationSeconds.getText().toString().equals("")) { + getMeditationAssistant().setDurationFormatted( + txtDurationSeconds.getText().toString()); + } + } else if (getMeditationAssistant().getTimeStartMeditate() > 0) { + if (txtDurationSeconds.getText().toString().equals("")) { + getMeditationAssistant().setDurationFormatted( + txtTimer.getText().toString()); + } else { + String secondsFormatted = txtDurationSeconds.getText() + .toString(); + if (secondsFormatted.length() == 1 + && String.valueOf(Integer.valueOf(secondsFormatted)) + .equals(secondsFormatted)) { + secondsFormatted = "0" + secondsFormatted; + } + + getMeditationAssistant().setDurationFormatted( + txtTimer.getText().toString() + ":" + secondsFormatted); + } + } + + //Log.d("MeditationAssistant", "DURATION SECONDS: " + String.valueOf(getMeditationAssistant().getEditingDuration())); + + if (getMeditationAssistant().getEditingDuration()) { + getMeditationAssistant().setAlphaCompat(txtDurationSeconds, 0f); + } else { + getMeditationAssistant().setAlphaCompat(txtDurationSeconds, 1f); + } + + txtTimer.setLayoutParams(txtTimerLayoutParams); + editDuration.setLayoutParams(editDurationLayoutParams); + + if (setDisabled) { + btnMeditate.setText(getString(R.string.meditate)); + findViewById(R.id.btnMeditate).setEnabled(false); + } + } + + public void startRunnable() { + if (getMeditationAssistant().getRunnableStopped()) { + Log.d("MeditationAssistant", "Starting runnable"); + Runnable runnable = new Runnable() { + @Override + public void run() { + handler.removeCallbacks(this); + boolean sessionEnding = false; + + if (getMeditationAssistant().getScreenOff()) { + getMeditationAssistant().setRunnableStopped(true); + Log.d("MeditationAssistant", + "Screen off, stopping runnable..."); + } + + if (getMeditationAssistant().pendingNotificationAction + .equals("exit")) { + getMeditationAssistant().pendingNotificationAction = ""; + + if (getMeditationAssistant().getTimeStartMeditate() > 0) { + longPressMeditate(null); + } + finish(); + return; + } else if (getMeditationAssistant().pendingNotificationAction + .equals("end")) { + getMeditationAssistant().pendingNotificationAction = ""; + sessionEnding = true; + + if (getMeditationAssistant().getTimeStartMeditate() > 0) { + longPressMeditate(new View(getApplicationContext())); + } + } + + if (sessionEnding) { + getMeditationAssistant().setRunnableStopped(true); + } else if (getMeditationAssistant().getTimeToStopMeditate() == -1 + || getMeditationAssistant().getTimeToStopMeditate() > (System + .currentTimeMillis() / 1000) || (getMeditationAssistant().getTimeToStopMeditate() != 0 && getMeditationAssistant().getPrefs().getBoolean("pref_softfinish", false))) { + updateMeditate(false, false); + if (!getMeditationAssistant().getScreenOff()) { + handler.postDelayed(this, 250); + } + } else { + Log.d("MeditationAssistant", + "Stopping - start:" + + String.valueOf(getMeditationAssistant() + .getTimeStartMeditate()) + + " stop:" + + String.valueOf(getMeditationAssistant() + .getTimeToStopMeditate()) + ); + + getMeditationAssistant().setRunnableStopped(true); + if (getMeditationAssistant().getTimeToStopMeditate() != 0) { + getMeditationAssistant().setTimeToStopMeditate(0); // Don't trigger the last_reminder change unless necessary + } + updateMeditate(false, (getMeditationAssistant() + .getTimeStartMeditate() > 0)); + } + } + }; + getMeditationAssistant().setRunnableStopped(false); + handler.postDelayed(runnable, 100); + } else { + Log.d("MeditationAssistant", + "Not starting runnable. Stopped flag is not set."); + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode == MeditationAssistant.REQUEST_FIT) { + getMeditationAssistant().googleAPIAuthInProgress = false; + if (resultCode == RESULT_OK) { + // Make sure the app is not already connected or attempting to connect + if (!getMeditationAssistant().googleClient.isConnecting() && !getMeditationAssistant().googleClient.isConnected()) { + getMeditationAssistant().googleClient.connect(); + + getMeditationAssistant().sendFitData(); + } + } + } + } + + public void pressCommunity(View view) { + if (sv != null && sv.isShown()) { + try { + sv.hide(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + getMeditationAssistant().getMediNET().browseTo(this, "community"); + } + + public void pressMediNET(View view) { + Log.d("MeditationAssistant", "Open medinet: " + getMeditationAssistant().getMediNETKey()); + + if (sv != null && sv.isShown()) { + try { + sv.hide(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + if (!getMeditationAssistant().getMediNETKey().equals("")) { + if (!getMeditationAssistant().getMediNET().status.equals("success")) { + getMeditationAssistant().getMediNET().connect(); + } else { + DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + switch (which) { + case DialogInterface.BUTTON_POSITIVE: + getMeditationAssistant().getMediNET().signOut(); + break; + + case DialogInterface.BUTTON_NEGATIVE: + break; + } + } + }; + + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setIcon( + getResources().getDrawable( + getTheme().obtainStyledAttributes( + getMeditationAssistant().getMATheme(), + new int[]{R.attr.actionIconSignOut}) + .getResourceId(0, 0) + ) + ) + .setTitle( + getString(R.string.signOutOfMediNETConfirmTitle)) + .setMessage( + String.format( + getString(R.string.signOutOfMediNETConfirm), + getMeditationAssistant() + .getMediNETProvider() + ) + ) + .setPositiveButton(getString(R.string.signOut), + dialogClickListener) + .setNegativeButton(getString(R.string.cancel), + dialogClickListener).show(); + } + } else { + getMeditationAssistant().getMediNET().askToSignIn(); + } + } + + public void stopMediaPlayer() { + if (mMediaPlayer != null) { + mMediaPlayer.release(); + } + } + + public void resetScreenBrightness() { + WindowManager.LayoutParams windowParams = getWindow() + .getAttributes(); + windowParams.screenBrightness = -1; + getWindow().setAttributes(windowParams); + } + + public MeditationAssistant getMeditationAssistant() { + if (ma == null) { + ma = (MeditationAssistant) this.getApplication(); + } + return ma; + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + if (sv != null && sv.isShown()) { + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + } + } + + @Override + public void onShowcaseViewHide(ShowcaseView showcaseView) { + if (!finishedTutorial) { + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); + } + sv = null; + } + + @Override + public void onShowcaseViewDidHide(ShowcaseView showcaseView) { + sv = null; + } + + @Override + public void onShowcaseViewShow(ShowcaseView showcaseView) { + + } +} diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MediNET.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MediNET.java new file mode 100644 index 0000000..c5e8382 --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MediNET.java @@ -0,0 +1,417 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.Intent; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.os.Handler; +import android.support.v4.app.FragmentActivity; +import android.util.Log; +import android.view.View; +import android.widget.ImageButton; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; + +/** + * Created by root on 11/2/13. + */ +public class MediNET { + public static Integer version = 5; + public String status = "disconnected"; + public String result = ""; + public MainActivity activity; + public MeditationSession session = new MeditationSession(); + public String provider = ""; + public ArrayList result_sessions = null; + public String announcement = ""; + private Boolean debug = false; + private MeditationAssistant ma = null; + private MediNETTask task = null; + private Handler handler = new Handler(); + private Runnable runnable; + private Runnable runnable2; + private Boolean runnable_finished = true; + private AlertDialog alertDialog = null; + private String browsetopage = ""; + + public MediNET(MainActivity _activity) { + activity = _activity; + runnable = new Runnable() { + @Override + public void run() { + handler.removeCallbacks(this); + getMeditationAssistant().updateWidgets(); + runnable_finished = true; + } + }; + runnable2 = new Runnable() { + @Override + public void run() { + handler.removeCallbacks(this); + Log.d("MeditationAssistant", "Delayed update() running..."); + getMeditationAssistant().getMediNET().updated(); + } + }; + } + + public static String durationToTimerString(long duration, boolean countDown) { + int hours = (int) duration / 3600; + int minutes = ((int) duration % 3600) / 60; + if (countDown) { + minutes += 1; + } + + return String.valueOf(hours) + ":" + String.format("%02d", minutes); + } + + public void askToSignIn() { + /*if (activity == null || activity.stopped) { + Log.d("MeditationAssistant", + "MainActivity null or stopped, restarting... Stopped: " + + activity.stopped.toString());*/ + if (activity == null) { + Intent openActivity = new Intent(getMeditationAssistant() + .getApplicationContext(), MainActivity.class); + openActivity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + openActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + + handler.postDelayed(new Runnable() { + + @Override + public void run() { + Log.d("MeditationAssistant", + "Open MainActivity runnable is now running..."); + askToSignIn(); + } + }, 400); + + getMeditationAssistant().getApplicationContext().startActivity( + openActivity); + return; + } + + activity.runOnUiThread(new Runnable() { + + @Override + public void run() { + if (activity == null) { + Log.d("MeditationAssistant", + "askToSignIn activity is null, returning..."); + return; + } + getMeditationAssistant().showSignInDialog(activity); + } + }); + } + + public void browseTo(MainActivity act, String page) { + activity = act; + browsetopage = page; + + if (status.equals("success") || page.equals("community")) { + act.runOnUiThread(new Runnable() { + @Override + public void run() { + Intent openActivity = new Intent(activity + .getApplicationContext(), MediNETActivity.class); + openActivity.putExtra("page", browsetopage); + openActivity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + openActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + getMeditationAssistant().getApplicationContext() + .startActivity(openActivity); + } + }); + } else { + askToSignIn(); + } + } + + public void resetSession() { + session = new MeditationSession(); + } + + public boolean connect() { + ConnectivityManager cm = (ConnectivityManager) getMeditationAssistant() + .getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo netInfo = cm.getActiveNetworkInfo(); + Boolean internetconnected = (netInfo != null && netInfo.isConnectedOrConnecting()); + + if (!internetconnected) { + Log.d("MeditationAssistant", + "Cancelled MediNET connection: Internet isn't connected"); + return false; + } + + if (getMeditationAssistant().getMediNETKey().equals("")) { + askToSignIn(); + return false; + } + + runnable_finished = true; + if (!this.status.equals("success")) { + JSONObject jobj = new JSONObject(); + try { + Log.d("MeditationAssistant", "Begin connect"); + jobj.put("x", getMeditationAssistant().getMediNETKey()); + } catch (JSONException e1) { + e1.printStackTrace(); + } + + // display json object being sent + // Log.d("MeditationAssistant", "JSON object send: " + + // jobj.toString()); + + status = "connecting"; + + updated(); + if (task != null) { + task.cancel(true); + } + task = new MediNETTask(); + task.action = "connect"; + task.context = activity.getApplicationContext(); + + Log.d("MeditationAssistant", "Executing MediNET Task"); + task.doIt(this); + return true; + } + updated(); + return false; + } + + public Boolean deleteSessionByStarted(long started) { + if (task != null) { + task.cancel(true); + } + task = new MediNETTask(); + task.action = "deletesession"; + task.actionextra = String.valueOf(started); + task.context = activity.getApplicationContext(); + if (debug) { + task.nextURL += "&debug77"; + } + task.doIt(this); + return true; + } + + public void signInWithAuthToken(String authtoken) { + if (task != null) { + task.cancel(true); + } + + task = new MediNETTask(); + task.action = "signin"; + task.actionextra = authtoken; + task.context = activity.getApplicationContext(); + + task.doIt(this); + } + + public MainActivity getActivity() { + return activity; + } + + public void setActivity(MainActivity activity) { + this.activity = activity; + } + + public MeditationAssistant getMeditationAssistant() { + if (ma == null) { + ma = (MeditationAssistant) this.activity.getApplication(); + } + return ma; + } + + public MeditationSession getSession() { + return session; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public Boolean postSession() { + return postSession(false, null); + } + + public Boolean postSession(Boolean manualposting, FragmentActivity act) { + Log.d("MeditationAssistant", "Session.toString(): " + + this.getSession().export().toString()); + if (task != null) { + task.cancel(true); + } + task = new MediNETTask(); + task.fragment_activity = act; + task.action = "postsession"; + if (manualposting) { + task.actionextra = "manualposting"; + } else { + // Only add streak if there isn't already a session for today + if (getMeditationAssistant().db.numSessionsByDate(getMeditationAssistant().db.timestampToAPIDate(getSession().completed * 1000)) == 0) { + getMeditationAssistant().addMeditationStreak(); + if (getSession().streakday == 0) { + getSession().streakday = getMeditationAssistant().getMeditationStreak(); + } + } + } + task.context = activity.getApplicationContext(); + if (debug) { + task.nextURL += "&debug77"; + } + task.doIt(this); + return true; + } + + public void saveSession(Boolean manualposting, Boolean posted) { + Long postedlong = (long) 0; + if (posted) { + postedlong = (long) 1; + } + + // Only add streak if there isn't already a session for that day + if (getMeditationAssistant().db.numSessionsByDate(getMeditationAssistant().db.timestampToAPIDate(getSession().completed * 1000)) == 0) { + if (!manualposting) { + getMeditationAssistant().addMeditationStreak(); + + if (getSession().streakday == 0) { + getSession().streakday = getMeditationAssistant().getMeditationStreak(); + } + } else { + Calendar c_midnight = new GregorianCalendar(); + c_midnight.setTime(new Date()); + c_midnight.set(Calendar.HOUR_OF_DAY, 0); + c_midnight.set(Calendar.MINUTE, 0); + c_midnight.set(Calendar.SECOND, 0); + c_midnight.set(Calendar.MILLISECOND, 0); + + if ((c_midnight.getTimeInMillis() / 1000) < getSession().started && (getSession().started - (c_midnight.getTimeInMillis() / 1000)) < 86400) { // After midnight today + getMeditationAssistant().addMeditationStreak(); + + if (getSession().streakday == 0) { + getSession().streakday = getMeditationAssistant().getMeditationStreak(); + } + } else { + c_midnight.add(Calendar.DATE, -1); + + if ((c_midnight.getTimeInMillis() / 1000) < getSession().started) { // After midnight yesterday + getMeditationAssistant().addMeditationStreak(false); + + if (getSession().streakday == 0) { + getSession().streakday = getMeditationAssistant().getMeditationStreak(); + } + } + } + } + } + + getMeditationAssistant().db.addSession(new SessionSQL( + getSession().started, getSession().completed, getSession().length, + getSession().message, postedlong, getSession().streakday)); + + resetSession(); + + if (!manualposting) { + getMeditationAssistant().asktorate = true; + } + } + + public void selectProvider(View v) { + ImageButton img = (ImageButton) v; + + Intent intent = new Intent(getMeditationAssistant() + .getApplicationContext(), MediNETActivity.class); + if (img.getId() == R.id.btnGoogle) { + intent.putExtra("provider", "Google"); + } else if (img.getId() == R.id.btnFacebook) { + intent.putExtra("provider", "Facebook"); + } else if (img.getId() == R.id.btnAOL) { + intent.putExtra("provider", "AOL"); + } else if (img.getId() == R.id.btnTwitter) { + intent.putExtra("provider", "Twitter"); + } else if (img.getId() == R.id.btnLive) { + intent.putExtra("provider", "Live"); + } else if (img.getId() == R.id.btnOpenID) { + intent.putExtra("provider", "OpenID"); + } + + getMeditationAssistant().getApplicationContext().startActivity(intent); + } + + public void signOut() { + Log.d("MeditationAssistant", "Signing out"); + if (task != null) { + task.cancel(true); + } + task = new MediNETTask(); + task.action = "signout"; + task.context = activity.getApplicationContext(); + if (debug) { + task.nextURL += "&debug77"; + } + task.doIt(this); + + status = "stopped"; + getMeditationAssistant().setMediNETKey("", ""); + if (!getMeditationAssistant().getPrefs().getBoolean("pref_autosignin", false)) { + getMeditationAssistant().getPrefs().edit().putString("key", "").apply(); + } + //getMeditationAssistant().setMeditationStreak(0, 0); + updated(); + } + + public Boolean syncSessions() { + getMeditationAssistant().shortToast(getMeditationAssistant().getString(R.string.downloadingSessions)); + if (task != null) { + task.cancel(true); + } + task = new MediNETTask(); + task.action = "syncsessions"; + task.context = activity.getApplicationContext(); + if (debug) { + task.nextURL += "&debug77"; + } + task.doIt(this); + return true; + } + + public Boolean uploadSessions() { + getMeditationAssistant().shortToast(getMeditationAssistant().getString(R.string.uploadingSessions)); + if (task != null) { + task.cancel(true); + } + task = new MediNETTask(); + task.action = "uploadsessions"; + task.context = activity.getApplicationContext(); + if (debug) { + task.nextURL += "&debug77"; + } + task.doIt(this); + return true; + } + + public void updateAfterDelay() { + Log.d("MeditationAssistant", "Update after delay: " + status); + handler.postDelayed(runnable2, 1750); + } + + public void updated() { + Log.d("MeditationAssistant", "updated() " + status); + + activity.updateTextsAsync(); + if (runnable_finished) { + runnable_finished = false; + handler.postDelayed(runnable, 750); + } + } +} diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MediNETActivity.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MediNETActivity.java new file mode 100644 index 0000000..52cb4d9 --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MediNETActivity.java @@ -0,0 +1,566 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.res.Configuration; +import android.graphics.Color; +import android.net.MailTo; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.util.Log; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.Window; +import android.webkit.CookieManager; +import android.webkit.CookieSyncManager; +import android.webkit.WebChromeClient; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import android.widget.FrameLayout; +import android.widget.RelativeLayout; + +import com.google.android.gms.ads.AdRequest; +import com.google.android.gms.ads.AdView; +import com.google.android.gms.analytics.GoogleAnalytics; + +import org.apache.http.cookie.Cookie; + +import java.util.Date; +import java.util.List; +import java.util.TimeZone; + +public class MediNETActivity extends Activity { + final Activity activity = this; + protected FrameLayout webViewPlaceholder = null; + protected WebView webView = null; + private AdView av = null; + private String provider = ""; + private MeditationAssistant ma = null; + private Handler handler = new Handler(); + private boolean signing_in = false; + private boolean hide_refresh = false; + + public static Intent newEmailIntent(Context context, String address, String subject, String body, String cc) { + Intent intent = new Intent(Intent.ACTION_SEND); + intent.putExtra(Intent.EXTRA_EMAIL, new String[]{address}); + intent.putExtra(Intent.EXTRA_TEXT, body); + intent.putExtra(Intent.EXTRA_SUBJECT, subject); + intent.putExtra(Intent.EXTRA_CC, cc); + intent.setType("message/rfc822"); + return intent; + } + + public MeditationAssistant getMeditationAssistant() { + if (ma == null) { + ma = (MeditationAssistant) this.getApplication(); + } + return ma; + } + + public String getPageUrl(String page) { + TimeZone tz = TimeZone.getDefault(); + Date now = new Date(); + + return "http://medinet.ftp.sh/client_android.php?v=" + + MediNET.version.toString() + "&avn=" + + String.valueOf(getMeditationAssistant().getMAAppVersionNumber()) + "&page=" + page + "&th=" + + ma.getMAThemeString() + "&tz=" + + String.valueOf(tz.getOffset(now.getTime())) + "&x=" + + getMeditationAssistant().getMediNETKey(); + } + + public void goTo(String go_to) { + String url; + + if (go_to.equals("Google") || go_to.equals("Facebook") + || go_to.equals("Twitter") || go_to.equals("AOL") + || go_to.equals("OpenID") || go_to.equals("Live") + || go_to.equals("LinkedIn")) { + setTitle(String.format(getString(R.string.signInWithProvider), + go_to)); + url = "http://medinet.ftp.sh/client_android_login.php?v=" + + MediNET.version.toString() + "&avn=" + + String.valueOf(getMeditationAssistant().getMAAppVersionNumber()) + "&provider=" + go_to; + provider = go_to; + signing_in = true; + } else if (go_to.equals("gpl") || go_to.equals("lgpl")) { + setTitle(""); + signing_in = true; + hide_refresh = true; + + if (go_to.equals("gpl")) { + url = "file:///android_asset/gpl.html"; + } else { + url = "file:///android_asset/lgpl.html"; + } + } else { + if (go_to.equals("community")) { + setTitle(getString(R.string.community)); + } else if (go_to.equals("sessions")) { + setTitle(getString(R.string.sessions)); + } else if (go_to.equals("account")) { + setTitle(getString(R.string.account)); + } else if (go_to.equals("forum")) { + setTitle(getString(R.string.forum)); + } else if (go_to.equals("groups")) { + setTitle(getString(R.string.groups)); + } else if (go_to.equals("signout")) { + + } else { + return; + } + + url = getPageUrl(go_to); + signing_in = false; + } + + Log.d("MeditationAssistant", go_to + " - Going to: " + url); + + webView.loadUrl(url); + setWindowBackground(); + } + + @SuppressLint({"AddJavascriptInterface", "SetJavaScriptEnabled"}) + protected void initUI(Boolean activityOnCreate) { + webViewPlaceholder = ((FrameLayout) findViewById(R.id.webViewPlaceholder)); + + if (webView == null) { + webView = new WebView(getApplicationContext()); + + // potential fixes for keeping zoom + // webView.getSettings().setLoadWithOverviewMode(true); + // webView.getSettings().setUseWideViewPort(true); + + webView.setWebChromeClient(new WebChromeClient() { + @Override + public void onProgressChanged(WebView view, int progress) { + if (Build.VERSION.SDK_INT >= 15) { // setProgress added API-15 + activity.setProgress(progress * 100); + } + } + }); + + webView.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + WebView.HitTestResult result = webView.getHitTestResult(); + Log.d("MeditationAssistant", "Hit test"); + if (result != null) { + if (result.getType() == WebView.HitTestResult.IMAGE_TYPE + || result.getType() == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE) { + Log.d("MeditationAssistant", + "Image: " + result.toString()); + Intent browserIntent = new Intent( + Intent.ACTION_VIEW, Uri.parse(result + .getExtra()) + ); + startActivity(browserIntent); + return true; + } else if (result.getType() == WebView.HitTestResult.SRC_ANCHOR_TYPE) { + Log.d("MeditationAssistant", + "Anchor: " + result.toString()); + Intent browserIntent = new Intent( + Intent.ACTION_VIEW, Uri.parse(result + .getExtra()) + ); + startActivity(browserIntent); + return true; + } + } + + return false; + } + }); + + webView.setHapticFeedbackEnabled(true); + webView.setLongClickable(true); + // webView.setInitialScale(getMeditationAssistant().getWebViewScale()); + + RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams( + RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT); + + webView.setLayoutParams(params); + webView.getSettings().setSupportZoom(true); + // webView.getSettings().setBuiltInZoomControls(true); + webView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY); + webView.setScrollbarFadingEnabled(true); + webView.getSettings().setLoadsImagesAutomatically(true); + + if (Build.VERSION.SDK_INT < 11) { + webView.getSettings(); + webView.setBackgroundColor(Color.TRANSPARENT); + } else { + // Fix background flicker + webView.getSettings(); + webView.setBackgroundColor(Color.argb(1, 0, 0, 0)); + } + + // JavaScript + webView.addJavascriptInterface( + new JavaScriptInterface(this, this.getApplicationContext()), + "MA"); + webView.getSettings().setJavaScriptEnabled(true); + + // Cookies + List cookies = getMeditationAssistant().getHttpClient() + .getCookieStore().getCookies(); + + if (!cookies.isEmpty()) { + CookieManager cookieManager = CookieManager.getInstance(); + + for (Cookie cookie : cookies) { + String cookieString = cookie.getName() + "=" + + cookie.getValue() + "; domain=" + + cookie.getDomain(); + cookieManager.setCookie("medinet.ftp.sh", cookieString); + CookieSyncManager.getInstance().sync(); + } + } + + webView.setWebViewClient(new WebViewClient() { + @Override + public void onPageFinished(WebView view, String url) { + if (Uri.parse(url) != null && Uri.parse(url).getHost() != null && Uri.parse(url).getHost().equals("medinet.ftp.sh")) { + if (webView.getTitle() != null + && !webView.getTitle().trim().equals("")) { + setTitle(webView.getTitle()); + } + signing_in = url.contains("/hybridauth/"); + } else { + /* + * setTitle(String.format(getString(R.string. + * signInWithProvider), provider)); + */ + } + + setWindowBackground(); + // view.setInitialScale(getMeditationAssistant().getWebViewScale()); + } + + @Override + public boolean shouldOverrideUrlLoading(WebView view, String url) { + /*getMeditationAssistant().setWebViewScale( + (int) (100 * view.getScale()));*/ + Log.d("MeditationAssistant", + "Signing_in: " + String.valueOf(signing_in) + " - " + + url + ); + if (url != null && url.startsWith("mailto:")) { + MailTo mt = MailTo.parse(url); + Intent i = newEmailIntent(MediNETActivity.this, mt.getTo(), mt.getSubject(), mt.getBody(), mt.getCc()); + startActivity(i); + view.reload(); + return true; + /*} else if (url != null && Uri.parse(url) != null && Uri.parse(url).getHost() != null + && !Uri.parse(url).getHost() + .equals("medinet.ftp.sh") + && webView.getUrl() != null + && Uri.parse(webView.getUrl()).getHost() != null && Uri.parse(webView.getUrl()).getHost() + .equals("medinet.ftp.sh") + && !webView.getUrl().contains("provider=OpenID")) { + + Log.d("MA", "!!!!!!!!!!!!!!!!! OPENING!!!"); + Intent browserIntent = new Intent(Intent.ACTION_VIEW, + Uri.parse(url)); + startActivity(browserIntent);*/ + } else { + view.loadUrl(url); + } + + Log.d("MA", Uri.parse(url).toString()); + Log.d("MA", Uri.parse(url).getHost()); + return true; + } + }); + + webView.getSettings().setSupportMultipleWindows(true); + webView.setWebChromeClient(new WebChromeClient() { + @Override + public boolean onCreateWindow(WebView view, boolean dialog, boolean userGesture, android.os.Message resultMsg) { + WebView.HitTestResult result = view.getHitTestResult(); + String data = result.getExtra(); + Context context = view.getContext(); + + context.startActivity(new Intent( + Intent.ACTION_VIEW, + Uri.parse(data)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); + + return false; + } + }); + } + + // webView.getSettings().setDefaultZoom(WebSettings.ZoomDensity.FAR); + webViewPlaceholder.addView(webView); + // webView.getSettings().setDefaultZoom(WebSettings.ZoomDensity.FAR); + + if (activityOnCreate) { + if (getIntent().hasExtra("provider")) { + provider = getIntent().getStringExtra("provider"); + if (provider.equals("Google") || provider.equals("Facebook") + || provider.equals("Twitter") || provider.equals("AOL") + || provider.equals("OpenID") || provider.equals("Live") + || provider.equals("LinkedIn")) { + signing_in = true; + goTo(provider); + } + } else if (getIntent().hasExtra("page") + && (getIntent().getStringExtra("page").equals("community") + || getIntent().getStringExtra("page").equals( + "sessions") + || getIntent().getStringExtra("page").equals( + "account") + || getIntent().getStringExtra("page").equals( + "groups") + || getIntent().getStringExtra("page").equals( + "forum") + || getIntent().getStringExtra("page").equals("gpl") || getIntent() + .getStringExtra("page").equals("lgpl"))) { + signing_in = false; + goTo(getIntent().getStringExtra("page")); + } + } else { + if (getPackageName().equals( + "sh.ftp.rocketninelabs.meditationassistant")) { + Log.d("MeditationAssistant", "Fetching ad"); + + // AdView av = new AdView(this, AdSize.SMART_BANNER, + // "a15110a172d3cff"); + av = (AdView) findViewById(R.id.adViewMediNET); + av.setVisibility(View.VISIBLE); + AdRequest adRequest = new AdRequest.Builder() + .addTestDevice(AdRequest.DEVICE_ID_EMULATOR) + .build(); + av.loadAd(adRequest); + + /* + * (new Thread() { public void run() { Looper.prepare(); AdView + * av = (AdView) findViewById(R.id.adViewMediNET); + * + * + * + * av.loadAd(adrequest); } }).start(); + */ + + } else { + // av.setVisibility(View.GONE); + } + } + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + if (webView != null) { + webViewPlaceholder.removeView(webView); + } + + super.onConfigurationChanged(newConfig); + + setContentView(R.layout.activity_medinet); + + initUI(false); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + requestWindowFeature(Window.FEATURE_PROGRESS); + super.onCreate(savedInstanceState); + + setTheme(getMeditationAssistant().getMATheme()); + setContentView(R.layout.activity_medinet); + getActionBar().setDisplayHomeAsUpEnabled(true); + + if (getPackageName() + .equals("sh.ftp.rocketninelabs.meditationassistant")) { + Log.d("MeditationAssistant", "Fetching ad"); + + // AdView av = new AdView(this, AdSize.SMART_BANNER, + // "a15110a172d3cff"); + av = (AdView) findViewById(R.id.adViewMediNET); + av.setVisibility(View.VISIBLE); + AdRequest adRequest = new AdRequest.Builder() + .addTestDevice(AdRequest.DEVICE_ID_EMULATOR) + .build(); + av.loadAd(adRequest); + } + + if (getMeditationAssistant().sendUsageReports()) { + getMeditationAssistant().getTracker(MeditationAssistant.TrackerName.APP_TRACKER); + } + + initUI(true); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.medinet, menu); + + return true; + } + + @Override + public void onDestroy() { + if (getMeditationAssistant().getMediNET() != null) { + if (getMeditationAssistant().getMediNET().getStatus() != null + && getMeditationAssistant().getMediNET().getStatus() + .equals("connecting")) { + getMeditationAssistant().getMediNET().setStatus("disconnected"); + } + getMeditationAssistant().getMediNET().updated(); + } + + if (av != null) { + av.destroy(); + } + + super.onDestroy(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if ((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()) { + webView.goBack(); + return true; + } + + return super.onKeyDown(keyCode, event); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + Log.d("MeditationAssistant", + "Selected menu item: " + String.valueOf(item.getItemId())); + int itemId = item.getItemId(); + if (itemId == android.R.id.home) { + finish(); + return true; + } else if (itemId == R.id.refreshMediNET) { + webView.loadUrl("javascript:window.location.reload(true)"); + return true; + } else if (itemId == R.id.menuMediNETCommunity) { + goTo("community"); + return true; + } else if (itemId == R.id.menuMediNETSessions) { + goTo("sessions"); + return true; + } else if (itemId == R.id.menuMediNETForum) { + goTo("forum"); + return true; + } else if (itemId == R.id.menuMediNETGroups) { + goTo("groups"); + return true; + } else if (itemId == R.id.menuMediNETAccount) { + goTo("account"); + return true; + } else if (itemId == R.id.menuMediNETBack) { + if (webView.canGoBack()) { + webView.goBack(); + } + return true; + } else if (itemId == R.id.menuMediNETForward) { + if (webView.canGoForward()) { + webView.goForward(); + } + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + protected void onPause() { + if (av != null) { + av.pause(); + } + CookieSyncManager.getInstance().stopSync(); + super.onStop(); + } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + if (signing_in) { + menu.findItem(R.id.menuMediNET).setVisible(false); + } else { + menu.findItem(R.id.menuMediNET).setVisible(true); + } + + if (hide_refresh) { + menu.findItem(R.id.refreshMediNET).setVisible(false); + } else { + menu.findItem(R.id.refreshMediNET).setVisible(true); + } + + super.onPrepareOptionsMenu(menu); + + return true; + } + + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) { + super.onRestoreInstanceState(savedInstanceState); + + webView.restoreState(savedInstanceState); + } + + @Override + protected void onResume() { + CookieSyncManager.getInstance().startSync(); + super.onResume(); + if (av != null) { + av.resume(); + } + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + + webView.saveState(outState); + } + + @Override + public void onStart() { + super.onStart(); + if (getMeditationAssistant().sendUsageReports()) { + GoogleAnalytics.getInstance(this).reportActivityStart(this); + } + } + + @Override + protected void onStop() { + super.onStop(); + if (getMeditationAssistant().sendUsageReports()) { + GoogleAnalytics.getInstance(this).reportActivityStop(this); + } + } + + public void setWindowBackground() { + if (getMeditationAssistant().getMATheme() != R.style.MeditationDarkTheme && getMeditationAssistant().getMATheme() != R.style.Buddhism) { + getWindow().setBackgroundDrawable( + getResources().getDrawable( + android.R.drawable.screen_background_light) + ); + } else { + /*getWindow() + .setBackgroundDrawable( + getResources().getDrawable( + android.R.drawable.background_holo_dark));*/ + webView.getSettings(); + if (signing_in) { + webView.setBackgroundColor(Color.WHITE); + } else { + if (Build.VERSION.SDK_INT < 11) { + webView.setBackgroundColor(Color.TRANSPARENT); + } else { + // Fix background flicker + webView.setBackgroundColor(Color.argb(1, 0, 0, 0)); + } + } + } + } +} diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MediNETTask.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MediNETTask.java new file mode 100644 index 0000000..2380f35 --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MediNETTask.java @@ -0,0 +1,479 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +import android.content.Context; +import android.os.AsyncTask; +import android.support.v4.app.FragmentActivity; +import android.util.Log; + +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.message.BasicNameValuePair; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.List; +import java.util.TimeZone; + +public class MediNETTask extends AsyncTask { + public Context context; + public String nextURL = null; + public String action = ""; + public String actionextra = ""; + public MediNET medinet; + public String x; + public FragmentActivity fragment_activity = null; + private BufferedReader webReader; + private MeditationAssistant ma = null; + private Crypt crypt = new Crypt(); + + @Override + protected MediNET doInBackground(MediNET... medinets) { + this.medinet = medinets[0]; + this.medinet.result = ""; + + if (isCancelled()) { + Log.d("MeditationAssistant", "Task cancelled"); + return this.medinet; + } + + TimeZone tz = TimeZone.getDefault(); + Date now = new Date(); + int offsetFromUTC = tz.getOffset(now.getTime()); + String appVersion = getMeditationAssistant().getMAAppVersion() + (getMeditationAssistant().getMAIsAppFull() ? "full" : "free"); + + if (this.nextURL == null) { + this.nextURL = "http://medinet.ftp.sh/client_android.php?v=" + + MediNET.version.toString() + "&av=" + + appVersion + "&avn=" + + String.valueOf(getMeditationAssistant().getMAAppVersionNumber()) + "&tz=" + + String.valueOf(offsetFromUTC); + } + + if (action.equals("signin")) { + this.nextURL = "http://medinet.ftp.sh/client_android_login_oauth2.php?v=" + + MediNET.version.toString() + "&av=" + + appVersion + "&avn=" + + String.valueOf(getMeditationAssistant().getMAAppVersionNumber()) + "&tz=" + + String.valueOf(offsetFromUTC) + "&token=" + actionextra; + } + + Log.d("MeditationAssistant", "URL => " + this.nextURL); + + HttpPost httpPost = new HttpPost(this.nextURL); + HttpResponse webResponse = null; + ArrayList sessionssql = null; + + try { + List nameValuePairs = new ArrayList(2); + nameValuePairs.add(new BasicNameValuePair("x", medinet + .getMeditationAssistant().getMediNETKey())); + + if (action.equals("connect")) { + nameValuePairs.add(new BasicNameValuePair("action", "connect")); + } else if (action.equals("postsession")) { + nameValuePairs.add(new BasicNameValuePair("postsession", Crypt + .bytesToHex(crypt.encrypt(medinet.getSession().export() + .toString())))); + if (actionextra.equals("manualposting")) { + nameValuePairs.add(new BasicNameValuePair("manualposting", + "true")); + } + } else if (action.equals("deletesession")) { + nameValuePairs.add(new BasicNameValuePair("action", + "deletesession")); // Session start time + nameValuePairs.add(new BasicNameValuePair("session", + actionextra)); + } else if (action.equals("syncsessions")) { + nameValuePairs.add(new BasicNameValuePair("action", + "syncsessions")); + } else if (action.equals("uploadsessions")) { + JSONArray jsonsessions = new JSONArray(); + sessionssql = getMeditationAssistant().db.getAllLocalSessions(); + + if (sessionssql.size() == 0) { + getMeditationAssistant().longToast( + medinet.activity, + getMeditationAssistant().getString(R.string.sessionsNotImported)); + + return medinet; + } + + for (SessionSQL uploadsessionsql : sessionssql) { + MeditationSession uploadsession = new MeditationSession(); + uploadsession.id = uploadsessionsql._id; + uploadsession.length = uploadsessionsql._length; + uploadsession.started = uploadsessionsql._started; + uploadsession.completed = uploadsessionsql._completed; + uploadsession.streakday = uploadsessionsql._streakday; + uploadsession.message = uploadsessionsql._message; + + jsonsessions.put(uploadsession.export()); + } + + Log.d("MeditationAssistant", jsonsessions.toString()); + + nameValuePairs.add(new BasicNameValuePair("uploadsessions", Crypt + .bytesToHex(crypt.encrypt(jsonsessions.toString())))); + } else if (action.equals("signout")) { + nameValuePairs + .add(new BasicNameValuePair("signout", "signout")); + } + + Log.d("MeditationAssistant", "Post to " + this.nextURL + ", " + + nameValuePairs.toString()); + httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); + webResponse = getMeditationAssistant().getHttpClient().execute( + httpPost, getMeditationAssistant().getHttpContext()); + } catch (ClientProtocolException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (Exception e) { + getMeditationAssistant().longToast(getMeditationAssistant().getString(R.string.sessionNotPosted)); + e.printStackTrace(); + } + + if (webResponse == null) { + Log.d("MeditationAssistant", "Unable to connect to MediNET"); + medinet.status = "disconnected"; + + if (!getMeditationAssistant().getMediNETKey().equals("") + && medinet.activity != null) { + getMeditationAssistant().longToast(medinet.activity, + getMeditationAssistant().getString(R.string.unableToConnect)); + medinet.activity.updateTextsAsync(); + } + + return medinet; + } + String result = ""; + + try { + this.webReader = new BufferedReader(new InputStreamReader( + webResponse.getEntity().getContent())); + } catch (IllegalStateException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + String line; + try { + while ((line = this.webReader.readLine()) != null) { + result += line + "\n"; + } + } catch (IOException e) { + e.printStackTrace(); + } + + Calendar date = new GregorianCalendar(); + date.setTimeZone(TimeZone.getDefault()); + date.set(Calendar.HOUR_OF_DAY, 0); + date.set(Calendar.MINUTE, 0); + date.set(Calendar.SECOND, 0); + date.set(Calendar.MILLISECOND, 0); + date.add(Calendar.DAY_OF_MONTH, 2); + Log.d("MeditationAssistant", + "two days: " + date.getTimeZone().getDisplayName() + + String.valueOf(date.getTimeInMillis() / 1000) + ); + + Log.d("MeditationAssistant", "Result: " + result); + if (webResponse.getFirstHeader("x-MediNET") != null) { + if (webResponse.getFirstHeader("x-MediNET").getValue() + .equals("signin")) { + this.medinet.askToSignIn(); + } else { + if (action.equals("signin") && webResponse.getFirstHeader("x-MediNET-Key") != null) { + /* Oauth2 sign in */ + Log.d("MeditationAssistant", "Header key: " + + webResponse.getFirstHeader("x-MediNET-Key") + .getValue()); + if (!webResponse.getFirstHeader("x-MediNET-Key") + .getValue().equals("")) { + getMeditationAssistant().setMediNETKey(webResponse.getFirstHeader("x-MediNET-Key") + .getValue(), "Google"); + //getMeditationAssistant().getMediNET().connect(); + + try { + getMeditationAssistant().shortToast( + medinet.activity, + getMeditationAssistant().getString(R.string.mediNETConnected)); + } catch (Exception e) { + e.printStackTrace(); + } + } + } else if (webResponse.getFirstHeader("x-MediNET-Streak") != null) { + Log.d("MeditationAssistant", "Header streak: " + + webResponse.getFirstHeader("x-MediNET-Streak") + .getValue()); + if (!webResponse.getFirstHeader("x-MediNET-Streak") + .getValue().equals("")) { + String streak_header = webResponse.getFirstHeader( + "x-MediNET-Streak").getValue(); + if (streak_header.contains(",")) { + getMeditationAssistant().setMeditationStreak(Integer.valueOf(streak_header.split(",")[0]), Integer.valueOf(streak_header.split(",")[1])); + getMeditationAssistant().recalculateMeditationStreak(); + } + } + } + if (webResponse.getFirstHeader("x-MediNET-Meditating") != null) { + if (!webResponse.getFirstHeader("x-MediNET-Meditating") + .getValue().equals("")) { + // TODO: Was this going to be a meditating-now feature? + } + } + if (webResponse.getFirstHeader("x-MediNET-MaxStreak") != null) { + if (!webResponse.getFirstHeader("x-MediNET-MaxStreak") + .getValue().equals("")) { + Integer maxstreak = Integer.valueOf(webResponse.getFirstHeader("x-MediNET-MaxStreak") + .getValue()); + if (maxstreak > getMeditationAssistant().getLongestMeditationStreak()) { + getMeditationAssistant().setLongestMeditationStreak(maxstreak); + } + } + } + } + Log.d("MeditationAssistant", "Header: " + + webResponse.getFirstHeader("x-MediNET").getValue()); + + if (!result.equals("") + && !result.trim().startsWith("<")) { + JSONObject jsonObj; + try { + jsonObj = new JSONObject(result); + Log.d("MeditationAssistant", + "jsonobj: " + jsonObj.toString()); + if (jsonObj.has("status")) { + medinet.status = jsonObj.getString("status"); + } + if (jsonObj.has("result")) { + medinet.result = jsonObj.getString("result"); + } + if (jsonObj.has("announce")) { + medinet.announcement = jsonObj.getString("announce"); + try { + medinet.activity.runOnUiThread(new Runnable() { + @Override + public void run() { + getMeditationAssistant() + .showAnnouncementDialog(null); + } + }); + } catch (Exception e) { + Log.d("MeditationAssistant", + "Caught error while parsing announcement..."); + e.printStackTrace(); + } + } + + if (action.equals("connect")) { + if (!getMeditationAssistant().getPrefs().getBoolean( + "asked_staledata", false)) { + try { + medinet.activity.runOnUiThread(new Runnable() { + @Override + public void run() { + getMeditationAssistant() + .showStaleDataDialog(); + } + }); + } catch (Exception e) { + Log.d("MeditationAssistant", + "Caught error while showing stale data dialog..."); + e.printStackTrace(); + } + + getMeditationAssistant().getPrefs().edit() + .putBoolean("asked_staledata", true) + .apply(); + } + } else if (action.equals("postsession")) { + if (medinet.result.equals("posted")) { + if (actionextra.equals("manualposting")) { + if (fragment_activity != null) { + fragment_activity + .runOnUiThread(new Runnable() { + @Override + public void run() { + getMeditationAssistant() + .shortToast( + getMeditationAssistant().getString(R.string.sessionPosted)); + } + }); + } + } else { + medinet.saveSession(false, true); + } + } else if (medinet.result.equals("alreadyposted") + && actionextra.equals("manualposting") + && fragment_activity != null) { + fragment_activity.runOnUiThread(new Runnable() { + @Override + public void run() { + getMeditationAssistant().shortToast( + getMeditationAssistant().getString(R.string.sessionAlreadyPosted)); + } + }); + } + } else if (action.equals("deletesession")) { + if (medinet.result.equals("deleted")) { + Log.d("MeditationAssistant", "Deleted session"); + + getMeditationAssistant().shortToast( + medinet.activity, + getMeditationAssistant().getString(R.string.sessionDeletedMediNET)); + + SessionSQL deletedsession = getMeditationAssistant().db.getSessionByStarted(Long.valueOf(actionextra)); + if (deletedsession != null) { + deletedsession._isposted = (long) 0; + try { + getMeditationAssistant().db.updateSession(deletedsession); + } catch (Exception e) { + // Do nothing, it was probably deleted locally as well + } + } + } else if (medinet.result.equals("notdeleted")) { + getMeditationAssistant().shortToast( + medinet.activity, + getMeditationAssistant().getString(R.string.sessionNotFoundMediNET)); + } else if (medinet.result.equals("accessdenied")) { + getMeditationAssistant() + .shortToast(medinet.activity, + getMeditationAssistant().getString(R.string.sessionNotProperAccount)); + } + } else if (action.equals("uploadsessions")) { + if (sessionssql != null && medinet.result.equals("uploaded")) { + for (SessionSQL sessionsql : sessionssql) { + sessionsql._isposted = (long) 1; + getMeditationAssistant().db.updateSession(sessionsql); + } + + Integer sessuploaded = sessionssql.size(); + getMeditationAssistant().longToast( + medinet.activity, + String.format(getMeditationAssistant().getResources().getQuantityString( + R.plurals.sessionsUploaded, sessuploaded, + sessuploaded), String.valueOf(sessuploaded)) + ); + } else { + getMeditationAssistant().longToast( + medinet.activity, + getMeditationAssistant().getString(R.string.sessionsNotImported)); + } + } else if (action.equals("syncsessions")) { + JSONArray jArray = jsonObj.getJSONArray("syncsessions"); + + Integer sessimported = 0; + + SessionSQL sess; + for (int i = 0; i < jArray.length(); i++) { + JSONObject session = jArray.getJSONObject(i); + + if (getMeditationAssistant().db + .getSessionByStarted(session + .getLong("started")) == null) { + sessimported += 1; + + sess = new SessionSQL(); + sess._length = session.getLong("length"); + sess._started = session.getLong("started"); + sess._completed = session.getLong("completed"); // Added in API 5 + sess._message = session.getString("message"); + sess._streakday = session.getLong("streakday"); + sess._isposted = (long) 1; + + Log.d("MeditationAssistant", + "Adding session started at " + + String.valueOf(sess._started) + ); + getMeditationAssistant().db.addSession(sess); + } else { + Log.d("MeditationAssistant", + "Skipping session " + String.valueOf(session)); + } + } + + if (sessimported > 0) { + getMeditationAssistant().longToast( + medinet.activity, + String.format(getMeditationAssistant().getResources().getQuantityString( + R.plurals.sessionsImported, sessimported, + sessimported), String.valueOf(sessimported)) + ); + } else { + getMeditationAssistant().longToast( + medinet.activity, + getMeditationAssistant().getString(R.string.sessionsNotImported)); + } + } + } catch (JSONException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + publishProgress(); + medinet.updateAfterDelay(); + + if (context == null) { + Throwable t = new Throwable(); + t.printStackTrace(); + } + + return medinet; + } + + public void doIt(MediNET m) { + try { + executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, m); + } catch (Exception e) { + execute(m); + e.printStackTrace(); + } + } + + public MeditationAssistant getMeditationAssistant() { + if (ma == null) { + ma = (MeditationAssistant) medinet.activity.getApplication(); + } + return ma; + } + + @Override + protected void onPostExecute(MediNET medinet) { + Log.d("MeditationAssistant", + "onPostExecute: " + String.valueOf(action)); + if (action != null) { + if (action.equals("connect")) { + try { + MainActivity mainActivity = medinet.activity; + mainActivity.updateTexts(); + Log.d("MeditationAssistant", + "Updated texts from finished 'connect'"); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + } + + @Override + protected void onProgressUpdate(Integer... progress) { + Log.d("MeditataionAssistant", "Progress update"); + medinet.updated(); + medinet.activity.updateTextsAsync(); + } +} diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MeditationAssistant.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MeditationAssistant.java new file mode 100644 index 0000000..0ff8cc6 --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MeditationAssistant.java @@ -0,0 +1,1497 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +import android.accounts.Account; +import android.accounts.AccountManager; +import android.accounts.AccountManagerCallback; +import android.accounts.AccountManagerFuture; +import android.accounts.AuthenticatorException; +import android.accounts.OperationCanceledException; +import android.app.Activity; +import android.app.AlarmManager; +import android.app.AlertDialog; +import android.app.Application; +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.appwidget.AppWidgetManager; +import android.content.ActivityNotFoundException; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.IntentSender; +import android.content.SharedPreferences; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.res.Resources; +import android.media.AudioManager; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.Vibrator; +import android.preference.PreferenceManager; +import android.support.v4.app.NotificationCompat; +import android.util.Log; +import android.util.TypedValue; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.webkit.CookieSyncManager; +import android.widget.ImageButton; +import android.widget.Toast; + +import com.google.android.gms.analytics.GoogleAnalytics; +import com.google.android.gms.analytics.Tracker; +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.GooglePlayServicesUtil; +import com.google.android.gms.common.Scopes; +import com.google.android.gms.common.api.GoogleApiClient; +import com.google.android.gms.common.api.Scope; +import com.google.android.gms.fitness.Fitness; +import com.google.android.gms.fitness.FitnessActivities; +import com.google.android.gms.fitness.data.Field; +import com.google.android.gms.fitness.data.Session; +import com.google.android.gms.fitness.request.DataTypeCreateRequest; +import com.google.android.gms.fitness.request.SessionInsertRequest; + +import org.apache.http.client.protocol.ClientContext; +import org.apache.http.conn.ClientConnectionManager; +import org.apache.http.impl.client.BasicCookieStore; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; +import org.apache.http.params.HttpParams; +import org.apache.http.protocol.BasicHttpContext; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.TimeZone; +import java.util.concurrent.TimeUnit; + +public class MeditationAssistant extends Application { + + public static String ACTION_PRESET = "sh.ftp.rocketninelabs.meditationassistant.PRESET"; + public static String ACTION_REMINDER = "sh.ftp.rocketninelabs.meditationassistant.DAILY_NOTIFICATION"; + public static String ACTION_UPDATED = "sh.ftp.rocketninelabs.meditationassistant.DAILY_NOTIFICATION_UPDATED"; + + public static int REQUEST_FIT = 22; + + public String package_name; + public Boolean debug_widgets = false; // Debug + public long lastpostedsessionstart = 0; + public boolean ispaused = false; + public long pausestart = 0; + public long pausetime = 0; + public int previousRingerMode = -1; + public String toastText = ""; + public DefaultHttpClient httpClient = null; + public BasicCookieStore cookieStore = null; + public BasicHttpContext httpContext = null; + public String pendingNotificationAction = ""; + public Boolean asktorate = false; + public DatabaseHandler db = null; + public AlarmManager reminderAlarmManager = null; + public PendingIntent reminderPendingIntent = null; + public String theme = null; + AlertDialog alertDialog = null; + String AUTH_TOKEN_TYPE = "oauth2:https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email"; + HashMap mTrackers = new HashMap(); + private String appVersion = null; + private Boolean appFull = null; + private long timeToStopMeditate = 0; + private long timeStartMeditate = 0; + private MediNET medinet = null; + private boolean screenoff = false; + private boolean runnablestopped = true; + private boolean sessrunnablestopped = true; + private String medinetkey = null; + private String medinetprovider = null; + private boolean connectedonce = false; + private boolean editingduration = false; + private Boolean rememberduration = null; + private Integer meditationstreak = null; + private long meditationstreakexpires = 0; + private long sessrunnablestarttime = 0; + private boolean sesswassignedout = false; + private Boolean sendusage = null; + private Activity toastActivity; + private long sessionduration = 0; + private Integer webview_scale = null; + private String timerMode = null; + private String durationFormatted = ""; + private Activity signin_activity = null; + private Bundle signin_options = new Bundle(); + private SharedPreferences prefs = null; + + private static final String AUTH_PENDING = "auth_state_pending"; + public boolean googleAPIAuthInProgress = false; + public GoogleApiClient googleClient = null; + + public static String getMarketName() { + return "google"; + //return "amazon"; + //return "getjar"; + // return "slideme"; + } + + public static int dpToPixels(float dp, Context context) { + Resources resources = context.getResources(); + return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, + resources.getDisplayMetrics()); + } + + public static DefaultHttpClient getThreadSafeHttpClient() { + + DefaultHttpClient client = new DefaultHttpClient(); + ClientConnectionManager mgr = client.getConnectionManager(); + HttpParams params = client.getParams(); + client = new DefaultHttpClient(new ThreadSafeClientConnManager(params, + mgr.getSchemeRegistry()), params); + return client; + } + + public static void setAlphaCompat(View view, float alpha) { + view.setAlpha(alpha); + } + + public Boolean getIsBB() { + String osname = System.getProperty("os.name"); + return osname != null && osname.equals("qnx"); + } + + synchronized Tracker getTracker(TrackerName trackerId) { + if (!mTrackers.containsKey(trackerId)) { + GoogleAnalytics analytics = GoogleAnalytics.getInstance(this); + Tracker t = analytics.newTracker(R.xml.analytics_tracker); + mTrackers.put(trackerId, t); + } + return mTrackers.get(trackerId); + } + + public boolean canVibrate() { + try { + Vibrator vi = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); + return vi.hasVibrator(); + } catch (NoSuchMethodError e) { + } catch (Exception e) { + } + return true; + } + + public void connectOnce() { + if (!connectedonce) { + getMediNET().connect(); + connectedonce = true; + } + } + + public String[] getStartPhrases() { + String[] start_phrases = {"om tat sat", "om mani padme hum"}; + // start_phrases.add("namo akasagarbhaya om arya kamari mauli svaha"); + + return start_phrases; + } + + public void askToRateApp() { + if (getIsBB()) { + try { + startActivity(new Intent(Intent.ACTION_VIEW, + Uri.parse("appworld://content/" + (getApplicationContext().getPackageName().equals("sh.ftp.rocketninelabs.meditationassistant") ? "59939924" : "59939922")) + ).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); + } catch (ActivityNotFoundException e) { + Log.d("MeditationAssistant", "Couldn't open play store"); + startActivity(new Intent( + Intent.ACTION_VIEW, + Uri.parse("appworld://content/" + (getApplicationContext().getPackageName().equals("sh.ftp.rocketninelabs.meditationassistant") ? "59939924" : "59939922")) + ).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); + } + } else if (MeditationAssistant.getMarketName().equals("google")) { + try { + startActivity(new Intent(Intent.ACTION_VIEW, + Uri.parse("market://details?id=" + + getApplicationContext().getPackageName()) + ).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); + } catch (ActivityNotFoundException e) { + Log.d("MeditationAssistant", "Couldn't open play store"); + startActivity(new Intent( + Intent.ACTION_VIEW, + Uri.parse("http://play.google.com/store/apps/details?id=" + + getApplicationContext().getPackageName()) + ).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); + } + } else if (MeditationAssistant.getMarketName().equals("amazon")) { + try { + startActivity(new Intent(Intent.ACTION_VIEW, + Uri.parse("amzn://apps/android?p=" + + getApplicationContext().getPackageName()) + ).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); + } catch (ActivityNotFoundException e) { + Log.d("MeditationAssistant", "Couldn't open amazon store"); + startActivity(new Intent( + Intent.ACTION_VIEW, + Uri.parse("http://www.amazon.com/gp/mas/dl/android?p=" + + getApplicationContext().getPackageName()) + ).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); + } + } + } + + public void setNotificationControl() { + AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); + previousRingerMode = audioManager.getRingerMode(); + + if (getPrefs().getString("pref_notificationcontrol", "").equals("vibrate")) { + audioManager.setRingerMode(AudioManager.RINGER_MODE_VIBRATE); + } else if (getPrefs().getString("pref_notificationcontrol", "").equals("silent")) { + audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT); + } + } + + public void unsetNotificationControl() { + AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); + + if (previousRingerMode >= 0 && getPrefs().getString("pref_notificationcontrol", "").equals("vibrate") || getPrefs().getString("pref_notificationcontrol", "").equals("silent")) { + audioManager.setRingerMode(previousRingerMode); + } + + previousRingerMode = -1; + } + + public String getDurationFormatted() { + return durationFormatted; + } + + public void setDurationFormatted(String d) { + if (!d.equals(durationFormatted)) { + durationFormatted = d; + // showNotification(); + } + } + + public boolean getEditingDuration() { + return editingduration; + } + + public void setEditingDuration(boolean bool) { + editingduration = bool; + } + + public DefaultHttpClient getHttpClient() { + if (httpClient == null) { + httpClient = getThreadSafeHttpClient(); + httpClient.setCookieStore(cookieStore); + } + + return httpClient; + } + + public BasicHttpContext getHttpContext() { + if (cookieStore == null) { + cookieStore = new BasicCookieStore(); + + httpContext = new BasicHttpContext(); + // Bind custom cookie store to the local context + httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore); + } + return httpContext; + } + + public int getMATextColor(Boolean enabled) { + if (enabled) { + if (!getMAThemeString().equals("dark") && !getMAThemeString().equals("buddhism")) { + return android.R.color.primary_text_light; + } else { + return android.R.color.primary_text_dark; + } + } else { + if (!getMAThemeString().equals("dark") && !getMAThemeString().equals("buddhism")) { + return android.R.color.secondary_text_light; + } else { + return android.R.color.secondary_text_dark; + } + } + } + + public int getMATheme() { + return getMATheme(false); + } + + public int getMATheme(Boolean dialogue) { + if (theme == null) { + theme = getPrefs().getString("pref_theme", "dark"); + } + + if (theme.equals("buddhism")) { + return dialogue ? R.style.BuddhismDialogue : R.style.Buddhism; + } + + if (dialogue) { + if (!theme.equals("dark")) { + return R.style.MeditationLightDialogTheme; + } else { + return R.style.MeditationDarkDialogTheme; + } + } else { + if (theme.equals("light")) { + return R.style.MeditationLightTheme; + } else if (theme.equals("lightdark")) { + return R.style.MeditationLightDarkTheme; + } else { + return R.style.MeditationDarkTheme; + } + } + } + + public String getMAThemeString() { + if (theme == null) { + theme = getPrefs().getString("pref_theme", "dark"); + } + + return theme; + } + + public MediNET getMediNET() { + if (medinet == null) { + // + } + return medinet; + } + + public void setMediNET(MediNET medi) { + medinet = medi; + Log.d("MeditationAssistant", "Session: " + String.valueOf(medinet)); + } + + public String getMediNETKey() { + Log.d("MeditationAssistant", "getMediNETKey() - medinetkey: " + String.valueOf(medinetkey) + " prefs: " + getPrefs().getString("key", "")); + if (medinetkey == null) { + medinetkey = getPrefs().getString("key", ""); + } + return medinetkey; + } + + public String getMediNETProvider() { + if (medinetprovider == null) { + medinetprovider = getPrefs().getString("provider", ""); + } + if (medinetprovider.trim().equals("")) { + return "Unknown"; + } + return medinetprovider; + } + + public void recalculateMeditationStreak() { + Calendar dayCalendar = Calendar.getInstance(); + Integer daysback = 0; + Integer recalculatedstreak = 0; + Boolean sessionexiststoday = false; + + while (true) { + if (db.numSessionsByDate(String.valueOf(dayCalendar.get(Calendar.DAY_OF_MONTH)) + "-" + + String.valueOf(dayCalendar.get(Calendar.MONTH) + 1) + "-" + + String.valueOf(dayCalendar.get(Calendar.YEAR))) > 0) { + recalculatedstreak++; + + if (daysback == 0) { + sessionexiststoday = true; + } + } else if (daysback > 0) { + break; + } + + daysback++; + dayCalendar.add(Calendar.DAY_OF_YEAR, -1); + } + + if (getMeditationStreak() < recalculatedstreak) { + setMeditationStreak(recalculatedstreak, sessionexiststoday ? getMidnightTwoDaysTimestamp() : getMidnightOneDayTimestamp()); + } + } + + public Integer getMeditationStreak() { + long timestamp = System.currentTimeMillis() / 1000; + + if (meditationstreak == null || meditationstreakexpires < 1) { // streak + // or + // expires + // timestamp + // not + // set + meditationstreak = getPrefs().getInt("meditationstreak", 0); + meditationstreakexpires = getPrefs().getLong("meditationstreakexpires", + 0); + } + + if (meditationstreakexpires > 0 && meditationstreakexpires < timestamp) { // expires + // timestamp + // has passed + meditationstreak = 0; + meditationstreakexpires = 0; + + getPrefs().edit().putInt("meditationstreak", meditationstreak).putLong("meditationstreakexpires", meditationstreakexpires).apply(); + } + + return meditationstreak; + } + + public void addMeditationStreak() { + addMeditationStreak(true); + } + + public void addMeditationStreak(Boolean twodays) { + Integer streak = getMeditationStreak(); + Log.d("MeditationAssistant", "addMeditationStreak() - Streak: " + String.valueOf(streak) + " Expires: in " + String.valueOf(meditationstreakexpires - getTimestamp()) + " seconds"); + if (meditationstreak == null || meditationstreak == 0 || meditationstreakexpires - getTimestamp() < 86400) { + streak++; + + if (twodays) { + setMeditationStreak(streak, + getMidnightTwoDaysTimestamp()); + } else { + setMeditationStreak(streak, + getMidnightOneDayTimestamp()); + } + } + } + + public int getLongestMeditationStreak() { + return getPrefs().getInt("longeststreak", 0); + } + + public void setLongestMeditationStreak(int ms) { + getPrefs().edit().putInt("longeststreak", ms).apply(); + } + + public long getMidnightOneDayTimestamp() { + Calendar c_midnight_oneday = new GregorianCalendar(); + c_midnight_oneday.setTime(new Date()); + c_midnight_oneday.set(Calendar.HOUR_OF_DAY, 0); + c_midnight_oneday.set(Calendar.MINUTE, 0); + c_midnight_oneday.set(Calendar.SECOND, 0); + c_midnight_oneday.set(Calendar.MILLISECOND, 0); + c_midnight_oneday.add(Calendar.DATE, 1); // One day + + return c_midnight_oneday.getTimeInMillis() / 1000; + } + + public long getMidnightTwoDaysTimestamp() { + Calendar c_midnight_twodays = new GregorianCalendar(); + c_midnight_twodays.setTime(new Date()); + c_midnight_twodays.set(Calendar.HOUR_OF_DAY, 0); + c_midnight_twodays.set(Calendar.MINUTE, 0); + c_midnight_twodays.set(Calendar.SECOND, 0); + c_midnight_twodays.set(Calendar.MILLISECOND, 0); + c_midnight_twodays.add(Calendar.DATE, 2); // Two days + + return c_midnight_twodays.getTimeInMillis() / 1000; + } + + public void notifySessionsUpdated() { + Log.d("MeditationAssistant", "Sending session update notification"); + getPrefs().edit().putLong("sessionsupdate", getTimestamp()).apply(); + } + + public Integer timePreferenceValueToSeconds(String timePreferenceValue, String defaultValue) { + try { + String[] timeValueSplit = ((timePreferenceValue != null && timePreferenceValue != "") ? timePreferenceValue : defaultValue).split(":"); + return (Integer.valueOf(timeValueSplit[0]) * 60) + Integer.valueOf(timeValueSplit[1]); + } catch (Exception e) { + e.printStackTrace(); + } + + return 0; + } + + public ArrayList formatDuration(String duration) { + if (!duration.equals("")) { + String[] duration_separated = duration.split(":"); + String newHours = "-1"; + String newMinutes = "-1"; + + if (duration_separated.length > 1) { + if (!duration_separated[0].trim().equals("")) { + try { + newHours = String.valueOf(Integer + .valueOf(duration_separated[0])); + } catch (Exception e) { + e.printStackTrace(); + } + } else { + newHours = "0"; + } + if (!duration_separated[1].trim().equals("")) { + try { + newMinutes = String.valueOf(Integer + .valueOf(duration_separated[1])); + } catch (Exception e) { + e.printStackTrace(); + } + } else { + newMinutes = "0"; + } + } else { + try { + newMinutes = String.valueOf(Integer.valueOf(duration)); + newHours = "0"; + } catch (Exception e) { + e.printStackTrace(); + } + } + + if (Integer.valueOf(newMinutes) >= 60) { + newHours = String.format("%d", + (int) (Integer.valueOf(newHours) + Math.floor(Integer + .valueOf(newMinutes) / 60)) + ); + newMinutes = String.format("%02d", + Integer.valueOf(newMinutes) % 60); + } + + if (!newHours.equals("-1") && !newMinutes.equals("-1") + && !(newHours.equals("0") && newMinutes.equals("0"))) { + ArrayList formatted_duration = new ArrayList(); + formatted_duration.add(newHours); + formatted_duration.add(String.format("%02d", + Integer.valueOf(newMinutes))); + + return formatted_duration; + } + } + + return null; + } + + public ArrayList formatDurationEndAt(String duration) { + if (!duration.equals("")) { + String[] duration_separated = duration.split(":"); + String newHours = "-1"; + String newMinutes = "-1"; + Boolean shorthand = false; + + if (duration_separated.length > 1) { + if (!duration_separated[0].trim().equals("")) { + try { + newHours = String.valueOf(Integer + .valueOf(duration_separated[0])); + } catch (Exception e) { + e.printStackTrace(); + } + } else { + newHours = "0"; + } + if (!duration_separated[1].trim().equals("")) { + try { + newMinutes = String.valueOf(Integer + .valueOf(duration_separated[1])); + if (duration_separated[1].trim().length() < 2) { + shorthand = true; + } + } catch (Exception e) { + e.printStackTrace(); + } + } else { + newMinutes = "0"; + } + } else { + try { + newHours = String.valueOf(Integer.valueOf(duration)); + newMinutes = "0"; + } catch (Exception e) { + e.printStackTrace(); + } + } + + Log.d("MeditationAssistant", "Formatted end at duration newMinutes: " + newMinutes); + if (shorthand && Integer.valueOf(newMinutes) > 0 && Integer.valueOf(newMinutes) <= 5) { // shorthand 3 -> 30, 4 -> 40... + newMinutes = String.format("%02d", + Integer.valueOf(newMinutes) * 10); + } else if (Integer.valueOf(newMinutes) >= 60) { + newHours = String.format("%d", + (int) (Integer.valueOf(newHours) + Math.floor(Integer + .valueOf(newMinutes) / 60)) + ); + newMinutes = String.format("%02d", + Integer.valueOf(newMinutes) % 60); + } + + if (Integer.valueOf(newHours) == 0 || Integer.valueOf(newHours) > 24) { + return null; // Invalid hour for time + } else if (Integer.valueOf(newHours) > 12) { + newHours = String.valueOf(Integer.valueOf(newHours) - 12); // Subtract 12 hours if 24 hour time was provided + } + + if (!newHours.equals("-1") && !newMinutes.equals("-1") + && !(newHours.equals("0") && newMinutes.equals("0"))) { + ArrayList formatted_duration = new ArrayList(); + formatted_duration.add(newHours); + formatted_duration.add(String.format("%02d", + Integer.valueOf(newMinutes))); + + return formatted_duration; + } + } + + return null; + } + + public SharedPreferences getPrefs() { + if (prefs == null) { + prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); + } + return prefs; + } + + public boolean getRememberDuration() { + if (rememberduration == null) { + rememberduration = getPrefs().getBoolean("pref_rememberlasttimer", true); + } + return rememberduration; + } + + public boolean getRunnableStopped() { + return runnablestopped; + } + + public void setRunnableStopped(boolean bool) { + runnablestopped = bool; + } + + public boolean getScreenOff() { + return screenoff; + } + + public void setScreenOff(boolean bool) { + screenoff = bool; + } + + public long getSessionDuration() { + return sessionduration; + } + + public void setSessionDuration(long duration) { + sessionduration = duration; + } + + public long getSessionsRunnableStartTime() { + return sessrunnablestarttime; + } + + public void setSessionsRunnableStartTime(long l) { + sessrunnablestarttime = l; + } + + public boolean getSessionsRunnableStopped() { + return sessrunnablestopped; + } + + public void setSessionsRunnableStopped(boolean bool) { + sessrunnablestopped = bool; + } + + public boolean getSessionsRunnableWasSignedOut() { + return sesswassignedout; + } + + public void setSessionsRunnableWasSignedOut(boolean bool) { + sesswassignedout = bool; + } + + public Long getTimestamp() { + return System.currentTimeMillis() / 1000; + } + + public long getTimeStartMeditate() { + return timeStartMeditate; + } + + public void setTimeStartMeditate(long l) { + timeStartMeditate = l; + pendingNotificationAction = ""; + // Log.d("MeditationAssistant", String.valueOf(timeToStopMeditate)); + } + + public long getTimeToStopMeditate() { + return timeToStopMeditate; + } + + public void setTimeToStopMeditate(long l) { + timeToStopMeditate = l; + getPrefs().edit().putLong("last_reminder", getTimestamp()).apply(); + //(new Exception()).printStackTrace(); + Log.d("MeditationAssistant", "Setting time to stop meditating: " + + String.valueOf(timeToStopMeditate)); + } + + public String getTimerMode() { + if (timerMode == null) { + timerMode = getPrefs().getString("pref_timer_mode", "timed"); + } + return timerMode; + } + + public void setTimerMode(String tm) { + timerMode = tm; + + getPrefs().edit().putString("pref_timer_mode", timerMode).apply(); + } + + public Integer getWebViewScale() { + if (webview_scale == null) { + webview_scale = getPrefs().getInt("webviewscale", 100); + } + return webview_scale; + } + + public void setWebViewScale(int scale) { + webview_scale = scale; + + getPrefs().edit().putInt("webviewscale", webview_scale).apply(); + } + + public void hideNotification() { + NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); + notificationManager.cancelAll(); + } + + public void longToast(Activity activity, String text) { + try { + Looper.prepare(); + } catch (Exception e) { + //e.printStackTrace(); + } + + if (activity == null) { + Toast.makeText(getApplicationContext(), text, Toast.LENGTH_LONG) + .show(); + } else { + toastActivity = activity; + toastText = text; + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + Toast.makeText(toastActivity, toastText, Toast.LENGTH_LONG) + .show(); + } + }); + } + } + + public void longToast(String text) { + longToast(null, text); + } + + @Override + public void onCreate() { + super.onCreate(); + + package_name = getApplicationContext().getPackageName(); + + Integer applaunches = getPrefs().getInt("applaunches", 0) + 1; + getPrefs().edit().putInt("applaunches", applaunches).apply(); + + Log.d("MeditationAssistant", + "Meditation Assistant running (" + applaunches + " launches) on API level " + + String.valueOf(Build.VERSION.SDK_INT) + ); + + // Reset timer to default values + if (!getPrefs().getBoolean("pref_rememberlasttimer", true)) { + SharedPreferences.Editor editor = getPrefs().edit(); + editor.putString("timerHours", + getPrefs().getString("timerDefaultHours", "15")); + editor.putString("timerMinutes", + getPrefs().getString("timerDefaultMinutes", "15")); + editor.apply(); + } + + // Upgrade to the new delay and interval preferences + /*long pref_delay = Integer.valueOf(getPrefs().getString("pref_delay", "-1")); + if (pref_delay >= 0) { + Log.d("MeditationAssistant", "Upgrading pref_delay to TimePreference: from " + String.valueOf(pref_delay) + " to " + String.format("%02d", pref_delay / 60) + ":" + String.format("%02d", pref_delay % 60)); + getPrefs().edit().putString("pref_session_delay", String.format("%02d", pref_delay / 60) + ":" + String.format("%02d", pref_delay % 60)).apply(); + getPrefs().edit().putString("pref_delay", "-1").apply(); + Log.d("MeditationAssistant", "New pref_session_delay value: " + getPrefs().getString("pref_session_delay", "00:15")); + + } + long pref_interval = Integer.valueOf(getPrefs().getString("pref_interval", "-1")); + if (pref_interval >= 0) { + Log.d("MeditationAssistant", "Upgrading pref_interval to TimePreference: from " + String.valueOf(pref_interval) + " to " + String.format("%02d", pref_interval / 60) + ":" + String.format("%02d", pref_interval % 60)); + getPrefs().edit().putString("pref_session_delay", String.format("%02d", pref_interval / 60) + ":" + String.format("%02d", pref_interval % 60)).apply(); + getPrefs().edit().putString("pref_interval", "-1").apply(); + }*/ + + db = DatabaseHandler.getInstance(getApplicationContext()); + CookieSyncManager.createInstance(getApplicationContext()); + + reminderAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); + + /* Send the daily notification updated intent just in case the receiver hasn't been called yet */ + Log.d("MeditationAssistant", "Sending initial daily notification updated intent"); + Intent intent = new Intent(); + intent.setAction(MeditationAssistant.ACTION_UPDATED); + sendBroadcast(intent); + } + + public void setupGoogleClient(final Activity activity) { + //if (googleClient != null) { + /// return; + //} + Log.d("MeditationAssistant", "Setting up Google Fit"); + + googleClient = new GoogleApiClient.Builder(activity) + .addApi(Fitness.HISTORY_API) + .addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE)) + .addConnectionCallbacks( + new GoogleApiClient.ConnectionCallbacks() { + + @Override + public void onConnected(Bundle bundle) { + Log.d("MeditationAssistant", "!!! Connected to Google Fit"); + // Now you can make calls to the Fitness APIs. + // Put application specific code here. + } + + @Override + public void onConnectionSuspended(int i) { + // If your connection to the sensor gets lost at some point, + // you'll be able to determine the reason and react to it here. + if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_NETWORK_LOST) { + Log.d("MeditationAssistant", "Connection lost. Cause: Network Lost."); + } else if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED) { + Log.d("MeditationAssistant", "Connection lost. Reason: Service Disconnected"); + } + } + } + ) + .addOnConnectionFailedListener( + new GoogleApiClient.OnConnectionFailedListener() { + // Called whenever the API client fails to connect. + @Override + public void onConnectionFailed(ConnectionResult result) { + Log.d("MeditationAssistant", "Connection failed. Cause: " + result.toString()); + if (!result.hasResolution()) { + // Show the localized error dialog + GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(), + activity, 0).show(); + return; + } + // The failure has a resolution. Resolve it. + // Called typically when the app is not yet authorized, and an + // authorization dialog is displayed to the user. + if (!googleAPIAuthInProgress) { + try { + Log.d("MeditationAssistant", "Attempting to resolve failed connection"); + googleAPIAuthInProgress = true; + result.startResolutionForResult(activity, + REQUEST_FIT); + } catch (IntentSender.SendIntentException e) { + Log.d("MeditationAssistant", + "Exception while starting resolution activity", e); + } + } + } + } + ) + .build(); + } + + public void sendFitData() { + Calendar cal = Calendar.getInstance(); + Date now = new Date(); + cal.setTime(now); + long endTime = cal.getTimeInMillis(); + cal.add(Calendar.HOUR, -1); + long startTime = cal.getTimeInMillis(); + + Session session = new Session.Builder() + .setName("No name") + .setDescription("Duration: blah blah") + .setIdentifier("meditation" + "11231241") + .setActivity(FitnessActivities.MEDITATION) + .setStartTime(startTime, TimeUnit.MILLISECONDS) + .setEndTime(endTime, TimeUnit.MILLISECONDS) + .build(); + + SessionInsertRequest insertRequest = new SessionInsertRequest.Builder() + .setSession(session) + .build(); + + // Then, invoke the Sessions API to insert the session and await the result, +// which is possible here because of the AsyncTask. Always include a timeout when +// calling await() to avoid hanging that can occur from the service being shutdown +// because of low memory or other conditions. + Log.d("MeditationAssistant", "Inserting the session in the History API"); + com.google.android.gms.common.api.Status insertStatus = + Fitness.SessionsApi.insertSession(googleClient, insertRequest) + .await(1, TimeUnit.MINUTES); + +// Before querying the session, check to see if the insertion succeeded. + if (!insertStatus.isSuccess()) { + Log.d("MeditationAssistant", "There was a problem inserting the session: " + + insertStatus.getStatusMessage()); + return; + } + +// At this point, the session has been inserted and can be read. + Log.i("MeditationAssistant", "Session insert was successful!"); + } + + public boolean sendUsageReports() { + if (sendusage == null) { + sendusage = getPrefs().getBoolean("pref_sendusage", true); + } + return sendusage; + } + + public void setMediNETKey(String key, String provider) { + Log.d("MeditationAssistant", "Setting medinet key: " + key + " - " + provider); + medinetkey = key; + medinetprovider = provider; + long timestamp = System.currentTimeMillis() / 1000; + + SharedPreferences.Editor editor = getPrefs().edit(); + if (getPrefs().getBoolean("pref_rememberme", true)) { + Log.d("MeditationAssistant", "Storing medinet key: " + key + " - " + provider); + editor.putString("key", key); + editor.putString("provider", provider); + } + editor.putString("keyupdate", String.valueOf(timestamp)); + editor.apply(); + } + + public void setMeditationStreak(Integer ms, long expires) { + if (meditationstreak == null) { + meditationstreak = getMeditationStreak(); + } + if (ms >= meditationstreak) { + meditationstreak = ms; + meditationstreakexpires = expires; + + Calendar date = new GregorianCalendar(); + date.setTimeZone(TimeZone.getDefault()); + long timestamp = date.getTimeInMillis() / 1000; + Log.d("MeditationAssistant", + "Streak: " + String.valueOf(meditationstreak) + ", expires: " + + String.valueOf(expires) + " (in " + + String.valueOf(expires - timestamp) + " seconds)" + ); + + getPrefs().edit().putInt("meditationstreak", meditationstreak).putLong("meditationstreakexpires", meditationstreakexpires).apply(); + + if (meditationstreak > getLongestMeditationStreak()) { + setLongestMeditationStreak(meditationstreak); + } + + updateWidgets(); + } else { + Log.d("MeditationAssistant", + "Not setting new meditation streak, current streak is higher"); + } + + /* Update all widgets */ + Intent update_widgets = new Intent(getApplicationContext(), MeditationProvider.class); + update_widgets.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE); + sendBroadcast(update_widgets); + } + + public void pauseSession() { + pausestart = getTimestamp(); + ispaused = true; + } + + public long unPauseSession() { + if (!ispaused) { + return 0; + } + + long thispausetime; + if (getTimerMode().equals("endat")) { + thispausetime = Math.min(getTimeToStopMeditate(), getTimestamp()) - pausestart; + } else { + thispausetime = Math.max(0, getTimestamp() - pausestart); + } + pausetime += thispausetime; + + Log.d("MeditationAssistant", "PAUSE: Un-paused. Paused for " + String.valueOf(thispausetime) + " seconds (" + String.valueOf(pausetime) + " total)"); + + ispaused = false; + return thispausetime; + } + + public void shortToast(Activity activity, String text) { + try { + Looper.prepare(); + } catch (Exception e) { + //e.printStackTrace(); + } + + if (activity == null) { + Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT) + .show(); + } else { + toastActivity = activity; + toastText = text; + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + Toast.makeText(toastActivity, toastText, Toast.LENGTH_SHORT) + .show(); + } + }); + } + } + + public void shortToast(String text) { + shortToast(null, text); + } + + public AlertDialog showAnnouncementDialog(String title) { + try { + Looper.prepare(); + } catch (Exception e) { + //e.printStackTrace(); + } + + if (getMediNET().activity != null + && !getMediNET().announcement.equals("")) { + AlertDialog announceDialog = new AlertDialog.Builder( + getMediNET().activity) + .setPositiveButton(R.string.dismiss, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, + int id) { + + } + } + ) + .setTitle(title == null ? getString(R.string.announcement) : title) + .setMessage(medinet.announcement) + .setIcon( + getMediNET().activity + .getResources() + .getDrawable( + getTheme() + .obtainStyledAttributes( + getMATheme(true), + new int[]{R.attr.actionIconGoToToday}) + .getResourceId(0, 0) + ) + ) + .setCancelable(false).create(); + + announceDialog.show(); + + return announceDialog; + } + + return null; + } + + public void showNotification() { + if (!getPrefs().getBoolean("pref_notification", true) + || getTimeStartMeditate() < 1) { + hideNotification(); + return; + } + + Intent intent = new Intent(this, MainActivity.class); + intent.setAction("notification"); + // intent.putExtra("notificationButton", "notification"); + // intent.putExtra("notificationButton", ""); + PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent, + PendingIntent.FLAG_UPDATE_CURRENT); + + Intent intent2 = new Intent(this, MainActivity.class); + // intent2.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); + intent2.setAction("notificationPause"); + PendingIntent pIntentPause = PendingIntent.getActivity(this, 0, intent2, + PendingIntent.FLAG_UPDATE_CURRENT); + + Intent intent3 = new Intent(this, MainActivity.class); + // intent3.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); + // intent3.putExtra("notificationButton", "end"); + intent3.setAction("notificationEnd"); + PendingIntent pIntentEnd = PendingIntent.getActivity(this, 0, intent3, + PendingIntent.FLAG_UPDATE_CURRENT); + + String streaktext = ""; + if (getMeditationStreak() > 1) { + streaktext = String.valueOf(getMeditationStreak()); + } + + String titleText = getString(R.string.sessionInProgress); + String contentText = getString(R.string.appName); + + /* + * if (!getDurationFormatted().equals("") && getTimeToStopMeditate() > + * (System .currentTimeMillis() / 1000)) { titleText = + * getDurationFormatted(); contentText = + * getString(R.string.sessionInProgress); } + */ + + Notification notification = new NotificationCompat.Builder(this) + .setOngoing(true) + .setSmallIcon(R.drawable.ic_notification) + .setContentTitle(titleText) + .setContentText(contentText) + .setPriority(NotificationCompat.PRIORITY_HIGH) + .setContentInfo(streaktext) + .setContentIntent(pIntent) + .addAction(R.drawable.ic_action_pause, + getString(R.string.pause), pIntentPause) + .addAction(R.drawable.ic_action_stop, + getString(R.string.end), pIntentEnd).build(); + + // .setContentText(contentText).setOngoing(true) + // .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), + // notification_icon)) + NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); + notificationManager.notify(0, notification); + } + + public AlertDialog showSignInDialog(final Activity activity) { + signin_activity = activity; + + AccountManager accountManager = AccountManager + .get(getApplicationContext()); + final Account[] accounts = accountManager + .getAccountsByType("com.google"); + + final int size = accounts.length; + + if (size > 0) { + String[] names = new String[size + 1]; + int i = 0; + for (i = 0; i < size; i++) { + names[i] = accounts[i].name; + } + names[i] = getString(R.string.signInWithOpenID); + + AlertDialog accountsAlertDialog = new AlertDialog.Builder(activity) + .setTitle(getString(R.string.signInWith)) + .setItems(names, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + if (which != size) { + AccountManager am = AccountManager.get(getApplicationContext()); + + if (am != null) { + am.getAuthToken(accounts[which], AUTH_TOKEN_TYPE, null, signin_activity, new OnTokenAcquired(), new Handler(new Handler.Callback() { + + public boolean handleMessage(Message msg) { + Log.d("MeditationAssistant", "on error: " + msg.what); + shortToast(getString(R.string.signInGoogleError)); + return false; + } + })); + } + } else { + showOpenIDSignInDialog(activity); + } + } + }) + .create(); + accountsAlertDialog.show(); + + return accountsAlertDialog; + } else { + return showOpenIDSignInDialog(activity); + } + } + + public AlertDialog showOpenIDSignInDialog(Activity activity) { + if (alertDialog != null && alertDialog.getOwnerActivity() != null + && alertDialog.getOwnerActivity() == activity) { + Log.d("MeditationAssistant", + "Attempting to reuse MediNET sign in dialog"); + + try { + if (!alertDialog.isShowing()) { + alertDialog.show(); + } + + Log.d("MeditationAssistant", "Reusing MediNET sign in dialog"); + return alertDialog; + } catch (WindowManager.BadTokenException e) { + // Activity is not in the foreground + } + } + + int[] buttons = {R.id.btnGoogle, R.id.btnFacebook, R.id.btnAOL, + R.id.btnTwitter, R.id.btnLive, R.id.btnOpenID}; + + View view = LayoutInflater.from(activity).inflate( + R.layout.medinet_signin, + (ViewGroup) activity.findViewById(R.id.medinetsignin_root)); + + for (int buttonid : buttons) { + ImageButton btn = (ImageButton) view.findViewById(buttonid); + + if (btn.getId() == R.id.btnGoogle) { + if (!getMAThemeString().equals("dark")) { + btn.setImageDrawable(getResources().getDrawable( + R.drawable.logo_google_light)); + } else { + btn.setImageDrawable(getResources().getDrawable( + R.drawable.logo_google)); + } + } else if (btn.getId() == R.id.btnFacebook) { + if (!getMAThemeString().equals("dark")) { + btn.setImageDrawable(getResources().getDrawable( + R.drawable.logo_facebook_light)); + } else { + btn.setImageDrawable(getResources().getDrawable( + R.drawable.logo_facebook)); + } + } else if (btn.getId() == R.id.btnAOL) { + if (!getMAThemeString().equals("dark")) { + btn.setImageDrawable(getResources().getDrawable( + R.drawable.logo_aol_light)); + } else { + btn.setImageDrawable(getResources().getDrawable( + R.drawable.logo_aol)); + } + } else if (btn.getId() == R.id.btnTwitter) { + if (!getMAThemeString().equals("dark")) { + btn.setImageDrawable(getResources().getDrawable( + R.drawable.logo_twitter_light)); + } else { + btn.setImageDrawable(getResources().getDrawable( + R.drawable.logo_twitter)); + } + } else if (btn.getId() == R.id.btnLive) { + if (!getMAThemeString().equals("dark")) { + btn.setImageDrawable(getResources().getDrawable( + R.drawable.logo_live_light)); + } else { + btn.setImageDrawable(getResources().getDrawable( + R.drawable.logo_live)); + } + } else if (btn.getId() == R.id.btnOpenID) { + if (!getMAThemeString().equals("dark")) { + btn.setImageDrawable(getResources().getDrawable( + R.drawable.logo_openid_light)); + } else { + btn.setImageDrawable(getResources().getDrawable( + R.drawable.logo_openid)); + } + } + + btn.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + ImageButton img = (ImageButton) v; + Intent intent = new Intent(getApplicationContext(), + MediNETActivity.class); + + if (img.getId() == R.id.btnGoogle) { + intent.putExtra("provider", "Google"); + } else if (img.getId() == R.id.btnFacebook) { + intent.putExtra("provider", "Facebook"); + } else if (img.getId() == R.id.btnAOL) { + intent.putExtra("provider", "AOL"); + } else if (img.getId() == R.id.btnTwitter) { + intent.putExtra("provider", "Twitter"); + } else if (img.getId() == R.id.btnLive) { + intent.putExtra("provider", "Live"); + } else if (img.getId() == R.id.btnOpenID) { + intent.putExtra("provider", "OpenID"); + } + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + + if (alertDialog != null) { + try { + alertDialog.dismiss(); + } catch (Exception e) { + // Do nothing + } + } + + startActivity(intent); + } + }); + } + + alertDialog = new AlertDialog.Builder(activity) + .setView(view) + .setTitle(R.string.signInToMediNET) + .setIcon( + activity.getResources().getDrawable( + getTheme().obtainStyledAttributes(getMATheme(true), + new int[]{R.attr.actionIconForward}) + .getResourceId(0, 0) + ) + ).create(); + alertDialog + .setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + if (getMediNETKey() == "") { + getMediNET().status = "disconnected"; + getMediNET().updated(); + } + } + }); + alertDialog.setOnCancelListener(new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + if (getMediNETKey() == "") { + getMediNET().status = "disconnected"; + getMediNET().updated(); + } + } + }); + + alertDialog.show(); + return alertDialog; + } + + public AlertDialog showStaleDataDialog() { + Log.d("MeditationAssistant", "Showing stale data dialog"); + + try { + Looper.prepare(); + } catch (Exception e) { + //e.printStackTrace(); + } + + if (getMediNET().activity != null) { + AlertDialog staleDataDialog = new AlertDialog.Builder( + getMediNET().activity) + .setPositiveButton(R.string.wordimport, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, + int id) { + getMediNET().syncSessions(); + } + } + ) + .setNegativeButton(R.string.dismiss, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, + int id) { + // Do nothing + } + } + ) + .setTitle(R.string.importsessionstitle) + .setMessage(R.string.importsessionsmessage) + .setIcon( + getMediNET().activity + .getResources() + .getDrawable( + getTheme() + .obtainStyledAttributes( + getMATheme(true), + new int[]{R.attr.actionIconDownCloud}) + .getResourceId(0, 0) + ) + ) + .create(); + + staleDataDialog.show(); + + return staleDataDialog; + } else { + longToast(getString(R.string.importSessionsHint)); + } + + return null; + } + + public void updateWidgets() { + AppWidgetManager man = AppWidgetManager + .getInstance(getApplicationContext()); + /*int[] ids = man.getAppWidgetIds(new ComponentName( + getApplicationContext(), MeditationProvider.class));*/ + Intent updateIntent = new Intent(); + updateIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE); + getApplicationContext().sendBroadcast(updateIntent); + } + + public Boolean vibrationEnabled() { + return (getPrefs().getBoolean("pref_vibrate", false) && canVibrate()); + } + + public void vibrateDevice() { + if (vibrationEnabled()) { + try { + Vibrator vi = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); + long[] pattern = {225, 110, 225, 110, 225, 110}; + vi.vibrate(pattern, -1); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + public String getMAAppVersion() { + if (appVersion == null) { + appVersion = ""; + try { + PackageInfo pInfo = getPackageManager().getPackageInfo( + getPackageName(), 0); + appVersion = pInfo.versionName; + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + } + + return appVersion; + } + + public int getMAAppVersionNumber() { + return BuildConfig.VERSION_CODE; + } + + public Boolean getMAIsAppFull() { + if (appFull == null) { + appFull = !(getPackageName().equals( + "sh.ftp.rocketninelabs.meditationassistant")); + } + + return appFull; + } + + public enum TrackerName { + APP_TRACKER, // Tracker used only in this app. + GLOBAL_TRACKER, // Tracker used by all the apps from a company. eg: roll-up tracking. + ECOMMERCE_TRACKER, // Tracker used by all ecommerce transactions from a company. + } + + private class OnTokenAcquired implements AccountManagerCallback { + @Override + public void run(AccountManagerFuture result) { + + Intent launch = null; + try { + launch = (Intent) result.getResult().get(AccountManager.KEY_INTENT); + + if (launch == null) { + String authtoken = result.getResult().getString(AccountManager.KEY_AUTHTOKEN); + if (!authtoken.equals("")) { + getMediNET().signInWithAuthToken(authtoken); + } + } + } catch (OperationCanceledException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (AuthenticatorException e) { + e.printStackTrace(); + } + if (launch != null) { + signin_activity.startActivityForResult(launch, 0); + } + } + } +} \ No newline at end of file diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MeditationProvider.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MeditationProvider.java new file mode 100644 index 0000000..63192fe --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MeditationProvider.java @@ -0,0 +1,87 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +import android.appwidget.AppWidgetManager; +import android.appwidget.AppWidgetProvider; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.util.Log; + +public class MeditationProvider extends AppWidgetProvider { + + private int[] mergeInts(int[] arg1, int[] arg2) { + int[] result = new int[arg1.length + arg2.length]; + System.arraycopy(arg1, 0, result, 0, arg1.length); + System.arraycopy(arg2, 0, result, arg1.length, arg2.length); + return result; + } + + @Override + public void onEnabled(Context context) { + Log.d("MeditationAssistant", "Widget onEnabled"); + super.onEnabled(context); + } + + @Override + public void onReceive(Context context, Intent intent) { + super.onReceive(context, intent); + if (intent != null) { + Log.d("MeditationAssistant", "Provider intent: " + intent.toString()); + } + + if (intent != null + && intent.getAction() != null + && intent.getAction().equals( + AppWidgetManager.ACTION_APPWIDGET_UPDATE)) { + AppWidgetManager gm = AppWidgetManager.getInstance(context); + int[] ids = gm.getAppWidgetIds(new ComponentName(context, + MeditationProvider.class)); + ids = mergeInts(ids, gm.getAppWidgetIds(new ComponentName(context, + MeditationProvider2.class))); + ids = mergeInts(ids, gm.getAppWidgetIds(new ComponentName(context, + MeditationProvider3.class))); + + onUpdate(context, gm, ids); + } + } + + @Override + public void onUpdate(Context context, AppWidgetManager appWidgetManager, + int[] appWidgetIds) { + Intent intent = new Intent(context, MeditationService.class); + intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds); + context.startService(intent); + + String ids_formatted = ""; + for (int id : appWidgetIds) { + ids_formatted += ", " + String.valueOf(id); + } + Log.d("MeditationAssistant", "Widget onUpdate, service started for IDs: " + ids_formatted); + + super.onUpdate(context, appWidgetManager, appWidgetIds); + + + /* + * int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget); + * for (int widgetId : allWidgetIds) { RemoteViews remoteViews = new + * RemoteViews(context.getPackageName(), R.layout.widget_layout); + * + * SActivity ctx = (SActivity) context; Log.d("MeditationAssistant", + * "!!!" + ctx.getApplication().toString()); // Set the text + * remoteViews.setTextViewText(R.id.txtDays, ctx.getApplication() + * .toString()); + * + * // Register an onClickListener // Intent intent = new Intent(context, + * MeditationProvider.class); + * + * // intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE); // + * intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, // + * appWidgetIds); + * + * // PendingIntent pendingIntent = PendingIntent.getBroadcast(context, + * // 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); // + * remoteViews.setOnClickPendingIntent(R.id.update, pendingIntent); + * appWidgetManager.updateAppWidget(widgetId, remoteViews); } + */ + } +} diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MeditationProvider1.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MeditationProvider1.java new file mode 100644 index 0000000..45d026d --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MeditationProvider1.java @@ -0,0 +1,5 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +public class MeditationProvider1 extends MeditationProvider { + +} diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MeditationProvider2.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MeditationProvider2.java new file mode 100644 index 0000000..ee835bc --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MeditationProvider2.java @@ -0,0 +1,5 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +public class MeditationProvider2 extends MeditationProvider { + +} diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MeditationProvider3.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MeditationProvider3.java new file mode 100644 index 0000000..41bde2d --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MeditationProvider3.java @@ -0,0 +1,5 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +public class MeditationProvider3 extends MeditationProvider { + +} diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MeditationService.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MeditationService.java new file mode 100644 index 0000000..3f55318 --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MeditationService.java @@ -0,0 +1,76 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +import android.app.PendingIntent; +import android.app.Service; +import android.appwidget.AppWidgetManager; +import android.content.Intent; +import android.os.IBinder; +import android.util.Log; +import android.widget.RemoteViews; + +public class MeditationService extends Service { + public IBinder onBind(Intent intent) { + return null; + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this + .getApplicationContext()); + Log.d("MeditationAssistant", "Widget onStartCommand(): " + String.valueOf(intent)); + + if (intent == null) { + Log.d("MeditationAssistant", "Widget intent was null, exiting..."); + return START_STICKY; + } + + int[] allWidgetIds = intent + .getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS); + + /* + * ComponentName thisWidget = new ComponentName(getApplicationContext(), + * MeditationProvider.class); + */ + + for (int widgetId : allWidgetIds) { + RemoteViews updateViews = new RemoteViews(this.getPackageName(), + R.layout.widget_layout); + getApplication(); + + MeditationAssistant ma = (MeditationAssistant) this + .getApplication(); + + if (ma.getMeditationStreak() > 0) { + updateViews.setTextViewText(R.id.txtWidgetDays, + String.valueOf(ma.getMeditationStreak())); + updateViews.setTextViewText( + R.id.txtWidgetText, + getResources().getQuantityString( + R.plurals.daysOfMeditationWithoutCount, + ma.getMeditationStreak()) + ); + } else { + updateViews.setTextViewText(R.id.txtWidgetDays, + getString(R.string.ignore_om)); + updateViews.setTextViewText(R.id.txtWidgetText, + getString(R.string.meditateToday)); + } + + Intent clickintent = new Intent(getApplicationContext(), + MainActivity.class); + // clickintent.putExtra("widgetid", startId); + clickintent.setAction("widgetclick"); + PendingIntent pendingIntent = PendingIntent.getActivity( + getApplicationContext(), 0, clickintent, 0); + updateViews.setOnClickPendingIntent(R.id.layWidget, pendingIntent); + updateViews.setOnClickPendingIntent(R.id.txtWidgetDays, + pendingIntent); + updateViews.setOnClickPendingIntent(R.id.txtWidgetText, + pendingIntent); + + appWidgetManager.updateAppWidget(widgetId, updateViews); + } + + return START_STICKY; + } +} diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MeditationSession.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MeditationSession.java new file mode 100644 index 0000000..c0aeff0 --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MeditationSession.java @@ -0,0 +1,30 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +import org.json.JSONException; +import org.json.JSONObject; + +public class MeditationSession { + public long id = 0; + public long length = 0; + public long started = 0; + public long completed = 0; + public long streakday = 0; + public String date = ""; + public String time = ""; + public String message = ""; + + public JSONObject export() { + JSONObject jobj = new JSONObject(); + try { + jobj.put("id", id); + jobj.put("length", length); + jobj.put("started", started); + jobj.put("completed", completed); + jobj.put("streakday", streakday); + jobj.put("message", message); + } catch (JSONException e1) { + e1.printStackTrace(); + } + return jobj; + } +} diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MeditationSounds.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MeditationSounds.java new file mode 100644 index 0000000..1c99e11 --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MeditationSounds.java @@ -0,0 +1,45 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +public class MeditationSounds { + public static int getMeditationSound(String sound) { + if (sound.equals("gong")) { + return R.raw.gong; + } else if (sound.equals("gong_burmese")) { + return R.raw.gong_burmese; + } else if (sound.equals("gong_metal")) { + return R.raw.gong_metal; + } else if (sound.equals("gong_heavy")) { + return R.raw.gong_heavy; + } else if (sound.equals("bell_indian")) { + return R.raw.bell_indian; + } else if (sound.equals("bell_temple")) { + return R.raw.bell_temple; + } else if (sound.equals("tinsha")) { + return R.raw.tinsha; + } else if (sound.equals("None")) { + return 0; + } + return R.raw.gong; + } + + public static String getMeditationSoundName(String sound) { // TODO: Localize + if (sound.equals("gong")) { + return "Gong"; + } else if (sound.equals("gong_burmese")) { + return "Burmese gong"; + } else if (sound.equals("gong_metal")) { + return "Metal gong"; + } else if (sound.equals("gong_heavy")) { + return "Heavy gong"; + } else if (sound.equals("bell_indian")) { + return "Indian bell"; + } else if (sound.equals("bell_temple")) { + return "Temple bell"; + } else if (sound.equals("tinsha")) { + return "Three Tinsha"; + } else if (sound.equals("none")) { + return ""; + } + return "Gong"; + } +} \ No newline at end of file diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MonthAdapter.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MonthAdapter.java new file mode 100644 index 0000000..611d3ea --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MonthAdapter.java @@ -0,0 +1,17 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +import android.content.Context; +import android.util.DisplayMetrics; +import android.view.View; + +public class MonthAdapter extends MonthAdapterMA { + + public MonthAdapter(Context c, int month, int year, DisplayMetrics metrics, ProgressActivity _pa, + MeditationAssistant _ma) { + super(c, month, year, metrics, _pa, _ma); + } + + @Override + protected void onDate(int[] date, int position, View item) { + } +} \ No newline at end of file diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MonthAdapterMA.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MonthAdapterMA.java new file mode 100644 index 0000000..236d53b --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/MonthAdapterMA.java @@ -0,0 +1,303 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +import android.content.Context; +import android.graphics.Paint; +import android.graphics.Typeface; +import android.util.DisplayMetrics; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.TextView; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.List; + +public abstract class MonthAdapterMA extends BaseAdapter { + private final int[] mDaysInMonth = {31, 28, 31, 30, 31, 30, 31, 31, 30, + 31, 30, 31}; + private GregorianCalendar mCalendar; + private Calendar mCalendarToday; + private Context mContext; + private DisplayMetrics mDisplayMetrics; + private List mItems; + private int mMonth; + private int mYear; + private int mDaysShown; + private int mDaysLastMonth; + private int mDaysNextMonth; + private int mDayHeight; + private String[] mDays = null; + private MeditationAssistant ma = null; + private ProgressActivity pa = null; + + public MonthAdapterMA(Context c, int month, int year, + DisplayMetrics metrics, ProgressActivity _pa, MeditationAssistant _ma) { + mContext = c; + mDayHeight = MeditationAssistant.dpToPixels(50, mContext); + + mMonth = month; + mYear = year; + mCalendar = new GregorianCalendar(mYear, mMonth, 1); + mCalendarToday = Calendar.getInstance(); + mDisplayMetrics = metrics; + ma = _ma; + pa = _pa; + + mDays = new String[]{mContext.getString(R.string.dayMondayShort), + mContext.getString(R.string.dayTuesdayShort), + mContext.getString(R.string.dayWednesdayShort), + mContext.getString(R.string.dayThursdayShort), + mContext.getString(R.string.dayFridayShort), + mContext.getString(R.string.daySaturdayShort), + mContext.getString(R.string.daySundayShort)}; + populateMonth(); + } + + private int daysInMonth(int month) { + int daysInMonth = mDaysInMonth[month]; + if (month == 1 && mCalendar.isLeapYear(mYear)) + daysInMonth++; + return daysInMonth; + } + + private int getBarHeight() { + switch (mDisplayMetrics.densityDpi) { + case DisplayMetrics.DENSITY_HIGH: + return 48; + case DisplayMetrics.DENSITY_MEDIUM: + return 32; + case DisplayMetrics.DENSITY_LOW: + return 24; + default: + return 48; + } + } + + @Override + public int getCount() { + return mItems.size(); + } + + private int[] getDate(int position) { + int date[] = new int[3]; + if (position <= 6) { + return null; // day names + } else if (position <= mDaysLastMonth + 6) { + // previous month + date[0] = Integer.parseInt(mItems.get(position)); + if (mMonth == 0) { + date[1] = 11; + date[2] = mYear - 1; + } else { + date[1] = mMonth - 1; + date[2] = mYear; + } + } else if (position <= mDaysShown - mDaysNextMonth) { + // current month + date[0] = position - (mDaysLastMonth + 6); + date[1] = mMonth; + date[2] = mYear; + } else { + // next month + date[0] = Integer.parseInt(mItems.get(position)); + if (mMonth == 11) { + date[1] = 0; + date[2] = mYear + 1; + } else { + date[1] = mMonth + 1; + date[2] = mYear; + } + } + return date; + } + + private int getDay(int day) { + switch (day) { + case Calendar.MONDAY: + return 0; + case Calendar.TUESDAY: + return 1; + case Calendar.WEDNESDAY: + return 2; + case Calendar.THURSDAY: + return 3; + case Calendar.FRIDAY: + return 4; + case Calendar.SATURDAY: + return 5; + case Calendar.SUNDAY: + return 6; + default: + return 0; + } + } + + @Override + public Object getItem(int position) { + return mItems.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + public MeditationAssistant getMeditationAssistant() { + return ma; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + final TextView view = new TextView(mContext); + view.setGravity(Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL); + view.setText(mItems.get(position)); + + int[] date = getDate(position); + if (date != null) { + view.setTextSize(20); + String date_formatted = String.valueOf(date[0]) + "-" + + String.valueOf(date[1] + 1) + "-" + + String.valueOf(date[2]); + + int numSessions = getMeditationAssistant().db.numSessionsByDate(date_formatted); + if (numSessions > 0) { + // At least one meditation session exists for this date + + view.setTag(R.id.calendarDate, date); + view.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + int[] date = (int[]) view.getTag(R.id.calendarDate); + if (date != null) { + pa.goToSessionAtDate(date); + } + } + }); + + if (getMeditationAssistant().getMAThemeString().equals("dark")) { + /*int bgcolor = (date[1] == mMonth) ? R.color.highlighted_text_light + : R.color.dim_foreground_light;*/ + int bgcolor = (date[1] == mMonth) ? android.R.color.holo_blue_dark + : android.R.color.secondary_text_dark; + + // : android.R.color.dim_foreground_light; + + view.setBackgroundColor(getMeditationAssistant() + .getResources().getColor(bgcolor)); + } else { + int bgcolor = (date[1] == mMonth) ? R.color.highlighted_text_dark + : R.color.dim_foreground_dark; + //: R.color.dim_foreground_holo_dark; + + view.setBackgroundColor(getMeditationAssistant() + .getResources().getColor(bgcolor)); + } + + if (numSessions > 1) { // Make large and bold if there's more than one session + view.setTypeface(null, Typeface.BOLD); + view.setTextSize(23); + } + } + + view.setHeight(mDayHeight); + if (date[1] != mMonth) { // previous or next month + if (getMeditationAssistant().getMAThemeString().equals("dark")) { + view.setTextColor(getMeditationAssistant().getResources() + .getColor(android.R.color.tertiary_text_light)); + } else { + view.setTextColor(getMeditationAssistant().getResources() + .getColor(android.R.color.tertiary_text_dark)); + } + } else { // current month + view.setTextColor(getMeditationAssistant() + .getResources() + .getColor( + getMeditationAssistant() + .getTheme() + .obtainStyledAttributes( + getMeditationAssistant() + .getMATheme(), + new int[]{android.R.attr.textColorPrimary} + ) + .getResourceId(0, 0) + )); + + if (isToday(date[0], date[1], date[2])) { + view.setPaintFlags(view.getPaintFlags() + | Paint.UNDERLINE_TEXT_FLAG); + } + } + } else { + view.setTextSize(16); + view.setPadding(0, 0, 0, + MeditationAssistant.dpToPixels(1, mContext)); + view.setTypeface(null, Typeface.BOLD); + view.setTextColor(getMeditationAssistant().getResources().getColor( + getMeditationAssistant() + .getTheme() + .obtainStyledAttributes( + getMeditationAssistant().getMATheme(), + new int[]{android.R.attr.textColorPrimary}) + .getResourceId(0, 0) + )); + view.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.TOP); + } + + onDate(date, position, view); + return view; + } + + @Override + public boolean isEnabled(int position) { + return false; + } + + private boolean isToday(int day, int month, int year) { + return mCalendarToday.get(Calendar.MONTH) == month + && mCalendarToday.get(Calendar.YEAR) == year + && mCalendarToday.get(Calendar.DAY_OF_MONTH) == day; + } + + /** + * @param date - null if day title (0 - dd / 1 - mm / 2 - yy) + * @param position - position in item list + * @param item - view for date + */ + protected abstract void onDate(int[] date, int position, View item); + + private void populateMonth() { + mItems = new ArrayList(); + for (String day : mDays) { + mItems.add(day); + mDaysShown++; + } + + int firstDay = getDay(mCalendar.get(Calendar.DAY_OF_WEEK)); + int prevDay; + if (mMonth == 0) + prevDay = daysInMonth(11) - firstDay + 1; + else + prevDay = daysInMonth(mMonth - 1) - firstDay + 1; + for (int i = 0; i < firstDay; i++) { + mItems.add(String.valueOf(prevDay + i)); + mDaysLastMonth++; + mDaysShown++; + } + + int daysInMonth = daysInMonth(mMonth); + for (int i = 1; i <= daysInMonth; i++) { + mItems.add(String.valueOf(i)); + mDaysShown++; + } + + mDaysNextMonth = 1; + while (mDaysShown % 7 != 0) { + mItems.add(String.valueOf(mDaysNextMonth)); + mDaysShown++; + mDaysNextMonth++; + } + } +} \ No newline at end of file diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/NumToWord.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/NumToWord.java new file mode 100644 index 0000000..b68b5ee --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/NumToWord.java @@ -0,0 +1,94 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +import java.util.Scanner; + +public class NumToWord { + // array containing single digits + public static final String[] digits = {"", "one", "two", "three", "four", + "five", "six", "seven", "eight", "nine", + }; + + // array containing teens + public static final String[] teens = {"eleven", "twelve", "thirteen", + "fourteen", " fifteen", "sixteen", "seventeen", "eighteen", + "nineteen"}; + + // array containing tens numbers + public static final String[] tens = {"ten", "twenty", "therty", "fourty", + "fifty", "sixty", "seventy", "eighty", "ninety",}; + + // string for hundreds numbers + public static final String hundred = "hundred"; + + public static int tmpDigit, // temp number to store digits + tmpTeen, // temp to store teens numbers + tmpTen, // temp number to store tens + number, // number to be converted to words + result; // result number + // deciding whether a num is teen or not + public static boolean teen = false; + + public static String getWord(int num) { + if (num > 0 && num < 10) { + result = num % 10; + return digits[result]; + } + if (num > 10 && num < 20) { + result = num % 10; + return teens[result - 1]; + } + if (num > 19 && num < 100) { + result = num / 10; + return tens[result - 1] + digits[num % 10]; + } + return ""; + } + + public static void main(String[] args) { + + Scanner in = new Scanner(System.in); + + // getting user input + System.out.print("Please enter a number: "); + number = in.nextInt(); // number to be converted + // input validation + while (number <= 0) { + System.out.println("Number should be bigger than cero!"); + System.out.print("Please enter a number:"); + number = in.nextInt(); + } + // converting single digits number + if (number > 0 && number < 10) { + result = number % 10; + System.out.println(digits[result]); + } + // converting teen numbers + if (number > 10 && number < 20) { + result = number % 10; + System.out.println(teens[result - 1]); + } + // converting from 20 to 100 numbers + if (number > 19 && number < 100) { + result = number / 10; // finding tens + System.out.print(tens[result - 1]); + + number %= 10; // finding single digits + System.out.println(digits[number]); + } + // converting from 101 to 999 + if (number > 100 && number < 1000) { + result = number / 100; // getting hundreds + // getting tens, and finding tens, and teens numbers + tmpTen = number % 100; + if (tmpTen > 1 && tmpTen < 20)// if teen go get it + { + tmpTeen = tmpTen % 10; + teen = true; + } else + // if not a teen split number + tmpTen /= 10; + // finding digits + tmpDigit = number % 10; + } + } +} diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/NumberPicker.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/NumberPicker.java new file mode 100644 index 0000000..9907169 --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/NumberPicker.java @@ -0,0 +1,2642 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import android.annotation.TargetApi; +import android.content.Context; +import android.content.res.ColorStateList; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Paint.Align; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Bundle; +import android.text.InputFilter; +import android.text.InputType; +import android.text.Spanned; +import android.text.TextUtils; +import android.text.method.NumberKeyListener; +import android.util.AttributeSet; +import android.util.SparseArray; +import android.util.TypedValue; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.LayoutInflater.Filter; +import android.view.MotionEvent; +import android.view.VelocityTracker; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityManager; +import android.view.accessibility.AccessibilityNodeInfo; +import android.view.accessibility.AccessibilityNodeProvider; +import android.view.animation.DecelerateInterpolator; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageButton; +import android.widget.LinearLayout; +import android.widget.TextView; + +import java.text.DecimalFormatSymbols; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Locale; + +//import android.annotation.Widget; + +/** + * A widget that enables the user to select a number form a predefined range. + * There are two flavors of this widget and which one is presented to the user + * depends on the current theme. + *
    + *
  • + * If the current theme is derived from {@link android.R.style#Theme} the widget + * presents the current value as an editable input field with an increment button + * above and a decrement button below. Long pressing the buttons allows for a quick + * change of the current value. Tapping on the input field allows to type in + * a desired value. + *
  • + *
  • + * If the current theme is derived from {@link android.R.style#Theme_Holo} or + * {@link android.R.style#Theme_Holo_Light} the widget presents the current + * value as an editable input field with a lesser value above and a greater + * value below. Tapping on the lesser or greater value selects it by animating + * the number axis up or down to make the chosen value current. Flinging up + * or down allows for multiple increments or decrements of the current value. + * Long pressing on the lesser and greater values also allows for a quick change + * of the current value. Tapping on the current value allows to type in a + * desired value. + *
  • + *
+ *

+ * For an example of using this widget, see {@link android.widget.TimePicker}. + *

+ */ +//@Widget +@SuppressWarnings("*") +public class NumberPicker extends LinearLayout { + + /** + * The number of items show in the selector wheel. + */ + private static final int SELECTOR_WHEEL_ITEM_COUNT = 3; + + /** + * The default update interval during long press. + */ + private static final long DEFAULT_LONG_PRESS_UPDATE_INTERVAL = 300; + + /** + * The index of the middle selector item. + */ + private static final int SELECTOR_MIDDLE_ITEM_INDEX = SELECTOR_WHEEL_ITEM_COUNT / 2; + + /** + * The coefficient by which to adjust (divide) the max fling velocity. + */ + private static final int SELECTOR_MAX_FLING_VELOCITY_ADJUSTMENT = 8; + + /** + * The the duration for adjusting the selector wheel. + */ + private static final int SELECTOR_ADJUSTMENT_DURATION_MILLIS = 800; + + /** + * The duration of scrolling while snapping to a given position. + */ + private static final int SNAP_SCROLL_DURATION = 300; + + /** + * The strength of fading in the top and bottom while drawing the selector. + */ + private static final float TOP_AND_BOTTOM_FADING_EDGE_STRENGTH = 0.9f; + + /** + * The default unscaled height of the selection divider. + */ + private static final int UNSCALED_DEFAULT_SELECTION_DIVIDER_HEIGHT = 2; + + /** + * The default unscaled distance between the selection dividers. + */ + private static final int UNSCALED_DEFAULT_SELECTION_DIVIDERS_DISTANCE = 48; + + /** + * The resource id for the default layout. + */ + private static final int DEFAULT_LAYOUT_RESOURCE_ID = 0; + + /** + * Constant for unspecified size. + */ + private static final int SIZE_UNSPECIFIED = -1; + private static final TwoDigitFormatter sTwoDigitFormatter = new TwoDigitFormatter(); + /** + * The numbers accepted by the input text's {@link Filter} + */ + private static final char[] DIGIT_CHARACTERS = new char[]{ + // Latin digits are the common case + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + // Arabic-Indic + '\u0660', '\u0661', '\u0662', '\u0663', '\u0664', '\u0665', '\u0666', '\u0667', '\u0668' + , '\u0669', + // Extended Arabic-Indic + '\u06f0', '\u06f1', '\u06f2', '\u06f3', '\u06f4', '\u06f5', '\u06f6', '\u06f7', '\u06f8' + , '\u06f9' + }; + /** + * The increment button. + */ + private final ImageButton mIncrementButton; + /** + * The decrement button. + */ + private final ImageButton mDecrementButton; + /** + * The text for showing the current value. + */ + private final EditText mInputText; + /** + * The distance between the two selection dividers. + */ + private final int mSelectionDividersDistance; + /** + * The min height of this widget. + */ + private final int mMinHeight; + /** + * The max height of this widget. + */ + private final int mMaxHeight; + /** + * The max width of this widget. + */ + private final int mMinWidth; + /** + * Flag whether to compute the max width. + */ + private final boolean mComputeMaxWidth; + /** + * The height of the text. + */ + private final int mTextSize; + /** + * Cache for the string representation of selector indices. + */ + private final SparseArray mSelectorIndexToStringCache = new SparseArray(); + /** + * The selector indices whose value are show by the selector. + */ + private final int[] mSelectorIndices = new int[SELECTOR_WHEEL_ITEM_COUNT]; + /** + * The {@link Paint} for drawing the selector. + */ + private final Paint mSelectorWheelPaint; + /** + * The {@link Drawable} for pressed virtual (increment/decrement) buttons. + */ + private final Drawable mVirtualButtonPressedDrawable; + /** + * The {@link Scroller} responsible for flinging the selector. + */ + private final Scroller mFlingScroller; + /** + * The {@link Scroller} responsible for adjusting the selector. + */ + private final Scroller mAdjustScroller; + /** + * The back ground color used to optimize scroller fading. + */ + private final int mSolidColor; + /** + * Flag whether this widget has a selector wheel. + */ + private final boolean mHasSelectorWheel; + /** + * Divider for showing item to be selected while scrolling + */ + private final Drawable mSelectionDivider; + /** + * The height of the selection divider. + */ + private final int mSelectionDividerHeight; + /** + * Helper class for managing pressed state of the virtual buttons. + */ + private final PressedStateHelper mPressedStateHelper; + /** + * The max width of this widget. + */ + private int mMaxWidth; + /** + * The height of the gap between text elements if the selector wheel. + */ + private int mSelectorTextGapHeight; + /** + * The values to be displayed instead the indices. + */ + private String[] mDisplayedValues; + /** + * Lower value of the range of numbers allowed for the NumberPicker + */ + private int mMinValue; + /** + * Upper value of the range of numbers allowed for the NumberPicker + */ + private int mMaxValue; + /** + * Current value of this NumberPicker + */ + private int mValue; + /** + * Listener to be notified upon current value change. + */ + private OnValueChangeListener mOnValueChangeListener; + /** + * Listener to be notified upon scroll state change. + */ + private OnScrollListener mOnScrollListener; + /** + * Formatter for for displaying the current value. + */ + private Formatter mFormatter; + /** + * The speed for updating the value form long press. + */ + private long mLongPressUpdateInterval = DEFAULT_LONG_PRESS_UPDATE_INTERVAL; + /** + * The height of a selector element (text + gap). + */ + private int mSelectorElementHeight; + /** + * The initial offset of the scroll selector. + */ + private int mInitialScrollOffset = Integer.MIN_VALUE; + /** + * The current offset of the scroll selector. + */ + private int mCurrentScrollOffset; + /** + * The previous Y coordinate while scrolling the selector. + */ + private int mPreviousScrollerY; + /** + * Handle to the reusable command for setting the input text selection. + */ + private SetSelectionCommand mSetSelectionCommand; + /** + * Handle to the reusable command for changing the current value from long + * press by one. + */ + private ChangeCurrentByOneFromLongPressCommand mChangeCurrentByOneFromLongPressCommand; + /** + * Command for beginning an edit of the current value via IME on long press. + */ + private BeginSoftInputOnLongPressCommand mBeginSoftInputOnLongPressCommand; + /** + * The Y position of the last down event. + */ + private float mLastDownEventY; + /** + * The time of the last down event. + */ + private long mLastDownEventTime; + /** + * The Y position of the last down or move event. + */ + private float mLastDownOrMoveEventY; + /** + * Determines speed during touch scrolling. + */ + private VelocityTracker mVelocityTracker; + /** + * @see ViewConfiguration#getScaledTouchSlop() + */ + private int mTouchSlop; + /** + * @see ViewConfiguration#getScaledMinimumFlingVelocity() + */ + private int mMinimumFlingVelocity; + /** + * @see ViewConfiguration#getScaledMaximumFlingVelocity() + */ + private int mMaximumFlingVelocity; + /** + * Flag whether the selector should wrap around. + */ + private boolean mWrapSelectorWheel; + /** + * The current scroll state of the number picker. + */ + private int mScrollState = OnScrollListener.SCROLL_STATE_IDLE; + + /** + * Flag whether to ignore move events - we ignore such when we show in IME + * to prevent the content from scrolling. + */ + private boolean mIngonreMoveEvents; + + /** + * Flag whether to show soft input on tap. + */ + private boolean mShowSoftInputOnTap; + + /** + * The top of the top selection divider. + */ + private int mTopSelectionDividerTop; + + /** + * The bottom of the bottom selection divider. + */ + private int mBottomSelectionDividerBottom; + + /** + * The virtual id of the last hovered child. + */ + private int mLastHoveredChildVirtualViewId; + + /** + * Whether the increment virtual button is pressed. + */ + private boolean mIncrementVirtualButtonPressed; + + /** + * Whether the decrement virtual button is pressed. + */ + private boolean mDecrementVirtualButtonPressed; + + /** + * Provider to report to clients the semantic structure of this widget. + */ + private SupportAccessibilityNodeProvider mAccessibilityNodeProvider; + /** + * The keycode of the last handled DPAD down event. + */ + private int mLastHandledDownDpadKeyCode = -1; + + /** + * Create a new number picker. + * + * @param context The application environment. + */ + public NumberPicker(Context context) { + this(context, null); + } + + /** + * Create a new number picker. + * + * @param context The application environment. + * @param attrs A collection of attributes. + */ + public NumberPicker(Context context, AttributeSet attrs) { + this(context, attrs, R.attr.numberPickerStyle); + } + + /** + * Create a new number picker + * + * @param context the application environment. + * @param attrs a collection of attributes. + * @param defStyle The default style to apply to this view. + */ + public NumberPicker(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs); + + // process style attributes + TypedArray attributesArray = context.obtainStyledAttributes( + attrs, R.styleable.NumberPicker, defStyle, 0); + final int layoutResId = attributesArray.getResourceId( + R.styleable.NumberPicker_internalLayout, DEFAULT_LAYOUT_RESOURCE_ID); + + mHasSelectorWheel = (layoutResId != DEFAULT_LAYOUT_RESOURCE_ID); + + mSolidColor = attributesArray.getColor(R.styleable.NumberPicker_solidColor, 0); + + mSelectionDivider = attributesArray.getDrawable(R.styleable.NumberPicker_selectionDivider); + + final int defSelectionDividerHeight = (int) TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, UNSCALED_DEFAULT_SELECTION_DIVIDER_HEIGHT, + getResources().getDisplayMetrics()); + mSelectionDividerHeight = attributesArray.getDimensionPixelSize( + R.styleable.NumberPicker_selectionDividerHeight, defSelectionDividerHeight); + + final int defSelectionDividerDistance = (int) TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, UNSCALED_DEFAULT_SELECTION_DIVIDERS_DISTANCE, + getResources().getDisplayMetrics()); + mSelectionDividersDistance = attributesArray.getDimensionPixelSize( + R.styleable.NumberPicker_selectionDividersDistance, defSelectionDividerDistance); + + mMinHeight = attributesArray.getDimensionPixelSize( + R.styleable.NumberPicker_internalMinHeight, SIZE_UNSPECIFIED); + + mMaxHeight = attributesArray.getDimensionPixelSize( + R.styleable.NumberPicker_internalMaxHeight, SIZE_UNSPECIFIED); + if (mMinHeight != SIZE_UNSPECIFIED && mMaxHeight != SIZE_UNSPECIFIED + && mMinHeight > mMaxHeight) { + throw new IllegalArgumentException("minHeight > maxHeight"); + } + + mMinWidth = attributesArray.getDimensionPixelSize( + R.styleable.NumberPicker_internalMinWidth, SIZE_UNSPECIFIED); + + mMaxWidth = attributesArray.getDimensionPixelSize( + R.styleable.NumberPicker_internalMaxWidth, SIZE_UNSPECIFIED); + if (mMinWidth != SIZE_UNSPECIFIED && mMaxWidth != SIZE_UNSPECIFIED + && mMinWidth > mMaxWidth) { + throw new IllegalArgumentException("minWidth > maxWidth"); + } + + mComputeMaxWidth = (mMaxWidth == SIZE_UNSPECIFIED); + + mVirtualButtonPressedDrawable = attributesArray.getDrawable( + R.styleable.NumberPicker_virtualButtonPressedDrawable); + + attributesArray.recycle(); + + mPressedStateHelper = new PressedStateHelper(); + + // By default Linearlayout that we extend is not drawn. This is + // its draw() method is not called but dispatchDraw() is called + // directly (see ViewGroup.drawChild()). However, this class uses + // the fading edge effect implemented by View and we need our + // draw() method to be called. Therefore, we declare we will draw. + setWillNotDraw(!mHasSelectorWheel); + + LayoutInflater inflater = (LayoutInflater) getContext().getSystemService( + Context.LAYOUT_INFLATER_SERVICE); + inflater.inflate(layoutResId, this, true); + + OnClickListener onClickListener = new OnClickListener() { + public void onClick(View v) { + hideSoftInput(); + mInputText.clearFocus(); + if (v.getId() == R.id.np__increment) { + changeValueByOne(true); + } else { + changeValueByOne(false); + } + } + }; + + OnLongClickListener onLongClickListener = new OnLongClickListener() { + public boolean onLongClick(View v) { + hideSoftInput(); + mInputText.clearFocus(); + if (v.getId() == R.id.np__increment) { + postChangeCurrentByOneFromLongPress(true, 0); + } else { + postChangeCurrentByOneFromLongPress(false, 0); + } + return true; + } + }; + + // increment button + if (!mHasSelectorWheel) { + mIncrementButton = (ImageButton) findViewById(R.id.np__increment); + mIncrementButton.setOnClickListener(onClickListener); + mIncrementButton.setOnLongClickListener(onLongClickListener); + } else { + mIncrementButton = null; + } + + // decrement button + if (!mHasSelectorWheel) { + mDecrementButton = (ImageButton) findViewById(R.id.np__decrement); + mDecrementButton.setOnClickListener(onClickListener); + mDecrementButton.setOnLongClickListener(onLongClickListener); + } else { + mDecrementButton = null; + } + + // input text + mInputText = (EditText) findViewById(R.id.np__numberpicker_input); + mInputText.setOnFocusChangeListener(new OnFocusChangeListener() { + public void onFocusChange(View v, boolean hasFocus) { + if (hasFocus) { + mInputText.selectAll(); + } else { + mInputText.setSelection(0, 0); + validateInputTextView(v); + } + } + }); + mInputText.setFilters(new InputFilter[]{ + new InputTextFilter() + }); + + mInputText.setRawInputType(InputType.TYPE_CLASS_NUMBER); + mInputText.setImeOptions(EditorInfo.IME_ACTION_DONE); + + // initialize constants + ViewConfiguration configuration = ViewConfiguration.get(context); + mTouchSlop = configuration.getScaledTouchSlop(); + mMinimumFlingVelocity = configuration.getScaledMinimumFlingVelocity(); + mMaximumFlingVelocity = configuration.getScaledMaximumFlingVelocity() + / SELECTOR_MAX_FLING_VELOCITY_ADJUSTMENT; + mTextSize = (int) mInputText.getTextSize(); + + // create the selector wheel paint + Paint paint = new Paint(); + paint.setAntiAlias(true); + paint.setTextAlign(Align.CENTER); + paint.setTextSize(mTextSize); + paint.setTypeface(mInputText.getTypeface()); + ColorStateList colors = mInputText.getTextColors(); + int color = colors.getColorForState(ENABLED_STATE_SET, Color.WHITE); + paint.setColor(color); + mSelectorWheelPaint = paint; + + // create the fling and adjust scrollers + mFlingScroller = new Scroller(getContext(), null, true); + mAdjustScroller = new Scroller(getContext(), new DecelerateInterpolator(2.5f)); + + updateInputTextView(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + // If not explicitly specified this view is important for accessibility. + if (getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) { + setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); + } + } + } + + /** + * @hide + */ + @SuppressWarnings("FinalStaticMethod") + public static final Formatter getTwoDigitFormatter() { + return sTwoDigitFormatter; + } + + /** + * Utility to reconcile a desired size and state, with constraints imposed + * by a MeasureSpec. Will take the desired size, unless a different size + * is imposed by the constraints. The returned value is a compound integer, + * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and + * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the resulting + * size is smaller than the size the view wants to be. + * + * @param size How big the view wants to be + * @param measureSpec Constraints imposed by the parent + * @return Size information bit mask as defined by + * {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}. + */ + public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) { + int result = size; + int specMode = MeasureSpec.getMode(measureSpec); + int specSize = MeasureSpec.getSize(measureSpec); + switch (specMode) { + case MeasureSpec.UNSPECIFIED: + result = size; + break; + case MeasureSpec.AT_MOST: + if (specSize < size) { + result = specSize | MEASURED_STATE_TOO_SMALL; + } else { + result = size; + } + break; + case MeasureSpec.EXACTLY: + result = specSize; + break; + } + return result | (childMeasuredState & MEASURED_STATE_MASK); + } + + static private String formatNumberWithLocale(int value) { + return String.format(Locale.getDefault(), "%d", value); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + if (!mHasSelectorWheel) { + super.onLayout(changed, left, top, right, bottom); + return; + } + final int msrdWdth = getMeasuredWidth(); + final int msrdHght = getMeasuredHeight(); + + // Input text centered horizontally. + final int inptTxtMsrdWdth = mInputText.getMeasuredWidth(); + final int inptTxtMsrdHght = mInputText.getMeasuredHeight(); + final int inptTxtLeft = (msrdWdth - inptTxtMsrdWdth) / 2; + final int inptTxtTop = (msrdHght - inptTxtMsrdHght) / 2; + final int inptTxtRight = inptTxtLeft + inptTxtMsrdWdth; + final int inptTxtBottom = inptTxtTop + inptTxtMsrdHght; + mInputText.layout(inptTxtLeft, inptTxtTop, inptTxtRight, inptTxtBottom); + + if (changed) { + // need to do all this when we know our size + initializeSelectorWheel(); + initializeFadingEdges(); + mTopSelectionDividerTop = (getHeight() - mSelectionDividersDistance) / 2 + - mSelectionDividerHeight; + mBottomSelectionDividerBottom = mTopSelectionDividerTop + 2 * mSelectionDividerHeight + + mSelectionDividersDistance; + } + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if (!mHasSelectorWheel) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + return; + } + // Try greedily to fit the max width and height. + final int newWidthMeasureSpec = makeMeasureSpec(widthMeasureSpec, mMaxWidth); + final int newHeightMeasureSpec = makeMeasureSpec(heightMeasureSpec, mMaxHeight); + super.onMeasure(newWidthMeasureSpec, newHeightMeasureSpec); + // Flag if we are measured with width or height less than the respective min. + final int widthSize = resolveSizeAndStateRespectingMinSize(mMinWidth, getMeasuredWidth(), + widthMeasureSpec); + final int heightSize = resolveSizeAndStateRespectingMinSize(mMinHeight, getMeasuredHeight(), + heightMeasureSpec); + setMeasuredDimension(widthSize, heightSize); + } + + /** + * Move to the final position of a scroller. Ensures to force finish the scroller + * and if it is not at its final position a scroll of the selector wheel is + * performed to fast forward to the final position. + * + * @param scroller The scroller to whose final position to get. + * @return True of the a move was performed, i.e. the scroller was not in final position. + */ + private boolean moveToFinalScrollerPosition(Scroller scroller) { + scroller.forceFinished(true); + int amountToScroll = scroller.getFinalY() - scroller.getCurrY(); + int futureScrollOffset = (mCurrentScrollOffset + amountToScroll) % mSelectorElementHeight; + int overshootAdjustment = mInitialScrollOffset - futureScrollOffset; + if (overshootAdjustment != 0) { + if (Math.abs(overshootAdjustment) > mSelectorElementHeight / 2) { + if (overshootAdjustment > 0) { + overshootAdjustment -= mSelectorElementHeight; + } else { + overshootAdjustment += mSelectorElementHeight; + } + } + amountToScroll += overshootAdjustment; + scrollBy(0, amountToScroll); + return true; + } + return false; + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent event) { + if (!mHasSelectorWheel || !isEnabled()) { + return false; + } + final int action = event.getAction() & MotionEvent.ACTION_MASK; + switch (action) { + case MotionEvent.ACTION_DOWN: { + removeAllCallbacks(); + mInputText.setVisibility(View.INVISIBLE); + mLastDownOrMoveEventY = mLastDownEventY = event.getY(); + mLastDownEventTime = event.getEventTime(); + mIngonreMoveEvents = false; + mShowSoftInputOnTap = false; + // Handle pressed state before any state change. + if (mLastDownEventY < mTopSelectionDividerTop) { + if (mScrollState == OnScrollListener.SCROLL_STATE_IDLE) { + mPressedStateHelper.buttonPressDelayed( + PressedStateHelper.BUTTON_DECREMENT); + } + } else if (mLastDownEventY > mBottomSelectionDividerBottom) { + if (mScrollState == OnScrollListener.SCROLL_STATE_IDLE) { + mPressedStateHelper.buttonPressDelayed( + PressedStateHelper.BUTTON_INCREMENT); + } + } + // Make sure we support flinging inside scrollables. + getParent().requestDisallowInterceptTouchEvent(true); + if (!mFlingScroller.isFinished()) { + mFlingScroller.forceFinished(true); + mAdjustScroller.forceFinished(true); + onScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE); + } else if (!mAdjustScroller.isFinished()) { + mFlingScroller.forceFinished(true); + mAdjustScroller.forceFinished(true); + } else if (mLastDownEventY < mTopSelectionDividerTop) { + hideSoftInput(); + postChangeCurrentByOneFromLongPress( + false, ViewConfiguration.getLongPressTimeout()); + } else if (mLastDownEventY > mBottomSelectionDividerBottom) { + hideSoftInput(); + postChangeCurrentByOneFromLongPress( + true, ViewConfiguration.getLongPressTimeout()); + } else { + mShowSoftInputOnTap = true; + postBeginSoftInputOnLongPressCommand(); + } + return true; + } + } + return false; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (!isEnabled() || !mHasSelectorWheel) { + return false; + } + if (mVelocityTracker == null) { + mVelocityTracker = VelocityTracker.obtain(); + } + mVelocityTracker.addMovement(event); + int action = event.getAction() & MotionEvent.ACTION_MASK; + switch (action) { + case MotionEvent.ACTION_MOVE: { + if (mIngonreMoveEvents) { + break; + } + float currentMoveY = event.getY(); + if (mScrollState != OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) { + int deltaDownY = (int) Math.abs(currentMoveY - mLastDownEventY); + if (deltaDownY > mTouchSlop) { + removeAllCallbacks(); + onScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL); + } + } else { + int deltaMoveY = (int) ((currentMoveY - mLastDownOrMoveEventY)); + scrollBy(0, deltaMoveY); + invalidate(); + } + mLastDownOrMoveEventY = currentMoveY; + } + break; + case MotionEvent.ACTION_UP: { + removeBeginSoftInputCommand(); + removeChangeCurrentByOneFromLongPress(); + mPressedStateHelper.cancel(); + VelocityTracker velocityTracker = mVelocityTracker; + velocityTracker.computeCurrentVelocity(1000, mMaximumFlingVelocity); + int initialVelocity = (int) velocityTracker.getYVelocity(); + if (Math.abs(initialVelocity) > mMinimumFlingVelocity) { + fling(initialVelocity); + onScrollStateChange(OnScrollListener.SCROLL_STATE_FLING); + } else { + int eventY = (int) event.getY(); + int deltaMoveY = (int) Math.abs(eventY - mLastDownEventY); + long deltaTime = event.getEventTime() - mLastDownEventTime; + long tapTimeout = ViewConfiguration.getTapTimeout(); + if (deltaMoveY <= mTouchSlop) { // && deltaTime < ViewConfiguration.getTapTimeout()) { + if (mShowSoftInputOnTap) { + mShowSoftInputOnTap = false; + showSoftInput(); + } else { + int selectorIndexOffset = (eventY / mSelectorElementHeight) + - SELECTOR_MIDDLE_ITEM_INDEX; + if (selectorIndexOffset > 0) { + changeValueByOne(true); + mPressedStateHelper.buttonTapped( + PressedStateHelper.BUTTON_INCREMENT); + } else if (selectorIndexOffset < 0) { + changeValueByOne(false); + mPressedStateHelper.buttonTapped( + PressedStateHelper.BUTTON_DECREMENT); + } + } + } else { + ensureScrollWheelAdjusted(); + } + onScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE); + } + mVelocityTracker.recycle(); + mVelocityTracker = null; + } + break; + } + return true; + } + + @Override + public boolean dispatchTouchEvent(MotionEvent event) { + final int action = event.getAction() & MotionEvent.ACTION_MASK; + switch (action) { + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: + removeAllCallbacks(); + break; + } + return super.dispatchTouchEvent(event); + } + + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + final int keyCode = event.getKeyCode(); + switch (keyCode) { + case KeyEvent.KEYCODE_DPAD_CENTER: + case KeyEvent.KEYCODE_ENTER: + removeAllCallbacks(); + break; + case KeyEvent.KEYCODE_DPAD_DOWN: + case KeyEvent.KEYCODE_DPAD_UP: + if (!mHasSelectorWheel) { + break; + } + switch (event.getAction()) { + case KeyEvent.ACTION_DOWN: + if (mWrapSelectorWheel || (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) + ? getValue() < getMaxValue() : getValue() > getMinValue()) { + requestFocus(); + mLastHandledDownDpadKeyCode = keyCode; + removeAllCallbacks(); + if (mFlingScroller.isFinished()) { + changeValueByOne(keyCode == KeyEvent.KEYCODE_DPAD_DOWN); + } + return true; + } + break; + case KeyEvent.ACTION_UP: + if (mLastHandledDownDpadKeyCode == keyCode) { + mLastHandledDownDpadKeyCode = -1; + return true; + } + break; + } + } + return super.dispatchKeyEvent(event); + } + + @Override + public boolean dispatchTrackballEvent(MotionEvent event) { + final int action = event.getAction() & MotionEvent.ACTION_MASK; + switch (action) { + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: + removeAllCallbacks(); + break; + } + return super.dispatchTrackballEvent(event); + } + + @Override + protected boolean dispatchHoverEvent(MotionEvent event) { + if (!mHasSelectorWheel) { + return super.dispatchHoverEvent(event); + } + + if (((AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE)).isEnabled()) { + final int eventY = (int) event.getY(); + final int hoveredVirtualViewId; + if (eventY < mTopSelectionDividerTop) { + hoveredVirtualViewId = AccessibilityNodeProviderImpl.VIRTUAL_VIEW_ID_DECREMENT; + } else if (eventY > mBottomSelectionDividerBottom) { + hoveredVirtualViewId = AccessibilityNodeProviderImpl.VIRTUAL_VIEW_ID_INCREMENT; + } else { + hoveredVirtualViewId = AccessibilityNodeProviderImpl.VIRTUAL_VIEW_ID_INPUT; + } + final int action = event.getAction() & MotionEvent.ACTION_MASK; + SupportAccessibilityNodeProvider provider = getSupportAccessibilityNodeProvider(); + + switch (action) { + case MotionEvent.ACTION_HOVER_ENTER: { + provider.sendAccessibilityEventForVirtualView(hoveredVirtualViewId, + AccessibilityEvent.TYPE_VIEW_HOVER_ENTER); + mLastHoveredChildVirtualViewId = hoveredVirtualViewId; + provider.performAction(hoveredVirtualViewId, + AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null); + } + break; + case MotionEvent.ACTION_HOVER_MOVE: { + if (mLastHoveredChildVirtualViewId != hoveredVirtualViewId + && mLastHoveredChildVirtualViewId != View.NO_ID) { + provider.sendAccessibilityEventForVirtualView( + mLastHoveredChildVirtualViewId, + AccessibilityEvent.TYPE_VIEW_HOVER_EXIT); + provider.sendAccessibilityEventForVirtualView(hoveredVirtualViewId, + AccessibilityEvent.TYPE_VIEW_HOVER_ENTER); + mLastHoveredChildVirtualViewId = hoveredVirtualViewId; + provider.performAction(hoveredVirtualViewId, + AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null); + } + } + break; + case MotionEvent.ACTION_HOVER_EXIT: { + provider.sendAccessibilityEventForVirtualView(hoveredVirtualViewId, + AccessibilityEvent.TYPE_VIEW_HOVER_EXIT); + mLastHoveredChildVirtualViewId = View.NO_ID; + } + break; + } + } + return false; + } + + @Override + public void computeScroll() { + Scroller scroller = mFlingScroller; + if (scroller.isFinished()) { + scroller = mAdjustScroller; + if (scroller.isFinished()) { + return; + } + } + scroller.computeScrollOffset(); + int currentScrollerY = scroller.getCurrY(); + if (mPreviousScrollerY == 0) { + mPreviousScrollerY = scroller.getStartY(); + } + scrollBy(0, currentScrollerY - mPreviousScrollerY); + mPreviousScrollerY = currentScrollerY; + if (scroller.isFinished()) { + onScrollerFinished(scroller); + } else { + invalidate(); + } + } + + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + if (!mHasSelectorWheel) { + mIncrementButton.setEnabled(enabled); + } + if (!mHasSelectorWheel) { + mDecrementButton.setEnabled(enabled); + } + mInputText.setEnabled(enabled); + } + + @Override + public void scrollBy(int x, int y) { + int[] selectorIndices = mSelectorIndices; + if (!mWrapSelectorWheel && y > 0 + && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] <= mMinValue) { + mCurrentScrollOffset = mInitialScrollOffset; + return; + } + if (!mWrapSelectorWheel && y < 0 + && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] >= mMaxValue) { + mCurrentScrollOffset = mInitialScrollOffset; + return; + } + mCurrentScrollOffset += y; + while (mCurrentScrollOffset - mInitialScrollOffset > mSelectorTextGapHeight) { + mCurrentScrollOffset -= mSelectorElementHeight; + decrementSelectorIndices(selectorIndices); + setValueInternal(selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX], true); + if (!mWrapSelectorWheel && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] <= mMinValue) { + mCurrentScrollOffset = mInitialScrollOffset; + } + } + while (mCurrentScrollOffset - mInitialScrollOffset < -mSelectorTextGapHeight) { + mCurrentScrollOffset += mSelectorElementHeight; + incrementSelectorIndices(selectorIndices); + setValueInternal(selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX], true); + if (!mWrapSelectorWheel && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] >= mMaxValue) { + mCurrentScrollOffset = mInitialScrollOffset; + } + } + } + + @Override + public int getSolidColor() { + return mSolidColor; + } + + /** + * Sets the listener to be notified on change of the current value. + * + * @param onValueChangedListener The listener. + */ + public void setOnValueChangedListener(OnValueChangeListener onValueChangedListener) { + mOnValueChangeListener = onValueChangedListener; + } + + /** + * Set listener to be notified for scroll state changes. + * + * @param onScrollListener The listener. + */ + public void setOnScrollListener(OnScrollListener onScrollListener) { + mOnScrollListener = onScrollListener; + } + + /** + * Set the formatter to be used for formatting the current value. + *

+ * Note: If you have provided alternative values for the values this + * formatter is never invoked. + *

+ * + * @param formatter The formatter object. If formatter is null, + * {@link String#valueOf(int)} will be used. + * @see #setDisplayedValues(String[]) + */ + public void setFormatter(Formatter formatter) { + if (formatter == mFormatter) { + return; + } + mFormatter = formatter; + initializeSelectorWheelIndices(); + updateInputTextView(); + } + + /** + * Shows the soft input for its input text. + */ + private void showSoftInput() { + InputMethodManager inputMethodManager = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + if (inputMethodManager != null) { + if (mHasSelectorWheel) { + mInputText.setVisibility(View.VISIBLE); + } + mInputText.requestFocus(); + inputMethodManager.showSoftInput(mInputText, 0); + } + } + + /** + * Hides the soft input if it is active for the input text. + */ + private void hideSoftInput() { + InputMethodManager inputMethodManager = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + if (inputMethodManager != null && inputMethodManager.isActive(mInputText)) { + inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0); + if (mHasSelectorWheel) { + mInputText.setVisibility(View.INVISIBLE); + } + } + } + + /** + * Computes the max width if no such specified as an attribute. + */ + private void tryComputeMaxWidth() { + if (!mComputeMaxWidth) { + return; + } + int maxTextWidth = 0; + if (mDisplayedValues == null) { + float maxDigitWidth = 0; + for (int i = 0; i <= 9; i++) { + final float digitWidth = mSelectorWheelPaint.measureText(formatNumberWithLocale(i)); + if (digitWidth > maxDigitWidth) { + maxDigitWidth = digitWidth; + } + } + int numberOfDigits = 0; + int current = mMaxValue; + while (current > 0) { + numberOfDigits++; + current = current / 10; + } + maxTextWidth = (int) (numberOfDigits * maxDigitWidth); + } else { + final int valueCount = mDisplayedValues.length; + for (int i = 0; i < valueCount; i++) { + final float textWidth = mSelectorWheelPaint.measureText(mDisplayedValues[i]); + if (textWidth > maxTextWidth) { + maxTextWidth = (int) textWidth; + } + } + } + maxTextWidth += mInputText.getPaddingLeft() + mInputText.getPaddingRight(); + if (mMaxWidth != maxTextWidth) { + if (maxTextWidth > mMinWidth) { + mMaxWidth = maxTextWidth; + } else { + mMaxWidth = mMinWidth; + } + invalidate(); + } + } + + /** + * Gets whether the selector wheel wraps when reaching the min/max value. + * + * @return True if the selector wheel wraps. + * @see #getMinValue() + * @see #getMaxValue() + */ + public boolean getWrapSelectorWheel() { + return mWrapSelectorWheel; + } + + /** + * Sets whether the selector wheel shown during flinging/scrolling should + * wrap around the {@link NumberPicker#getMinValue()} and + * {@link NumberPicker#getMaxValue()} values. + *

+ * By default if the range (max - min) is more than the number of items shown + * on the selector wheel the selector wheel wrapping is enabled. + *

+ *

+ * Note: If the number of items, i.e. the range ( + * {@link #getMaxValue()} - {@link #getMinValue()}) is less than + * the number of items shown on the selector wheel, the selector wheel will + * not wrap. Hence, in such a case calling this method is a NOP. + *

+ * + * @param wrapSelectorWheel Whether to wrap. + */ + public void setWrapSelectorWheel(boolean wrapSelectorWheel) { + final boolean wrappingAllowed = (mMaxValue - mMinValue) >= mSelectorIndices.length; + if ((!wrapSelectorWheel || wrappingAllowed) && wrapSelectorWheel != mWrapSelectorWheel) { + mWrapSelectorWheel = wrapSelectorWheel; + } + } + + /** + * Sets the speed at which the numbers be incremented and decremented when + * the up and down buttons are long pressed respectively. + *

+ * The default value is 300 ms. + *

+ * + * @param intervalMillis The speed (in milliseconds) at which the numbers + * will be incremented and decremented. + */ + public void setOnLongPressUpdateInterval(long intervalMillis) { + mLongPressUpdateInterval = intervalMillis; + } + + /** + * Returns the value of the picker. + * + * @return The value. + */ + public int getValue() { + return mValue; + } + + /** + * Set the current value for the number picker. + *

+ * If the argument is less than the {@link NumberPicker#getMinValue()} and + * {@link NumberPicker#getWrapSelectorWheel()} is false the + * current value is set to the {@link NumberPicker#getMinValue()} value. + *

+ *

+ * If the argument is less than the {@link NumberPicker#getMinValue()} and + * {@link NumberPicker#getWrapSelectorWheel()} is true the + * current value is set to the {@link NumberPicker#getMaxValue()} value. + *

+ *

+ * If the argument is less than the {@link NumberPicker#getMaxValue()} and + * {@link NumberPicker#getWrapSelectorWheel()} is false the + * current value is set to the {@link NumberPicker#getMaxValue()} value. + *

+ *

+ * If the argument is less than the {@link NumberPicker#getMaxValue()} and + * {@link NumberPicker#getWrapSelectorWheel()} is true the + * current value is set to the {@link NumberPicker#getMinValue()} value. + *

+ * + * @param value The current value. + * @see #setWrapSelectorWheel(boolean) + * @see #setMinValue(int) + * @see #setMaxValue(int) + */ + public void setValue(int value) { + setValueInternal(value, false); + } + + /** + * Returns the min value of the picker. + * + * @return The min value + */ + public int getMinValue() { + return mMinValue; + } + + /** + * Sets the min value of the picker. + * + * @param minValue The min value inclusive. + *

+ * Note: The length of the displayed values array + * set via {@link #setDisplayedValues(String[])} must be equal to the + * range of selectable numbers which is equal to + * {@link #getMaxValue()} - {@link #getMinValue()} + 1. + */ + public void setMinValue(int minValue) { + if (mMinValue == minValue) { + return; + } + if (minValue < 0) { + throw new IllegalArgumentException("minValue must be >= 0"); + } + mMinValue = minValue; + if (mMinValue > mValue) { + mValue = mMinValue; + } + boolean wrapSelectorWheel = mMaxValue - mMinValue > mSelectorIndices.length; + setWrapSelectorWheel(wrapSelectorWheel); + initializeSelectorWheelIndices(); + updateInputTextView(); + tryComputeMaxWidth(); + invalidate(); + } + + /** + * Returns the max value of the picker. + * + * @return The max value. + */ + public int getMaxValue() { + return mMaxValue; + } + + /** + * Sets the max value of the picker. + * + * @param maxValue The max value inclusive. + *

+ * Note: The length of the displayed values array + * set via {@link #setDisplayedValues(String[])} must be equal to the + * range of selectable numbers which is equal to + * {@link #getMaxValue()} - {@link #getMinValue()} + 1. + */ + public void setMaxValue(int maxValue) { + if (mMaxValue == maxValue) { + return; + } + if (maxValue < 0) { + throw new IllegalArgumentException("maxValue must be >= 0"); + } + mMaxValue = maxValue; + if (mMaxValue < mValue) { + mValue = mMaxValue; + } + boolean wrapSelectorWheel = mMaxValue - mMinValue > mSelectorIndices.length; + setWrapSelectorWheel(wrapSelectorWheel); + initializeSelectorWheelIndices(); + updateInputTextView(); + tryComputeMaxWidth(); + invalidate(); + } + + /** + * Gets the values to be displayed instead of string values. + * + * @return The displayed values. + */ + public String[] getDisplayedValues() { + return mDisplayedValues; + } + + /** + * Sets the values to be displayed. + * + * @param displayedValues The displayed values. + *

+ * Note: The length of the displayed values array + * must be equal to the range of selectable numbers which is equal to + * {@link #getMaxValue()} - {@link #getMinValue()} + 1. + */ + public void setDisplayedValues(String[] displayedValues) { + if (mDisplayedValues == displayedValues) { + return; + } + mDisplayedValues = displayedValues; + if (mDisplayedValues != null) { + // Allow text entry rather than strictly numeric entry. + mInputText.setRawInputType(InputType.TYPE_CLASS_TEXT + | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); + } else { + mInputText.setRawInputType(InputType.TYPE_CLASS_NUMBER); + } + updateInputTextView(); + initializeSelectorWheelIndices(); + tryComputeMaxWidth(); + } + + @Override + protected float getTopFadingEdgeStrength() { + return TOP_AND_BOTTOM_FADING_EDGE_STRENGTH; + } + + @Override + protected float getBottomFadingEdgeStrength() { + return TOP_AND_BOTTOM_FADING_EDGE_STRENGTH; + } + + @Override + protected void onDetachedFromWindow() { + removeAllCallbacks(); + super.onDetachedFromWindow(); + } + + @Override + protected void onDraw(Canvas canvas) { + if (!mHasSelectorWheel) { + super.onDraw(canvas); + return; + } + float x = (getRight() - getLeft()) / 2; + float y = mCurrentScrollOffset; + + // draw the virtual buttons pressed state if needed + if (mVirtualButtonPressedDrawable != null + && mScrollState == OnScrollListener.SCROLL_STATE_IDLE) { + if (mDecrementVirtualButtonPressed) { + //mVirtualButtonPressedDrawable.setState(PRESSED_STATE_SET); + mVirtualButtonPressedDrawable.setState(PRESSED_ENABLED_STATE_SET); + mVirtualButtonPressedDrawable.setBounds(0, 0, getRight(), mTopSelectionDividerTop); + mVirtualButtonPressedDrawable.draw(canvas); + } + if (mIncrementVirtualButtonPressed) { + //mVirtualButtonPressedDrawable.setState(PRESSED_STATE_SET); + mVirtualButtonPressedDrawable.setState(PRESSED_ENABLED_STATE_SET); + mVirtualButtonPressedDrawable.setBounds(0, mBottomSelectionDividerBottom, getRight(), + getBottom()); + mVirtualButtonPressedDrawable.draw(canvas); + } + } + + // draw the selector wheel + int[] selectorIndices = mSelectorIndices; + for (int i = 0; i < selectorIndices.length; i++) { + int selectorIndex = selectorIndices[i]; + String scrollSelectorValue = mSelectorIndexToStringCache.get(selectorIndex); + // Do not draw the middle item if input is visible since the input + // is shown only if the wheel is static and it covers the middle + // item. Otherwise, if the user starts editing the text via the + // IME he may see a dimmed version of the old value intermixed + // with the new one. + if (i != SELECTOR_MIDDLE_ITEM_INDEX || mInputText.getVisibility() != VISIBLE) { + canvas.drawText(scrollSelectorValue, x, y, mSelectorWheelPaint); + } + y += mSelectorElementHeight; + } + + // draw the selection dividers + if (mSelectionDivider != null) { + // draw the top divider + int topOfTopDivider = mTopSelectionDividerTop; + int bottomOfTopDivider = topOfTopDivider + mSelectionDividerHeight; + mSelectionDivider.setBounds(0, topOfTopDivider, getRight(), bottomOfTopDivider); + mSelectionDivider.draw(canvas); + + // draw the bottom divider + int bottomOfBottomDivider = mBottomSelectionDividerBottom; + int topOfBottomDivider = bottomOfBottomDivider - mSelectionDividerHeight; + mSelectionDivider.setBounds(0, topOfBottomDivider, getRight(), bottomOfBottomDivider); + mSelectionDivider.draw(canvas); + } + } + + @Override + public void onInitializeAccessibilityEvent(AccessibilityEvent event) { + super.onInitializeAccessibilityEvent(event); + event.setClassName(NumberPicker.class.getName()); + event.setScrollable(true); + event.setScrollY((mMinValue + mValue) * mSelectorElementHeight); + event.setMaxScrollY((mMaxValue - mMinValue) * mSelectorElementHeight); + } + + @Override + public AccessibilityNodeProvider getAccessibilityNodeProvider() { + if (!mHasSelectorWheel) { + return super.getAccessibilityNodeProvider(); + } + if (mAccessibilityNodeProvider == null) { + mAccessibilityNodeProvider = new SupportAccessibilityNodeProvider(); + } + return mAccessibilityNodeProvider.mProvider; + } + + /** + * Makes a measure spec that tries greedily to use the max value. + * + * @param measureSpec The measure spec. + * @param maxSize The max value for the size. + * @return A measure spec greedily imposing the max size. + */ + private int makeMeasureSpec(int measureSpec, int maxSize) { + if (maxSize == SIZE_UNSPECIFIED) { + return measureSpec; + } + final int size = MeasureSpec.getSize(measureSpec); + final int mode = MeasureSpec.getMode(measureSpec); + switch (mode) { + case MeasureSpec.EXACTLY: + return measureSpec; + case MeasureSpec.AT_MOST: + return MeasureSpec.makeMeasureSpec(Math.min(size, maxSize), MeasureSpec.EXACTLY); + case MeasureSpec.UNSPECIFIED: + return MeasureSpec.makeMeasureSpec(maxSize, MeasureSpec.EXACTLY); + default: + throw new IllegalArgumentException("Unknown measure mode: " + mode); + } + } + + /** + * Utility to reconcile a desired size and state, with constraints imposed + * by a MeasureSpec. Tries to respect the min size, unless a different size + * is imposed by the constraints. + * + * @param minSize The minimal desired size. + * @param measuredSize The currently measured size. + * @param measureSpec The current measure spec. + * @return The resolved size and state. + */ + private int resolveSizeAndStateRespectingMinSize( + int minSize, int measuredSize, int measureSpec) { + if (minSize != SIZE_UNSPECIFIED) { + final int desiredWidth = Math.max(minSize, measuredSize); + return resolveSizeAndState(desiredWidth, measureSpec, 0); + } else { + return measuredSize; + } + } + + /** + * Resets the selector indices and clear the cached string representation of + * these indices. + */ + private void initializeSelectorWheelIndices() { + mSelectorIndexToStringCache.clear(); + int[] selectorIndices = mSelectorIndices; + int current = getValue(); + for (int i = 0; i < mSelectorIndices.length; i++) { + int selectorIndex = current + (i - SELECTOR_MIDDLE_ITEM_INDEX); + if (mWrapSelectorWheel) { + selectorIndex = getWrappedSelectorIndex(selectorIndex); + } + selectorIndices[i] = selectorIndex; + ensureCachedScrollSelectorValue(selectorIndices[i]); + } + } + + /** + * Sets the current value of this NumberPicker. + * + * @param current The new value of the NumberPicker. + * @param notifyChange Whether to notify if the current value changed. + */ + private void setValueInternal(int current, boolean notifyChange) { + if (mValue == current) { + return; + } + // Wrap around the values if we go past the start or end + if (mWrapSelectorWheel) { + current = getWrappedSelectorIndex(current); + } else { + current = Math.max(current, mMinValue); + current = Math.min(current, mMaxValue); + } + int previous = mValue; + mValue = current; + updateInputTextView(); + if (notifyChange) { + notifyChange(previous, current); + } + initializeSelectorWheelIndices(); + invalidate(); + } + + /** + * Changes the current value by one which is increment or + * decrement based on the passes argument. + * decrement the current value. + * + * @param increment True to increment, false to decrement. + */ + private void changeValueByOne(boolean increment) { + if (mHasSelectorWheel) { + mInputText.setVisibility(View.INVISIBLE); + if (!moveToFinalScrollerPosition(mFlingScroller)) { + moveToFinalScrollerPosition(mAdjustScroller); + } + mPreviousScrollerY = 0; + if (increment) { + mFlingScroller.startScroll(0, 0, 0, -mSelectorElementHeight, SNAP_SCROLL_DURATION); + } else { + mFlingScroller.startScroll(0, 0, 0, mSelectorElementHeight, SNAP_SCROLL_DURATION); + } + invalidate(); + } else { + if (increment) { + setValueInternal(mValue + 1, true); + } else { + setValueInternal(mValue - 1, true); + } + } + } + + private void initializeSelectorWheel() { + initializeSelectorWheelIndices(); + int[] selectorIndices = mSelectorIndices; + int totalTextHeight = selectorIndices.length * mTextSize; + float totalTextGapHeight = (getBottom() - getTop()) - totalTextHeight; + float textGapCount = selectorIndices.length; + mSelectorTextGapHeight = (int) (totalTextGapHeight / textGapCount + 0.5f); + mSelectorElementHeight = mTextSize + mSelectorTextGapHeight; + // Ensure that the middle item is positioned the same as the text in + // mInputText + int editTextTextPosition = mInputText.getBaseline() + mInputText.getTop(); + mInitialScrollOffset = editTextTextPosition + - (mSelectorElementHeight * SELECTOR_MIDDLE_ITEM_INDEX); + mCurrentScrollOffset = mInitialScrollOffset; + updateInputTextView(); + } + + private void initializeFadingEdges() { + setVerticalFadingEdgeEnabled(true); + setFadingEdgeLength((getBottom() - getTop() - mTextSize) / 2); + } + + /** + * Callback invoked upon completion of a given scroller. + */ + private void onScrollerFinished(Scroller scroller) { + if (scroller == mFlingScroller) { + if (!ensureScrollWheelAdjusted()) { + updateInputTextView(); + } + onScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE); + } else { + if (mScrollState != OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) { + updateInputTextView(); + } + } + } + + /** + * Handles transition to a given scrollState + */ + private void onScrollStateChange(int scrollState) { + if (mScrollState == scrollState) { + return; + } + mScrollState = scrollState; + if (mOnScrollListener != null) { + mOnScrollListener.onScrollStateChange(this, scrollState); + } + } + + /** + * Flings the selector with the given velocityY. + */ + private void fling(int velocityY) { + mPreviousScrollerY = 0; + + if (velocityY > 0) { + mFlingScroller.fling(0, 0, 0, velocityY, 0, 0, 0, Integer.MAX_VALUE); + } else { + mFlingScroller.fling(0, Integer.MAX_VALUE, 0, velocityY, 0, 0, 0, Integer.MAX_VALUE); + } + + invalidate(); + } + + /** + * @return The wrapped index selectorIndex value. + */ + private int getWrappedSelectorIndex(int selectorIndex) { + if (selectorIndex > mMaxValue) { + return mMinValue + (selectorIndex - mMaxValue) % (mMaxValue - mMinValue) - 1; + } else if (selectorIndex < mMinValue) { + return mMaxValue - (mMinValue - selectorIndex) % (mMaxValue - mMinValue) + 1; + } + return selectorIndex; + } + + /** + * Increments the selectorIndices whose string representations + * will be displayed in the selector. + */ + private void incrementSelectorIndices(int[] selectorIndices) { + for (int i = 0; i < selectorIndices.length - 1; i++) { + selectorIndices[i] = selectorIndices[i + 1]; + } + int nextScrollSelectorIndex = selectorIndices[selectorIndices.length - 2] + 1; + if (mWrapSelectorWheel && nextScrollSelectorIndex > mMaxValue) { + nextScrollSelectorIndex = mMinValue; + } + selectorIndices[selectorIndices.length - 1] = nextScrollSelectorIndex; + ensureCachedScrollSelectorValue(nextScrollSelectorIndex); + } + + /** + * Decrements the selectorIndices whose string representations + * will be displayed in the selector. + */ + private void decrementSelectorIndices(int[] selectorIndices) { + for (int i = selectorIndices.length - 1; i > 0; i--) { + selectorIndices[i] = selectorIndices[i - 1]; + } + int nextScrollSelectorIndex = selectorIndices[1] - 1; + if (mWrapSelectorWheel && nextScrollSelectorIndex < mMinValue) { + nextScrollSelectorIndex = mMaxValue; + } + selectorIndices[0] = nextScrollSelectorIndex; + ensureCachedScrollSelectorValue(nextScrollSelectorIndex); + } + + /** + * Ensures we have a cached string representation of the given + * selectorIndex to avoid multiple instantiations of the same string. + */ + private void ensureCachedScrollSelectorValue(int selectorIndex) { + SparseArray cache = mSelectorIndexToStringCache; + String scrollSelectorValue = cache.get(selectorIndex); + if (scrollSelectorValue != null) { + return; + } + if (selectorIndex < mMinValue || selectorIndex > mMaxValue) { + scrollSelectorValue = ""; + } else { + if (mDisplayedValues != null) { + int displayedValueIndex = selectorIndex - mMinValue; + scrollSelectorValue = mDisplayedValues[displayedValueIndex]; + } else { + scrollSelectorValue = formatNumber(selectorIndex); + } + } + cache.put(selectorIndex, scrollSelectorValue); + } + + private String formatNumber(int value) { + return (mFormatter != null) ? mFormatter.format(value) : formatNumberWithLocale(value); + } + + private void validateInputTextView(View v) { + String str = String.valueOf(((TextView) v).getText()); + if (TextUtils.isEmpty(str)) { + // Restore to the old value as we don't allow empty values + updateInputTextView(); + } else { + // Check the new value and ensure it's in range + int current = getSelectedPos(str); + setValueInternal(current, true); + } + } + + /** + * Updates the view of this NumberPicker. If displayValues were specified in + * the string corresponding to the index specified by the current value will + * be returned. Otherwise, the formatter specified in {@link #setFormatter} + * will be used to format the number. + * + * @return Whether the text was updated. + */ + private boolean updateInputTextView() { + /* + * If we don't have displayed values then use the current number else + * find the correct value in the displayed values for the current + * number. + */ + String text = (mDisplayedValues == null) ? formatNumber(mValue) + : mDisplayedValues[mValue - mMinValue]; + if (!TextUtils.isEmpty(text) && !text.equals(mInputText.getText().toString())) { + mInputText.setText(text); + return true; + } + + return false; + } + + /** + * Notifies the listener, if registered, of a change of the value of this + * NumberPicker. + */ + private void notifyChange(int previous, int current) { + if (mOnValueChangeListener != null) { + mOnValueChangeListener.onValueChange(this, previous, mValue); + } + } + + /** + * Posts a command for changing the current value by one. + * + * @param increment Whether to increment or decrement the value. + */ + private void postChangeCurrentByOneFromLongPress(boolean increment, long delayMillis) { + if (mChangeCurrentByOneFromLongPressCommand == null) { + mChangeCurrentByOneFromLongPressCommand = new ChangeCurrentByOneFromLongPressCommand(); + } else { + removeCallbacks(mChangeCurrentByOneFromLongPressCommand); + } + mChangeCurrentByOneFromLongPressCommand.setStep(increment); + postDelayed(mChangeCurrentByOneFromLongPressCommand, delayMillis); + } + + /** + * Removes the command for changing the current value by one. + */ + private void removeChangeCurrentByOneFromLongPress() { + if (mChangeCurrentByOneFromLongPressCommand != null) { + removeCallbacks(mChangeCurrentByOneFromLongPressCommand); + } + } + + /** + * Posts a command for beginning an edit of the current value via IME on + * long press. + */ + private void postBeginSoftInputOnLongPressCommand() { + if (mBeginSoftInputOnLongPressCommand == null) { + mBeginSoftInputOnLongPressCommand = new BeginSoftInputOnLongPressCommand(); + } else { + removeCallbacks(mBeginSoftInputOnLongPressCommand); + } + postDelayed(mBeginSoftInputOnLongPressCommand, ViewConfiguration.getLongPressTimeout()); + } + + /** + * Removes the command for beginning an edit of the current value via IME. + */ + private void removeBeginSoftInputCommand() { + if (mBeginSoftInputOnLongPressCommand != null) { + removeCallbacks(mBeginSoftInputOnLongPressCommand); + } + } + + /** + * Removes all pending callback from the message queue. + */ + private void removeAllCallbacks() { + if (mChangeCurrentByOneFromLongPressCommand != null) { + removeCallbacks(mChangeCurrentByOneFromLongPressCommand); + } + if (mSetSelectionCommand != null) { + removeCallbacks(mSetSelectionCommand); + } + if (mBeginSoftInputOnLongPressCommand != null) { + removeCallbacks(mBeginSoftInputOnLongPressCommand); + } + mPressedStateHelper.cancel(); + } + + /** + * @return The selected index given its displayed value. + */ + private int getSelectedPos(String value) { + if (mDisplayedValues == null) { + try { + return Integer.parseInt(value); + } catch (NumberFormatException e) { + // Ignore as if it's not a number we don't care + } + } else { + for (int i = 0; i < mDisplayedValues.length; i++) { + // Don't force the user to type in jan when ja will do + value = value.toLowerCase(); + if (mDisplayedValues[i].toLowerCase().startsWith(value)) { + return mMinValue + i; + } + } + + /* + * The user might have typed in a number into the month field i.e. + * 10 instead of OCT so support that too. + */ + try { + return Integer.parseInt(value); + } catch (NumberFormatException e) { + + // Ignore as if it's not a number we don't care + } + } + return mMinValue; + } + + /** + * Posts an {@link SetSelectionCommand} from the given selectionStart + * to selectionEnd. + */ + private void postSetSelectionCommand(int selectionStart, int selectionEnd) { + if (mSetSelectionCommand == null) { + mSetSelectionCommand = new SetSelectionCommand(); + } else { + removeCallbacks(mSetSelectionCommand); + } + mSetSelectionCommand.mSelectionStart = selectionStart; + mSetSelectionCommand.mSelectionEnd = selectionEnd; + post(mSetSelectionCommand); + } + + /** + * Ensures that the scroll wheel is adjusted i.e. there is no offset and the + * middle element is in the middle of the widget. + * + * @return Whether an adjustment has been made. + */ + private boolean ensureScrollWheelAdjusted() { + // adjust to the closest value + int deltaY = mInitialScrollOffset - mCurrentScrollOffset; + if (deltaY != 0) { + mPreviousScrollerY = 0; + if (Math.abs(deltaY) > mSelectorElementHeight / 2) { + deltaY += (deltaY > 0) ? -mSelectorElementHeight : mSelectorElementHeight; + } + mAdjustScroller.startScroll(0, 0, 0, deltaY, SELECTOR_ADJUSTMENT_DURATION_MILLIS); + invalidate(); + return true; + } + return false; + } + + private SupportAccessibilityNodeProvider getSupportAccessibilityNodeProvider() { + return new SupportAccessibilityNodeProvider(); + } + + /** + * Interface to listen for changes of the current value. + */ + public interface OnValueChangeListener { + + /** + * Called upon a change of the current value. + * + * @param picker The NumberPicker associated with this listener. + * @param oldVal The previous value. + * @param newVal The new value. + */ + void onValueChange(NumberPicker picker, int oldVal, int newVal); + } + + /** + * Interface to listen for the picker scroll state. + */ + public interface OnScrollListener { + + /** + * The view is not scrolling. + */ + public static int SCROLL_STATE_IDLE = 0; + + /** + * The user is scrolling using touch, and his finger is still on the screen. + */ + public static int SCROLL_STATE_TOUCH_SCROLL = 1; + + /** + * The user had previously been scrolling using touch and performed a fling. + */ + public static int SCROLL_STATE_FLING = 2; + + /** + * Callback invoked while the number picker scroll state has changed. + * + * @param view The view whose scroll state is being reported. + * @param scrollState The current scroll state. One of + * {@link #SCROLL_STATE_IDLE}, + * {@link #SCROLL_STATE_TOUCH_SCROLL} or + * {@link #SCROLL_STATE_IDLE}. + */ + public void onScrollStateChange(NumberPicker view, int scrollState); + } + + /** + * Interface used to format current value into a string for presentation. + */ + public interface Formatter { + + /** + * Formats a string representation of the current value. + * + * @param value The currently selected value. + * @return A formatted string representation. + */ + public String format(int value); + } + + /** + * Use a custom NumberPicker formatting callback to use two-digit minutes + * strings like "01". Keeping a static formatter etc. is the most efficient + * way to do this; it avoids creating temporary objects on every call to + * format(). + */ + private static class TwoDigitFormatter implements NumberPicker.Formatter { + final StringBuilder mBuilder = new StringBuilder(); + final Object[] mArgs = new Object[1]; + char mZeroDigit; + java.util.Formatter mFmt; + + TwoDigitFormatter() { + final Locale locale = Locale.getDefault(); + init(locale); + } + + private static char getZeroDigit(Locale locale) { + // return LocaleData.get(locale).zeroDigit; + return new DecimalFormatSymbols(locale).getZeroDigit(); + } + + private void init(Locale locale) { + mFmt = createFormatter(locale); + mZeroDigit = getZeroDigit(locale); + } + + public String format(int value) { + final Locale currentLocale = Locale.getDefault(); + if (mZeroDigit != getZeroDigit(currentLocale)) { + init(currentLocale); + } + mArgs[0] = value; + mBuilder.delete(0, mBuilder.length()); + mFmt.format("%02d", mArgs); + return mFmt.toString(); + } + + private java.util.Formatter createFormatter(Locale locale) { + return new java.util.Formatter(mBuilder, locale); + } + } + + /** + * @hide + */ + public static class CustomEditText extends EditText { + + public CustomEditText(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + public void onEditorAction(int actionCode) { + super.onEditorAction(actionCode); + if (actionCode == EditorInfo.IME_ACTION_DONE) { + clearFocus(); + } + } + } + + /** + * Filter for accepting only valid indices or prefixes of the string + * representation of valid indices. + */ + class InputTextFilter extends NumberKeyListener { + + // XXX This doesn't allow for range limits when controlled by a + // soft input method! + public int getInputType() { + return InputType.TYPE_CLASS_TEXT; + } + + @Override + protected char[] getAcceptedChars() { + return DIGIT_CHARACTERS; + } + + @Override + public CharSequence filter( + CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { + if (mDisplayedValues == null) { + CharSequence filtered = super.filter(source, start, end, dest, dstart, dend); + if (filtered == null) { + filtered = source.subSequence(start, end); + } + + String result = String.valueOf(dest.subSequence(0, dstart)) + filtered + + dest.subSequence(dend, dest.length()); + + if ("".equals(result)) { + return result; + } + int val = getSelectedPos(result); + + /* + * Ensure the user can't type in a value greater than the max + * allowed. We have to allow less than min as the user might + * want to delete some numbers and then type a new number. + */ + if (val > mMaxValue) { + return ""; + } else { + return filtered; + } + } else { + CharSequence filtered = String.valueOf(source.subSequence(start, end)); + if (TextUtils.isEmpty(filtered)) { + return ""; + } + String result = String.valueOf(dest.subSequence(0, dstart)) + filtered + + dest.subSequence(dend, dest.length()); + String str = String.valueOf(result).toLowerCase(); + for (String val : mDisplayedValues) { + String valLowerCase = val.toLowerCase(); + if (valLowerCase.startsWith(str)) { + postSetSelectionCommand(result.length(), val.length()); + return val.subSequence(dstart, val.length()); + } + } + return ""; + } + } + } + + class PressedStateHelper implements Runnable { + public static final int BUTTON_INCREMENT = 1; + public static final int BUTTON_DECREMENT = 2; + + private final int MODE_PRESS = 1; + private final int MODE_TAPPED = 2; + + private int mManagedButton; + private int mMode; + + public void cancel() { + mMode = 0; + mManagedButton = 0; + NumberPicker.this.removeCallbacks(this); + if (mIncrementVirtualButtonPressed) { + mIncrementVirtualButtonPressed = false; + invalidate(0, mBottomSelectionDividerBottom, getRight(), getBottom()); + } + mDecrementVirtualButtonPressed = false; + if (mDecrementVirtualButtonPressed) { + invalidate(0, 0, getRight(), mTopSelectionDividerTop); + } + } + + public void buttonPressDelayed(int button) { + cancel(); + mMode = MODE_PRESS; + mManagedButton = button; + NumberPicker.this.postDelayed(this, ViewConfiguration.getTapTimeout()); + } + + public void buttonTapped(int button) { + cancel(); + mMode = MODE_TAPPED; + mManagedButton = button; + NumberPicker.this.post(this); + } + + @Override + public void run() { + switch (mMode) { + case MODE_PRESS: { + switch (mManagedButton) { + case BUTTON_INCREMENT: { + mIncrementVirtualButtonPressed = true; + invalidate(0, mBottomSelectionDividerBottom, getRight(), getBottom()); + } + break; + case BUTTON_DECREMENT: { + mDecrementVirtualButtonPressed = true; + invalidate(0, 0, getRight(), mTopSelectionDividerTop); + } + } + } + break; + case MODE_TAPPED: { + switch (mManagedButton) { + case BUTTON_INCREMENT: { + if (!mIncrementVirtualButtonPressed) { + NumberPicker.this.postDelayed(this, + ViewConfiguration.getPressedStateDuration()); + } + mIncrementVirtualButtonPressed ^= true; + invalidate(0, mBottomSelectionDividerBottom, getRight(), getBottom()); + } + break; + case BUTTON_DECREMENT: { + if (!mDecrementVirtualButtonPressed) { + NumberPicker.this.postDelayed(this, + ViewConfiguration.getPressedStateDuration()); + } + mDecrementVirtualButtonPressed ^= true; + invalidate(0, 0, getRight(), mTopSelectionDividerTop); + } + } + } + break; + } + } + } + + /** + * Command for setting the input text selection. + */ + class SetSelectionCommand implements Runnable { + private int mSelectionStart; + + private int mSelectionEnd; + + public void run() { + mInputText.setSelection(mSelectionStart, mSelectionEnd); + } + } + + /** + * Command for changing the current value from a long press by one. + */ + class ChangeCurrentByOneFromLongPressCommand implements Runnable { + private boolean mIncrement; + + private void setStep(boolean increment) { + mIncrement = increment; + } + + @Override + public void run() { + changeValueByOne(mIncrement); + postDelayed(this, mLongPressUpdateInterval); + } + } + + /** + * Command for beginning soft input on long press. + */ + class BeginSoftInputOnLongPressCommand implements Runnable { + + @Override + public void run() { + showSoftInput(); + mIngonreMoveEvents = true; + } + } + + class SupportAccessibilityNodeProvider { + + AccessibilityNodeProviderImpl mProvider; + + private SupportAccessibilityNodeProvider() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + mProvider = new AccessibilityNodeProviderImpl(); + } + } + + public boolean performAction(int virtualViewId, int action, Bundle arguments) { + return mProvider != null && mProvider.performAction(virtualViewId, action, arguments); + } + + public void sendAccessibilityEventForVirtualView(int virtualViewId, int eventType) { + if (mProvider != null) + mProvider.sendAccessibilityEventForVirtualView(virtualViewId, eventType); + } + } + + /** + * Class for managing virtual view tree rooted at this picker. + */ + @TargetApi(Build.VERSION_CODES.JELLY_BEAN) + class AccessibilityNodeProviderImpl extends AccessibilityNodeProvider { + private static final int UNDEFINED = Integer.MIN_VALUE; + + private static final int VIRTUAL_VIEW_ID_INCREMENT = 1; + + private static final int VIRTUAL_VIEW_ID_INPUT = 2; + + private static final int VIRTUAL_VIEW_ID_DECREMENT = 3; + + private final Rect mTempRect = new Rect(); + + private final int[] mTempArray = new int[2]; + + private int mAccessibilityFocusedView = UNDEFINED; + + @Override + public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) { + switch (virtualViewId) { + case View.NO_ID: + return createAccessibilityNodeInfoForNumberPicker(getScrollX(), getScrollY(), + getScrollX() + (getRight() - getLeft()), getScrollY() + (getBottom() - getTop())); + case VIRTUAL_VIEW_ID_DECREMENT: + return createAccessibilityNodeInfoForVirtualButton(VIRTUAL_VIEW_ID_DECREMENT, + getVirtualDecrementButtonText(), getScrollX(), getScrollY(), + getScrollX() + (getRight() - getLeft()), + mTopSelectionDividerTop + mSelectionDividerHeight); + case VIRTUAL_VIEW_ID_INPUT: + return createAccessibiltyNodeInfoForInputText(); + case VIRTUAL_VIEW_ID_INCREMENT: + return createAccessibilityNodeInfoForVirtualButton(VIRTUAL_VIEW_ID_INCREMENT, + getVirtualIncrementButtonText(), getScrollX(), + mBottomSelectionDividerBottom - mSelectionDividerHeight, + getScrollX() + (getRight() - getLeft()), getScrollY() + (getBottom() - getTop())); + } + return super.createAccessibilityNodeInfo(virtualViewId); + } + + @Override + public List findAccessibilityNodeInfosByText(String searched, + int virtualViewId) { + if (TextUtils.isEmpty(searched)) { + return Collections.emptyList(); + } + String searchedLowerCase = searched.toLowerCase(); + List result = new ArrayList(); + switch (virtualViewId) { + case View.NO_ID: { + findAccessibilityNodeInfosByTextInChild(searchedLowerCase, + VIRTUAL_VIEW_ID_DECREMENT, result); + findAccessibilityNodeInfosByTextInChild(searchedLowerCase, + VIRTUAL_VIEW_ID_INPUT, result); + findAccessibilityNodeInfosByTextInChild(searchedLowerCase, + VIRTUAL_VIEW_ID_INCREMENT, result); + return result; + } + case VIRTUAL_VIEW_ID_DECREMENT: + case VIRTUAL_VIEW_ID_INCREMENT: + case VIRTUAL_VIEW_ID_INPUT: { + findAccessibilityNodeInfosByTextInChild(searchedLowerCase, virtualViewId, + result); + return result; + } + } + return super.findAccessibilityNodeInfosByText(searched, virtualViewId); + } + + @Override + public boolean performAction(int virtualViewId, int action, Bundle arguments) { + switch (virtualViewId) { + case View.NO_ID: { + switch (action) { + case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: { + if (mAccessibilityFocusedView != virtualViewId) { + mAccessibilityFocusedView = virtualViewId; + // requestAccessibilityFocus(); + performAccessibilityAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null); + return true; + } + } + return false; + case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: { + if (mAccessibilityFocusedView == virtualViewId) { + mAccessibilityFocusedView = UNDEFINED; + // clearAccessibilityFocus(); + performAccessibilityAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null); + return true; + } + return false; + } + case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: { + if (NumberPicker.this.isEnabled() + && (getWrapSelectorWheel() || getValue() < getMaxValue())) { + changeValueByOne(true); + return true; + } + } + return false; + case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: { + if (NumberPicker.this.isEnabled() + && (getWrapSelectorWheel() || getValue() > getMinValue())) { + changeValueByOne(false); + return true; + } + } + return false; + } + } + break; + case VIRTUAL_VIEW_ID_INPUT: { + switch (action) { + case AccessibilityNodeInfo.ACTION_FOCUS: { + if (NumberPicker.this.isEnabled() && !mInputText.isFocused()) { + return mInputText.requestFocus(); + } + } + break; + case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: { + if (NumberPicker.this.isEnabled() && mInputText.isFocused()) { + mInputText.clearFocus(); + return true; + } + return false; + } + case AccessibilityNodeInfo.ACTION_CLICK: { + if (NumberPicker.this.isEnabled()) { + showSoftInput(); + return true; + } + return false; + } + case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: { + if (mAccessibilityFocusedView != virtualViewId) { + mAccessibilityFocusedView = virtualViewId; + sendAccessibilityEventForVirtualView(virtualViewId, + AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED); + mInputText.invalidate(); + return true; + } + } + return false; + case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: { + if (mAccessibilityFocusedView == virtualViewId) { + mAccessibilityFocusedView = UNDEFINED; + sendAccessibilityEventForVirtualView(virtualViewId, + AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED); + mInputText.invalidate(); + return true; + } + } + return false; + default: { + return mInputText.performAccessibilityAction(action, arguments); + } + } + } + return false; + case VIRTUAL_VIEW_ID_INCREMENT: { + switch (action) { + case AccessibilityNodeInfo.ACTION_CLICK: { + if (NumberPicker.this.isEnabled()) { + NumberPicker.this.changeValueByOne(true); + sendAccessibilityEventForVirtualView(virtualViewId, + AccessibilityEvent.TYPE_VIEW_CLICKED); + return true; + } + } + return false; + case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: { + if (mAccessibilityFocusedView != virtualViewId) { + mAccessibilityFocusedView = virtualViewId; + sendAccessibilityEventForVirtualView(virtualViewId, + AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED); + invalidate(0, mBottomSelectionDividerBottom, getRight(), getBottom()); + return true; + } + } + return false; + case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: { + if (mAccessibilityFocusedView == virtualViewId) { + mAccessibilityFocusedView = UNDEFINED; + sendAccessibilityEventForVirtualView(virtualViewId, + AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED); + invalidate(0, mBottomSelectionDividerBottom, getRight(), getBottom()); + return true; + } + } + return false; + } + } + return false; + case VIRTUAL_VIEW_ID_DECREMENT: { + switch (action) { + case AccessibilityNodeInfo.ACTION_CLICK: { + if (NumberPicker.this.isEnabled()) { + final boolean increment = (virtualViewId == VIRTUAL_VIEW_ID_INCREMENT); + NumberPicker.this.changeValueByOne(increment); + sendAccessibilityEventForVirtualView(virtualViewId, + AccessibilityEvent.TYPE_VIEW_CLICKED); + return true; + } + } + return false; + case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: { + if (mAccessibilityFocusedView != virtualViewId) { + mAccessibilityFocusedView = virtualViewId; + sendAccessibilityEventForVirtualView(virtualViewId, + AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED); + invalidate(0, 0, getRight(), mTopSelectionDividerTop); + return true; + } + } + return false; + case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: { + if (mAccessibilityFocusedView == virtualViewId) { + mAccessibilityFocusedView = UNDEFINED; + sendAccessibilityEventForVirtualView(virtualViewId, + AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED); + invalidate(0, 0, getRight(), mTopSelectionDividerTop); + return true; + } + } + return false; + } + } + return false; + } + return super.performAction(virtualViewId, action, arguments); + } + + public void sendAccessibilityEventForVirtualView(int virtualViewId, int eventType) { + switch (virtualViewId) { + case VIRTUAL_VIEW_ID_DECREMENT: { + if (hasVirtualDecrementButton()) { + sendAccessibilityEventForVirtualButton(virtualViewId, eventType, + getVirtualDecrementButtonText()); + } + } + break; + case VIRTUAL_VIEW_ID_INPUT: { + sendAccessibilityEventForVirtualText(eventType); + } + break; + case VIRTUAL_VIEW_ID_INCREMENT: { + if (hasVirtualIncrementButton()) { + sendAccessibilityEventForVirtualButton(virtualViewId, eventType, + getVirtualIncrementButtonText()); + } + } + break; + } + } + + private void sendAccessibilityEventForVirtualText(int eventType) { + if (((AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE)).isEnabled()) { + AccessibilityEvent event = AccessibilityEvent.obtain(eventType); + mInputText.onInitializeAccessibilityEvent(event); + mInputText.onPopulateAccessibilityEvent(event); + event.setSource(NumberPicker.this, VIRTUAL_VIEW_ID_INPUT); + requestSendAccessibilityEvent(NumberPicker.this, event); + } + } + + private void sendAccessibilityEventForVirtualButton(int virtualViewId, int eventType, + String text) { + if (((AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE)).isEnabled()) { + AccessibilityEvent event = AccessibilityEvent.obtain(eventType); + event.setClassName(Button.class.getName()); + event.setPackageName(getContext().getPackageName()); + event.getText().add(text); + event.setEnabled(NumberPicker.this.isEnabled()); + event.setSource(NumberPicker.this, virtualViewId); + requestSendAccessibilityEvent(NumberPicker.this, event); + } + } + + private void findAccessibilityNodeInfosByTextInChild(String searchedLowerCase, + int virtualViewId, List outResult) { + switch (virtualViewId) { + case VIRTUAL_VIEW_ID_DECREMENT: { + String text = getVirtualDecrementButtonText(); + if (!TextUtils.isEmpty(text) + && text.toLowerCase().contains(searchedLowerCase)) { + outResult.add(createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_DECREMENT)); + } + } + return; + case VIRTUAL_VIEW_ID_INPUT: { + CharSequence text = mInputText.getText(); + if (!TextUtils.isEmpty(text) && + text.toString().toLowerCase().contains(searchedLowerCase)) { + outResult.add(createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_INPUT)); + return; + } + CharSequence contentDesc = mInputText.getText(); + if (!TextUtils.isEmpty(contentDesc) && + contentDesc.toString().toLowerCase().contains(searchedLowerCase)) { + outResult.add(createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_INPUT)); + return; + } + } + break; + case VIRTUAL_VIEW_ID_INCREMENT: { + String text = getVirtualIncrementButtonText(); + if (!TextUtils.isEmpty(text) + && text.toLowerCase().contains(searchedLowerCase)) { + outResult.add(createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_INCREMENT)); + } + } + return; + } + } + + private AccessibilityNodeInfo createAccessibiltyNodeInfoForInputText() { + AccessibilityNodeInfo info = mInputText.createAccessibilityNodeInfo(); + info.setSource(NumberPicker.this, VIRTUAL_VIEW_ID_INPUT); + if (mAccessibilityFocusedView != VIRTUAL_VIEW_ID_INPUT) { + info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS); + } + if (mAccessibilityFocusedView == VIRTUAL_VIEW_ID_INPUT) { + info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS); + } + return info; + } + + private AccessibilityNodeInfo createAccessibilityNodeInfoForVirtualButton(int virtualViewId, + String text, int left, int top, int right, int bottom) { + AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(); + info.setClassName(Button.class.getName()); + info.setPackageName(getContext().getPackageName()); + info.setSource(NumberPicker.this, virtualViewId); + info.setParent(NumberPicker.this); + info.setText(text); + info.setClickable(true); + info.setLongClickable(true); + info.setEnabled(NumberPicker.this.isEnabled()); + Rect boundsInParent = mTempRect; + boundsInParent.set(left, top, right, bottom); + // TODO info.setVisibleToUser(isVisibleToUser(boundsInParent)); + info.setBoundsInParent(boundsInParent); + Rect boundsInScreen = boundsInParent; + int[] locationOnScreen = mTempArray; + getLocationOnScreen(locationOnScreen); + boundsInScreen.offset(locationOnScreen[0], locationOnScreen[1]); + info.setBoundsInScreen(boundsInScreen); + + if (mAccessibilityFocusedView != virtualViewId) { + info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS); + } + if (mAccessibilityFocusedView == virtualViewId) { + info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS); + } + if (NumberPicker.this.isEnabled()) { + info.addAction(AccessibilityNodeInfo.ACTION_CLICK); + } + + return info; + } + + private AccessibilityNodeInfo createAccessibilityNodeInfoForNumberPicker(int left, int top, + int right, int bottom) { + AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(); + info.setClassName(NumberPicker.class.getName()); + info.setPackageName(getContext().getPackageName()); + info.setSource(NumberPicker.this); + + if (hasVirtualDecrementButton()) { + info.addChild(NumberPicker.this, VIRTUAL_VIEW_ID_DECREMENT); + } + info.addChild(NumberPicker.this, VIRTUAL_VIEW_ID_INPUT); + if (hasVirtualIncrementButton()) { + info.addChild(NumberPicker.this, VIRTUAL_VIEW_ID_INCREMENT); + } + + info.setParent((View) getParentForAccessibility()); + info.setEnabled(NumberPicker.this.isEnabled()); + info.setScrollable(true); + + /** TODO: Figure out compat implementation for this + final float applicationScale = + getContext().getResources().getCompatibilityInfo().applicationScale; + + Rect boundsInParent = mTempRect; + boundsInParent.set(left, top, right, bottom); + boundsInParent.scale(applicationScale); + info.setBoundsInParent(boundsInParent); + + info.setVisibleToUser(isVisibleToUser()); + + Rect boundsInScreen = boundsInParent; + int[] locationOnScreen = mTempArray; + getLocationOnScreen(locationOnScreen); + boundsInScreen.offset(locationOnScreen[0], locationOnScreen[1]); + boundsInScreen.scale(applicationScale); + info.setBoundsInScreen(boundsInScreen); + */ + + if (mAccessibilityFocusedView != View.NO_ID) { + info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS); + } + if (mAccessibilityFocusedView == View.NO_ID) { + info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS); + } + if (NumberPicker.this.isEnabled()) { + if (getWrapSelectorWheel() || getValue() < getMaxValue()) { + info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD); + } + if (getWrapSelectorWheel() || getValue() > getMinValue()) { + info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD); + } + } + + return info; + } + + private boolean hasVirtualDecrementButton() { + return getWrapSelectorWheel() || getValue() > getMinValue(); + } + + private boolean hasVirtualIncrementButton() { + return getWrapSelectorWheel() || getValue() < getMaxValue(); + } + + private String getVirtualDecrementButtonText() { + int value = mValue - 1; + if (mWrapSelectorWheel) { + value = getWrappedSelectorIndex(value); + } + if (value >= mMinValue) { + return (mDisplayedValues == null) ? formatNumber(value) + : mDisplayedValues[value - mMinValue]; + } + return null; + } + + private String getVirtualIncrementButtonText() { + int value = mValue + 1; + if (mWrapSelectorWheel) { + value = getWrappedSelectorIndex(value); + } + if (value <= mMaxValue) { + return (mDisplayedValues == null) ? formatNumber(value) + : mDisplayedValues[value - mMinValue]; + } + return null; + } + } +} \ No newline at end of file diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/Preset.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/Preset.java new file mode 100644 index 0000000..1263f21 --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/Preset.java @@ -0,0 +1,42 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +import org.json.JSONException; +import org.json.JSONObject; + +public class Preset { + public String modeandduration = ""; + public String delay = ""; + public String startsound = ""; + public String startsoundcustom = ""; + public String intervalduration = ""; + public String intervalsound = ""; + public String intervalsoundcustom = ""; + public String intervalcount = ""; + public String completesound = ""; + public String completesoundcustom = ""; + public String ringtone = ""; + public Boolean endless = false; + public Boolean vibrate = false; + + public JSONObject export() { + JSONObject jobj = new JSONObject(); + try { + jobj.put("modeandduration", modeandduration); + jobj.put("delay", delay); + jobj.put("startsound", startsound); + jobj.put("startsoundcustom", startsoundcustom); + jobj.put("intervalduration", intervalduration); + jobj.put("intervalsound", intervalsound); + jobj.put("intervalsoundcustom", intervalsoundcustom); + jobj.put("intervalcount", intervalcount); + jobj.put("completesound", completesound); + jobj.put("completesoundcustom", completesoundcustom); + jobj.put("ringtone", ringtone); + jobj.put("endless", endless); + jobj.put("vibrate", vibrate); + } catch (JSONException e1) { + e1.printStackTrace(); + } + return jobj; + } +} \ No newline at end of file diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/ProgressActivity.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/ProgressActivity.java new file mode 100644 index 0000000..81c63c1 --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/ProgressActivity.java @@ -0,0 +1,811 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +import android.app.AlertDialog; +import android.app.DatePickerDialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; +import android.support.v4.app.NavUtils; +import android.support.v4.view.PagerTabStrip; +import android.support.v4.view.ViewPager; +import android.util.Log; +import android.util.SparseArray; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.DatePicker; +import android.widget.EditText; +import android.widget.TabHost; +import android.widget.TextView; + +import com.google.android.gms.ads.AdRequest; +import com.google.android.gms.ads.AdView; +import com.google.android.gms.analytics.GoogleAnalytics; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.Iterator; +import java.util.Locale; +import java.util.TimeZone; + +public class ProgressActivity extends FragmentActivity { + public SparseArray sessions_map = new SparseArray(); + TabHost mTabHost; + ViewPager mViewPager; + ProgressPagerAdapter mPagerAdapter = null; + int pagePosition = 0; + private AlertDialog addSessionDialog = null; + private AdView av = null; + private int SESSIONS_FRAGMENT = 0; + private int CALENDAR_FRAGMENT = 1; + private int STATS_FRAGMENT = 2; + private SessionsFragment sessionsFragment = null; + private MeditationAssistant ma = null; + private MenuItem menuCalendarBack = null; + private MenuItem menuCalendarForward = null; + private String beingSet = "started"; + private Button btnSetDateStarted = null; + private Button btnSetTimeStarted = null; + private Button btnSetDateCompleted = null; + private Button btnSetTimeCompleted = null; + private EditText editAddSessionMessage = null; + private int startedYear = -1; + private int startedMonth = -1; + private int startedDay = -1; + private int startedHour = -1; + private int startedMinute = -1; + private int completedYear = -1; + private int completedMonth = -1; + private int completedDay = -1; + private int completedHour = -1; + private int completedMinute = -1; + private DatePickerDialog.OnDateSetListener mDateSetListener = + new DatePickerDialog.OnDateSetListener() { + @Override + public void onDateSet(DatePicker view, int year, + int monthOfYear, int dayOfMonth) { + if (beingSet.equals("started")) { + startedYear = year; + startedMonth = monthOfYear; + startedDay = dayOfMonth; + + if (completedYear == -1 || completedMonth == -1 || completedDay == -1) { + completedYear = startedYear; + completedMonth = startedMonth; + completedDay = startedDay; + } else if (completedYear != -1 && completedMonth != -1 && completedDay != -1) { + Calendar c_started = Calendar.getInstance(); + c_started.set(Calendar.YEAR, startedYear); + c_started.set(Calendar.MONTH, startedMonth); + c_started.set(Calendar.DAY_OF_MONTH, startedDay); + c_started.set(Calendar.HOUR_OF_DAY, 0); + c_started.set(Calendar.MINUTE, 0); + c_started.set(Calendar.SECOND, 0); + c_started.set(Calendar.MILLISECOND, 0); + + Calendar c_completed = Calendar.getInstance(); + c_completed.set(Calendar.YEAR, completedYear); + c_completed.set(Calendar.MONTH, completedMonth); + c_completed.set(Calendar.DAY_OF_MONTH, completedDay); + c_completed.set(Calendar.HOUR_OF_DAY, 0); + c_completed.set(Calendar.MINUTE, 0); + c_completed.set(Calendar.SECOND, 0); + c_completed.set(Calendar.MILLISECOND, 0); + + if (c_started.getTimeInMillis() > c_completed.getTimeInMillis()) { + completedYear = startedYear; + completedMonth = startedMonth; + completedDay = startedDay; + } + } + } else { + completedYear = year; + completedMonth = monthOfYear; + completedDay = dayOfMonth; + } + + updateDateAndTimeButtons(); + } + }; + private TimePickerDialog.OnTimeSetListener mTimeSetListener = + new TimePickerDialog.OnTimeSetListener() { + @Override + public void onTimeSet(TimePicker view, int hourOfDay, int minute) { + if (beingSet.equals("started")) { + startedHour = hourOfDay; + startedMinute = minute; + + if (completedHour == -1 && completedMinute == -1) { + completedHour = startedHour; + completedMinute = startedMinute; + } + } else { + completedHour = hourOfDay; + completedMinute = minute; + } + + updateDateAndTimeButtons(); + } + }; + private AlertDialog sessionDetailsDialog = null; + + public MeditationAssistant getMeditationAssistant() { + if (ma == null) { + ma = (MeditationAssistant) this.getApplication(); + } + return ma; + } + + public void updateDateAndTimeButtons() { + SimpleDateFormat sdf_date = new SimpleDateFormat("MMMM d", + Locale.getDefault()); + SimpleDateFormat sdf_time = new SimpleDateFormat("h:mm a", + Locale.getDefault()); + + sdf_date.setTimeZone(TimeZone.getDefault()); + sdf_time.setTimeZone(TimeZone.getDefault()); + + if (startedYear == -1 || startedMonth == -1 || startedDay == -1) { + btnSetDateStarted.setText(getString(R.string.setDate)); + } else { + Calendar c = Calendar.getInstance(); + c.set(Calendar.YEAR, startedYear); + c.set(Calendar.MONTH, startedMonth); + c.set(Calendar.DAY_OF_MONTH, startedDay); + c.set(Calendar.HOUR_OF_DAY, 0); + c.set(Calendar.MINUTE, 0); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + + btnSetDateStarted.setText(sdf_date.format(c.getTime())); + } + if (completedYear == -1 || completedMonth == -1 || completedDay == -1) { + btnSetDateCompleted.setText(getString(R.string.setDate)); + } else { + Calendar c = Calendar.getInstance(); + c.set(Calendar.YEAR, completedYear); + c.set(Calendar.MONTH, completedMonth); + c.set(Calendar.DAY_OF_MONTH, completedDay); + c.set(Calendar.HOUR_OF_DAY, 0); + c.set(Calendar.MINUTE, 0); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + + btnSetDateCompleted.setText(sdf_date.format(c.getTime())); + } + + if (startedHour == -1 || startedMinute == -1) { + btnSetTimeStarted.setText(getString(R.string.setTime)); + } else { + Calendar c = Calendar.getInstance(); + c.set(Calendar.HOUR_OF_DAY, startedHour); + c.set(Calendar.MINUTE, startedMinute); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + + btnSetTimeStarted.setText(sdf_time.format(c.getTime())); + } + if (completedHour == -1 || completedMinute == -1) { + btnSetTimeCompleted.setText(getString(R.string.setTime)); + } else { + Calendar c = Calendar.getInstance(); + c.set(Calendar.HOUR_OF_DAY, completedHour); + c.set(Calendar.MINUTE, completedMinute); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + + btnSetTimeCompleted.setText(sdf_time.format(c.getTime())); + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setTheme(getMeditationAssistant().getMATheme()); + setContentView(R.layout.activity_progress); + getActionBar().setDisplayHomeAsUpEnabled(true); /// todo: not necessary on settings activity why? + //getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + + if (getPackageName().equals("sh.ftp.rocketninelabs.meditationassistant")) { + Log.d("MeditationAssistant", "Fetching ad"); + + av = (AdView) findViewById(R.id.adViewProgress); + av.setVisibility(View.VISIBLE); + AdRequest adRequest = new AdRequest.Builder() + .addTestDevice(AdRequest.DEVICE_ID_EMULATOR) + .build(); + av.loadAd(adRequest); + } + + mViewPager = (ViewPager) findViewById(R.id.pager); + + mPagerAdapter = new ProgressPagerAdapter( + getSupportFragmentManager()); + + mViewPager.setAdapter(mPagerAdapter); + + /*ActionBar.TabListener tabListener = new ActionBar.TabListener() { + + public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) { + // hide the given tab + } + + public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) { + // probably ignore this event + } + + @Override + public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) { + + } + }; + + getActionBar().addTab(getActionBar().newTab() + .setText(getString(R.string.sessions)) + .setTabListener(tabListener)); + getActionBar().addTab(getActionBar().newTab() + .setText(getString(R.string.statistics)) + .setTabListener(tabListener)); + + getActionBar().addTab(getActionBar().newTab() + .setText(getString(R.string.calendar)) + .setTabListener(tabListener));*/ + + PagerTabStrip tabStrip = (PagerTabStrip) findViewById(R.id.titles); + tabStrip.setDrawFullUnderline(true); + + if (getMeditationAssistant().getMAThemeString().equals("buddhism")) { + tabStrip.setBackgroundColor(getResources().getColor(R.color.buddhism_tab_background)); + tabStrip.setTabIndicatorColor(getResources().getColor(R.color.buddhism_tab_color)); + tabStrip.setTextColor(getResources().getColor(android.R.color.primary_text_dark)); + } else { + tabStrip.setTabIndicatorColor(getResources().getColor(android.R.color.holo_blue_dark)); + } + + + /*ViewPagerIndicator titleIndicator = (TitlePageIndicator) findViewById(R.id.titles); + titleIndicator.setViewPager(mViewPager); + + titleIndicator.setFooterIndicatorStyle(IndicatorStyle.Underline); + + titleIndicator + .setOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, + float positionOffset, int positionOffsetPixels) { + } + + @Override + public void onPageScrollStateChanged(int state) { + } + + @Override + public void onPageSelected(int position) { + if (menuCalendarBack != null + && menuCalendarForward != null) { + pagePosition = position; + } + } + });*/ + + String defaulttab = getMeditationAssistant().getPrefs().getString( + "pref_progresstab", "calendar"); + if (defaulttab.equals("sessions")) { + mViewPager.setCurrentItem(SESSIONS_FRAGMENT, false); + } else if (defaulttab.equals("stats")) { + mViewPager.setCurrentItem(STATS_FRAGMENT, false); + } else { + mViewPager.setCurrentItem(CALENDAR_FRAGMENT, false); + } + + if (getMeditationAssistant().sendUsageReports()) { + getMeditationAssistant().getTracker(MeditationAssistant.TrackerName.APP_TRACKER); + } + } + + public void goToSessionAtDate(int[] date) { + if (date != null) { + SessionSQL sessionsql = getMeditationAssistant().db.getSessionByDate(String.valueOf(date[0]) + "-" + String.valueOf(date[1] + 1) + "-" + String.valueOf(date[2])); + if (sessionsql != null) { + final Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(sessionsql._completed * 1000); + Date sess_date = cal.getTime(); + + if (getMeditationAssistant().db.numSessionsByDate(String.valueOf(date[0]) + "-" + String.valueOf(date[1] + 1) + "-" + String.valueOf(date[2])) > 1) { + if (sessionDetailsDialog != null && sessionDetailsDialog.isShowing()) { + sessionDetailsDialog.dismiss(); + } + + SimpleDateFormat sdf = new SimpleDateFormat("d MMM yyyy", + Locale.getDefault()); + SimpleDateFormat sdf2 = new SimpleDateFormat("h:mm a", + Locale.getDefault()); + + ArrayList sessions = getMeditationAssistant().db.getSessionsByDate(String.valueOf(date[0]) + "-" + String.valueOf(date[1] + 1) + "-" + String.valueOf(date[2])); + + final ArrayAdapter sessionsDialogAdapter = new ArrayAdapter( + this, + android.R.layout.select_dialog_item); + + sessions_map.clear(); + int session_index = 0; + for (Iterator i = sessions.iterator(); i.hasNext(); ) { + SessionSQL session = i.next(); + Calendar cal2 = Calendar.getInstance(); + cal2.setTimeInMillis(session._completed * 1000); + sessionsDialogAdapter.add(String.valueOf(session._length / 3600) + ":" + + String.format("%02d", (session._length % 3600) / 60) + + " - " + sdf2.format(cal2.getTime())); + + sessions_map.put(session_index, session); + session_index++; + } + + if (sessionDetailsDialog != null && sessionDetailsDialog.isShowing()) { + sessionDetailsDialog.dismiss(); + } + + sessionDetailsDialog = new AlertDialog.Builder(this) + .setIcon( + getResources().getDrawable( + getMeditationAssistant().getTheme().obtainStyledAttributes(getMeditationAssistant().getMATheme(true), + new int[]{R.attr.actionIconGoToToday}) + .getResourceId(0, 0) + ) + ) + .setTitle(sdf.format(sess_date)) + .setAdapter(sessionsDialogAdapter, + new DialogInterface.OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int which) { + SessionSQL session = sessions_map.get(which); + if (session != null) { + showSessionPopup(session); + } + + try { + dialog.dismiss(); + } catch (Exception e) { + + } + } + }) + .create(); + + sessionDetailsDialog.show(); + } else { + showSessionPopup(sessionsql); + } + + /*mViewPager.setCurrentItem(SESSIONS_FRAGMENT, false); + Integer session_position = ((SessionAdapter) sessionsFragment.getListAdapter()).sessions_map.get(String.valueOf(date[0]) + "-" + String.valueOf(date[1] + 1) + "-" + String.valueOf(date[2])); + if (session_position != null) { + Log.d("MeditationAssistant", "Position: " + String.valueOf(session_position)); + sessionsFragment.getListView().smoothScrollToPosition(session_position); + }*/ + } + } + } + + private void showSessionPopup(SessionSQL sessionsql) { + final Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(sessionsql._completed * 1000); + Date sess_date = cal.getTime(); + + SimpleDateFormat sdf = new SimpleDateFormat("d MMM yyyy h:mm a", + Locale.getDefault()); + sdf.setTimeZone(TimeZone.getDefault()); + + SimpleDateFormat sdf2 = new SimpleDateFormat("h:mm a", + Locale.getDefault()); + sdf2.setTimeZone(TimeZone.getDefault()); + + String session_title = String.valueOf(sessionsql._length / 3600) + ":" + + String.format("%02d", (sessionsql._length % 3600) / 60) + + " - " + sdf.format(sess_date); + + cal.setTimeInMillis(sessionsql._started * 1000); + String session_started = sdf2.format(cal.getTime()); + + View detailsView = LayoutInflater.from(this).inflate( + R.layout.session_details, + (ViewGroup) findViewById(R.id.sessionDetails_root)); + + TextView txtSessionDetailsStarted = (TextView) detailsView.findViewById(R.id.txtSessionDetailsStarted); + TextView txtSessionDetailsMessage = (TextView) detailsView.findViewById(R.id.txtSessionDetailsMessage); + + txtSessionDetailsStarted.setText(String.format(getString(R.string.sessionStartedAt), session_started)); + + if (!sessionsql._message.trim().equals("")) { + txtSessionDetailsMessage.setText(sessionsql._message.trim()); + } else { + View divSessionDetailsMessage = detailsView.findViewById(R.id.divSessionDetailsMessage); + + divSessionDetailsMessage.setVisibility(View.GONE); + txtSessionDetailsMessage.setVisibility(View.GONE); + } + + if (sessionDetailsDialog != null && sessionDetailsDialog.isShowing()) { + sessionDetailsDialog.dismiss(); + } + + sessionDetailsDialog = new AlertDialog.Builder(this) + .setIcon( + getResources().getDrawable( + getMeditationAssistant().getTheme().obtainStyledAttributes(getMeditationAssistant().getMATheme(true), + new int[]{R.attr.actionIconGoToToday}) + .getResourceId(0, 0) + ) + ) + .setTitle(session_title) + .setView(detailsView) + .create(); + + sessionDetailsDialog.show(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.progress, menu); + return super.onCreateOptionsMenu(menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + int i = item.getItemId(); + if (i == android.R.id.home) { + NavUtils.navigateUpFromSameTask(this); + } else if (i == R.id.addSession) { + if (addSessionDialog != null) { + try { + if (addSessionDialog.isShowing()) { + addSessionDialog.dismiss(); + } + } catch (WindowManager.BadTokenException e) { + // Activity is not in the foreground + } + } + + //debug + + if (getMeditationAssistant() + .getTimeStartMeditate() > 0) { + getMeditationAssistant().shortToast(getString(R.string.addSessionMeditating)); + return true; + } + + startedYear = -1; + startedMonth = -1; + startedDay = -1; + startedHour = -1; + startedMinute = -1; + + completedYear = -1; + completedMonth = -1; + completedDay = -1; + completedHour = -1; + completedMinute = -1; + + View addSessionView = LayoutInflater.from(this).inflate( + R.layout.session_add, + (ViewGroup) findViewById(R.id.sessionAdd_root)); + + btnSetDateStarted = (Button) addSessionView.findViewById(R.id.btnSetDateStarted); + btnSetTimeStarted = (Button) addSessionView.findViewById(R.id.btnSetTimeStarted); + btnSetDateCompleted = (Button) addSessionView.findViewById(R.id.btnSetDateCompleted); + btnSetTimeCompleted = (Button) addSessionView.findViewById(R.id.btnSetTimeCompleted); + editAddSessionMessage = (EditText) addSessionView.findViewById(R.id.editAddSessionMessage); + + btnSetDateStarted.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + beingSet = "started"; + DatePickerDialog dateDialog = null; + + if (startedYear == -1 || startedMonth == -1 || startedDay == -1) { + Calendar c = Calendar.getInstance(); + dateDialog = new DatePickerDialog(ProgressActivity.this, + mDateSetListener, + c.get(Calendar.YEAR), c.get(Calendar.MONTH), c.get(Calendar.DAY_OF_MONTH)); + } else { + dateDialog = new DatePickerDialog(ProgressActivity.this, + mDateSetListener, + startedYear, startedMonth, startedDay); + } + + dateDialog.show(); + } + }); + btnSetTimeStarted.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + beingSet = "started"; + TimePickerDialog timeDialog = null; + + if (startedHour == -1 || startedMinute == -1) { + Calendar c = Calendar.getInstance(); + timeDialog = new TimePickerDialog(ProgressActivity.this, + mTimeSetListener, + c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE), false); + } else { + timeDialog = new TimePickerDialog(ProgressActivity.this, + mTimeSetListener, + startedHour, startedMinute, false); + } + + timeDialog.show(); + } + }); + btnSetDateCompleted.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + beingSet = "completed"; + DatePickerDialog dateDialog = null; + + if (completedYear == -1 || completedMonth == -1 || completedDay == -1) { + Calendar c = Calendar.getInstance(); + dateDialog = new DatePickerDialog(ProgressActivity.this, + mDateSetListener, + c.get(Calendar.YEAR), c.get(Calendar.MONTH), c.get(Calendar.DAY_OF_MONTH)); + } else { + dateDialog = new DatePickerDialog(ProgressActivity.this, + mDateSetListener, + completedYear, completedMonth, completedDay); + } + + dateDialog.show(); + } + }); + btnSetTimeCompleted.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + beingSet = "completed"; + TimePickerDialog timeDialog = null; + + if (completedHour == -1 || completedMinute == -1) { + Calendar c = Calendar.getInstance(); + timeDialog = new TimePickerDialog(ProgressActivity.this, + mTimeSetListener, + c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE), false); + } else { + timeDialog = new TimePickerDialog(ProgressActivity.this, + mTimeSetListener, + completedHour, completedMinute, false); + } + + timeDialog.show(); + } + }); + + updateDateAndTimeButtons(); + + addSessionDialog = new AlertDialog.Builder(this) + .setIcon( + getResources().getDrawable( + getMeditationAssistant().getTheme().obtainStyledAttributes(getMeditationAssistant().getMATheme(true), + new int[]{R.attr.actionIconNew}) + .getResourceId(0, 0) + ) + ) + .setTitle(getString(R.string.addSession)) + .setView(addSessionView) + .setPositiveButton(getString(R.string.add), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, + int which) { + // Overridden later + } + }) + .setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, + int which) { + dialogInterface.dismiss(); + } + }) + .create(); + + addSessionDialog.show(); + + Button saveButton = addSessionDialog.getButton(AlertDialog.BUTTON_POSITIVE); + saveButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View view) { + if (startedYear == -1 || startedMonth == -1 || startedDay == -1 || startedHour == -1 || startedMinute == -1 || completedYear == -1 || completedMonth == -1 || completedDay == -1 || completedHour == -1 || completedMinute == -1) { + getMeditationAssistant().shortToast(getString(R.string.invalidDateOrTime)); + } else { + Calendar c_started = Calendar.getInstance(); + c_started.set(Calendar.YEAR, startedYear); + c_started.set(Calendar.MONTH, startedMonth); + c_started.set(Calendar.DAY_OF_MONTH, startedDay); + c_started.set(Calendar.HOUR_OF_DAY, startedHour); + c_started.set(Calendar.MINUTE, startedMinute); + c_started.set(Calendar.SECOND, 0); + c_started.set(Calendar.MILLISECOND, 0); + + Calendar c_completed = Calendar.getInstance(); + c_completed.set(Calendar.YEAR, completedYear); + c_completed.set(Calendar.MONTH, completedMonth); + c_completed.set(Calendar.DAY_OF_MONTH, completedDay); + c_completed.set(Calendar.HOUR_OF_DAY, completedHour); + c_completed.set(Calendar.MINUTE, completedMinute); + c_completed.set(Calendar.SECOND, 0); + c_completed.set(Calendar.MILLISECOND, 0); + + if (c_started.getTimeInMillis() > Calendar.getInstance().getTimeInMillis() || c_completed.getTimeInMillis() > Calendar.getInstance().getTimeInMillis() || c_completed.getTimeInMillis() <= c_started.getTimeInMillis()) { + getMeditationAssistant().shortToast(getString(R.string.invalidDateOrTime)); + } else if (getMeditationAssistant().db + .getSessionByStarted(c_started.getTimeInMillis() / 1000) == null) { + getMeditationAssistant().getMediNET().resetSession(); + getMeditationAssistant().getMediNET().session.started = c_started.getTimeInMillis() / 1000; + getMeditationAssistant().getMediNET().session.length = ((c_completed.getTimeInMillis() / 1000) - (c_started.getTimeInMillis() / 1000)); + getMeditationAssistant().getMediNET().session.completed = c_completed.getTimeInMillis() / 1000; + getMeditationAssistant().getMediNET().session.message = editAddSessionMessage.getText().toString().trim(); + getMeditationAssistant().getMediNET().saveSession(true, false); + + addSessionDialog.dismiss(); + + if (sessionsFragment != null) { + sessionsFragment.refreshSessionList(); + } + + /*if (calendarFragment != null) { + calendarFragment.refreshMonthDisplay(); + }*/ + } else { + getMeditationAssistant().shortToast(getString(R.string.addSessionExists)); + } + } + } + }); + + return true; + } + + return super.onOptionsItemSelected(item); + } + + @Override + public void onStart() { + super.onStart(); + if (getMeditationAssistant().sendUsageReports()) { + GoogleAnalytics.getInstance(this).reportActivityStart(this); + } + } + + @Override + protected void onStop() { + super.onStop(); + if (getMeditationAssistant().sendUsageReports()) { + GoogleAnalytics.getInstance(this).reportActivityStop(this); + } + } + + @Override + public void onPause() { + if (av != null) { + av.pause(); + } + super.onPause(); + } + + @Override + public void onResume() { + super.onResume(); + if (av != null) { + av.resume(); + } + } + + @Override + public void onDestroy() { + if (av != null) { + av.destroy(); + } + super.onDestroy(); + } + + class ProgressPagerAdapter extends FragmentPagerAdapter { + private final String[] ProgressPages = new String[]{ + getString(R.string.sessions), getString(R.string.calendar), getString(R.string.statistics)}; + + public ProgressPagerAdapter(FragmentManager fm) { + super(fm); + } + + @Override + public int getCount() { + return ProgressPages.length; + } + + @Override + public Fragment getItem(int position) { + if (position == SESSIONS_FRAGMENT) { + sessionsFragment = new SessionsFragment(); + return sessionsFragment; + } else if (position == CALENDAR_FRAGMENT) { + CalendarFragment calendarFragment = new CalendarFragment(); + return calendarFragment; + } else if (position == STATS_FRAGMENT) { + return new StatsFragment(); + } else { + return null; + } + } + + @Override + public CharSequence getPageTitle(int position) { + return ProgressPages[position % ProgressPages.length].toUpperCase(); + } + } +} + +/* +public class ProgressActivity extends FragmentActivity + implements ItemListFragment.Callbacks { + + /** + * Whether or not the activity is in two-pane mode, i.e. running on a tablet + * device. + private boolean mTwoPane; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_item_list); + + if (findViewById(R.id.item_detail_container) != null) { + // The detail container view will be present only in the + // large-screen layouts (res/values-large and + // res/values-sw600dp). If this view is present, then the + // activity should be in two-pane mode. + mTwoPane = true; + + // In two-pane mode, list items should be given the + // 'activated' state when touched. + ((ItemListFragment) getSupportFragmentManager() + .findFragmentById(R.id.item_list)) + .setActivateOnItemClick(true); + } + } + + /** + * Callback method from {@link ItemListFragment.Callbacks} + * indicating that the item with the given ID was selected. + @Override + public void onItemSelected(String id) { + if (mTwoPane) { + // In two-pane mode, show the detail view in this activity by + // adding or replacing the detail fragment using a + // fragment transaction. + Bundle arguments = new Bundle(); + arguments.putString(ItemDetailFragment.ARG_ITEM_ID, id); + ItemDetailFragment fragment = new ItemDetailFragment(); + fragment.setArguments(arguments); + getSupportFragmentManager().beginTransaction() + .replace(R.id.item_detail_container, fragment) + .apply(); + + } else { + // In single-pane mode, simply start the detail activity + // for the selected item ID. + Intent detailIntent = new Intent(this, ItemDetailActivity.class); + detailIntent.putExtra(ItemDetailFragment.ARG_ITEM_ID, id); + startActivity(detailIntent); + } + } +} +*/ \ No newline at end of file diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/Scroller.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/Scroller.java new file mode 100644 index 0000000..4f602e3 --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/Scroller.java @@ -0,0 +1,495 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import android.content.Context; +import android.hardware.SensorManager; +import android.util.FloatMath; +import android.view.ViewConfiguration; +import android.view.animation.AnimationUtils; +import android.view.animation.Interpolator; + +/** + * This class encapsulates scrolling. The duration of the scroll + * can be passed in the constructor and specifies the maximum time that + * the scrolling animation should take. Past this time, the scrolling is + * automatically moved to its final stage and computeScrollOffset() + * will always return false to indicate that scrolling is over. + */ +public class Scroller { + private static final int DEFAULT_DURATION = 250; + private static final int SCROLL_MODE = 0; + private static final int FLING_MODE = 1; + private static final int NB_SAMPLES = 100; + private static final float[] SPLINE = new float[NB_SAMPLES + 1]; + private static float DECELERATION_RATE = (float) (Math.log(0.75) / Math.log(0.9)); + @SuppressWarnings("FieldCanBeLocal") + private static float ALPHA = 800; // pixels / seconds + private static float START_TENSION = 0.4f; // Tension at start: (0.4 * total T, 1.0 * Distance) + private static float END_TENSION = 1.0f - START_TENSION; + private static float sViscousFluidScale; + private static float sViscousFluidNormalize; + + static { + float x_min = 0.0f; + for (int i = 0; i <= NB_SAMPLES; i++) { + final float t = (float) i / NB_SAMPLES; + float x_max = 1.0f; + float x, tx, coef; + while (true) { + x = x_min + (x_max - x_min) / 2.0f; + coef = 3.0f * x * (1.0f - x); + tx = coef * ((1.0f - x) * START_TENSION + x * END_TENSION) + x * x * x; + if (Math.abs(tx - t) < 1E-5) break; + if (tx > t) x_max = x; + else x_min = x; + } + final float d = coef + x * x * x; + SPLINE[i] = d; + } + SPLINE[NB_SAMPLES] = 1.0f; + + // This controls the viscous fluid effect (how much of it) + sViscousFluidScale = 8.0f; + // must be set to 1.0 (used in viscousFluid()) + sViscousFluidNormalize = 1.0f; + sViscousFluidNormalize = 1.0f / viscousFluid(1.0f); + } + + private final float mPpi; + private int mMode; + private int mStartX; + private int mStartY; + private int mFinalX; + private int mFinalY; + private int mMinX; + private int mMaxX; + private int mMinY; + private int mMaxY; + private int mCurrX; + private int mCurrY; + private long mStartTime; + private int mDuration; + private float mDurationReciprocal; + private float mDeltaX; + private float mDeltaY; + private boolean mFinished; + private Interpolator mInterpolator; + private boolean mFlywheel; + private float mVelocity; + private float mDeceleration; + + /** + * Create a Scroller with the default duration and interpolator. + */ + public Scroller(Context context) { + this(context, null); + } + + /** + * Create a Scroller with the specified interpolator. If the interpolator is + * null, the default (viscous) interpolator will be used. "Flywheel" behavior will + * be in effect for apps targeting Honeycomb or newer. + */ + public Scroller(Context context, Interpolator interpolator) { + this(context, interpolator, true); + } + + /** + * Create a Scroller with the specified interpolator. If the interpolator is + * null, the default (viscous) interpolator will be used. Specify whether or + * not to support progressive "flywheel" behavior in flinging. + */ + public Scroller(Context context, Interpolator interpolator, boolean flywheel) { + mFinished = true; + mInterpolator = interpolator; + mPpi = context.getResources().getDisplayMetrics().density * 160.0f; + mDeceleration = computeDeceleration(ViewConfiguration.getScrollFriction()); + mFlywheel = flywheel; + } + + static float viscousFluid(float x) { + x *= sViscousFluidScale; + if (x < 1.0f) { + x -= (1.0f - (float) Math.exp(-x)); + } else { + float start = 0.36787944117f; // 1/e == exp(-1) + x = 1.0f - (float) Math.exp(1.0f - x); + x = start + x * (1.0f - start); + } + x *= sViscousFluidNormalize; + return x; + } + + /** + * The amount of friction applied to flings. The default value + * is {@link android.view.ViewConfiguration#getScrollFriction}. + * + * @param friction A scalar dimension-less value representing the coefficient of + * friction. + */ + public final void setFriction(float friction) { + mDeceleration = computeDeceleration(friction); + } + + private float computeDeceleration(float friction) { + return SensorManager.GRAVITY_EARTH // g (m/s^2) + * 39.37f // inch/meter + * mPpi // pixels per inch + * friction; + } + + /** + * Returns whether the scroller has finished scrolling. + * + * @return True if the scroller has finished scrolling, false otherwise. + */ + public final boolean isFinished() { + return mFinished; + } + + /** + * Force the finished field to a particular value. + * + * @param finished The new finished value. + */ + public final void forceFinished(boolean finished) { + mFinished = finished; + } + + /** + * Returns how long the scroll event will take, in milliseconds. + * + * @return The duration of the scroll in milliseconds. + */ + public final int getDuration() { + return mDuration; + } + + /** + * Returns the current X offset in the scroll. + * + * @return The new X offset as an absolute distance from the origin. + */ + public final int getCurrX() { + return mCurrX; + } + + /** + * Returns the current Y offset in the scroll. + * + * @return The new Y offset as an absolute distance from the origin. + */ + public final int getCurrY() { + return mCurrY; + } + + /** + * Returns the current velocity. + * + * @return The original velocity less the deceleration. Result may be + * negative. + */ + public float getCurrVelocity() { + return mVelocity - mDeceleration * timePassed() / 2000.0f; + } + + /** + * Returns the start X offset in the scroll. + * + * @return The start X offset as an absolute distance from the origin. + */ + public final int getStartX() { + return mStartX; + } + + /** + * Returns the start Y offset in the scroll. + * + * @return The start Y offset as an absolute distance from the origin. + */ + public final int getStartY() { + return mStartY; + } + + /** + * Returns where the scroll will end. Valid only for "fling" scrolls. + * + * @return The final X offset as an absolute distance from the origin. + */ + public final int getFinalX() { + return mFinalX; + } + + /** + * Sets the final position (X) for this scroller. + * + * @param newX The new X offset as an absolute distance from the origin. + * @see #extendDuration(int) + * @see #setFinalY(int) + */ + public void setFinalX(int newX) { + mFinalX = newX; + mDeltaX = mFinalX - mStartX; + mFinished = false; + } + + /** + * Returns where the scroll will end. Valid only for "fling" scrolls. + * + * @return The final Y offset as an absolute distance from the origin. + */ + public final int getFinalY() { + return mFinalY; + } + + /** + * Sets the final position (Y) for this scroller. + * + * @param newY The new Y offset as an absolute distance from the origin. + * @see #extendDuration(int) + * @see #setFinalX(int) + */ + public void setFinalY(int newY) { + mFinalY = newY; + mDeltaY = mFinalY - mStartY; + mFinished = false; + } + + /** + * Call this when you want to know the new location. If it returns true, + * the animation is not yet finished. loc will be altered to provide the + * new location. + */ + public boolean computeScrollOffset() { + if (mFinished) { + return false; + } + + int timePassed = (int) (AnimationUtils.currentAnimationTimeMillis() - mStartTime); + + if (timePassed < mDuration) { + switch (mMode) { + case SCROLL_MODE: + float x = timePassed * mDurationReciprocal; + + if (mInterpolator == null) + x = viscousFluid(x); + else + x = mInterpolator.getInterpolation(x); + + mCurrX = mStartX + Math.round(x * mDeltaX); + mCurrY = mStartY + Math.round(x * mDeltaY); + break; + case FLING_MODE: + final float t = (float) timePassed / mDuration; + final int index = (int) (NB_SAMPLES * t); + final float t_inf = (float) index / NB_SAMPLES; + final float t_sup = (float) (index + 1) / NB_SAMPLES; + final float d_inf = SPLINE[index]; + final float d_sup = SPLINE[index + 1]; + final float distanceCoef = d_inf + (t - t_inf) / (t_sup - t_inf) * (d_sup - d_inf); + + mCurrX = mStartX + Math.round(distanceCoef * (mFinalX - mStartX)); + // Pin to mMinX <= mCurrX <= mMaxX + mCurrX = Math.min(mCurrX, mMaxX); + mCurrX = Math.max(mCurrX, mMinX); + + mCurrY = mStartY + Math.round(distanceCoef * (mFinalY - mStartY)); + // Pin to mMinY <= mCurrY <= mMaxY + mCurrY = Math.min(mCurrY, mMaxY); + mCurrY = Math.max(mCurrY, mMinY); + + if (mCurrX == mFinalX && mCurrY == mFinalY) { + mFinished = true; + } + + break; + } + } else { + mCurrX = mFinalX; + mCurrY = mFinalY; + mFinished = true; + } + return true; + } + + /** + * Start scrolling by providing a starting point and the distance to travel. + * The scroll will use the default value of 250 milliseconds for the + * duration. + * + * @param startX Starting horizontal scroll offset in pixels. Positive + * numbers will scroll the content to the left. + * @param startY Starting vertical scroll offset in pixels. Positive numbers + * will scroll the content up. + * @param dx Horizontal distance to travel. Positive numbers will scroll the + * content to the left. + * @param dy Vertical distance to travel. Positive numbers will scroll the + * content up. + */ + public void startScroll(int startX, int startY, int dx, int dy) { + startScroll(startX, startY, dx, dy, DEFAULT_DURATION); + } + + /** + * Start scrolling by providing a starting point and the distance to travel. + * + * @param startX Starting horizontal scroll offset in pixels. Positive + * numbers will scroll the content to the left. + * @param startY Starting vertical scroll offset in pixels. Positive numbers + * will scroll the content up. + * @param dx Horizontal distance to travel. Positive numbers will scroll the + * content to the left. + * @param dy Vertical distance to travel. Positive numbers will scroll the + * content up. + * @param duration Duration of the scroll in milliseconds. + */ + public void startScroll(int startX, int startY, int dx, int dy, int duration) { + mMode = SCROLL_MODE; + mFinished = false; + mDuration = duration; + mStartTime = AnimationUtils.currentAnimationTimeMillis(); + mStartX = startX; + mStartY = startY; + mFinalX = startX + dx; + mFinalY = startY + dy; + mDeltaX = dx; + mDeltaY = dy; + mDurationReciprocal = 1.0f / (float) mDuration; + } + + /** + * Start scrolling based on a fling gesture. The distance travelled will + * depend on the initial velocity of the fling. + * + * @param startX Starting point of the scroll (X) + * @param startY Starting point of the scroll (Y) + * @param velocityX Initial velocity of the fling (X) measured in pixels per + * second. + * @param velocityY Initial velocity of the fling (Y) measured in pixels per + * second + * @param minX Minimum X value. The scroller will not scroll past this + * point. + * @param maxX Maximum X value. The scroller will not scroll past this + * point. + * @param minY Minimum Y value. The scroller will not scroll past this + * point. + * @param maxY Maximum Y value. The scroller will not scroll past this + * point. + */ + public void fling(int startX, int startY, int velocityX, int velocityY, + int minX, int maxX, int minY, int maxY) { + // Continue a scroll or fling in progress + if (mFlywheel && !mFinished) { + float oldVel = getCurrVelocity(); + + float dx = (float) (mFinalX - mStartX); + float dy = (float) (mFinalY - mStartY); + float hyp = FloatMath.sqrt(dx * dx + dy * dy); + + float ndx = dx / hyp; + float ndy = dy / hyp; + + float oldVelocityX = ndx * oldVel; + float oldVelocityY = ndy * oldVel; + if (Math.signum(velocityX) == Math.signum(oldVelocityX) && + Math.signum(velocityY) == Math.signum(oldVelocityY)) { + velocityX += oldVelocityX; + velocityY += oldVelocityY; + } + } + + mMode = FLING_MODE; + mFinished = false; + + float velocity = FloatMath.sqrt(velocityX * velocityX + velocityY * velocityY); + + mVelocity = velocity; + final double l = Math.log(START_TENSION * velocity / ALPHA); + mDuration = (int) (1000.0 * Math.exp(l / (DECELERATION_RATE - 1.0))); + mStartTime = AnimationUtils.currentAnimationTimeMillis(); + mStartX = startX; + mStartY = startY; + + float coeffX = velocity == 0 ? 1.0f : velocityX / velocity; + float coeffY = velocity == 0 ? 1.0f : velocityY / velocity; + + int totalDistance = + (int) (ALPHA * Math.exp(DECELERATION_RATE / (DECELERATION_RATE - 1.0) * l)); + + mMinX = minX; + mMaxX = maxX; + mMinY = minY; + mMaxY = maxY; + + mFinalX = startX + Math.round(totalDistance * coeffX); + // Pin to mMinX <= mFinalX <= mMaxX + mFinalX = Math.min(mFinalX, mMaxX); + mFinalX = Math.max(mFinalX, mMinX); + + mFinalY = startY + Math.round(totalDistance * coeffY); + // Pin to mMinY <= mFinalY <= mMaxY + mFinalY = Math.min(mFinalY, mMaxY); + mFinalY = Math.max(mFinalY, mMinY); + } + + /** + * Stops the animation. Contrary to {@link #forceFinished(boolean)}, + * aborting the animating cause the scroller to move to the final x and y + * position + * + * @see #forceFinished(boolean) + */ + public void abortAnimation() { + mCurrX = mFinalX; + mCurrY = mFinalY; + mFinished = true; + } + + /** + * Extend the scroll animation. This allows a running animation to scroll + * further and longer, when used with {@link #setFinalX(int)} or {@link #setFinalY(int)}. + * + * @param extend Additional time to scroll in milliseconds. + * @see #setFinalX(int) + * @see #setFinalY(int) + */ + public void extendDuration(int extend) { + int passed = timePassed(); + mDuration = passed + extend; + mDurationReciprocal = 1.0f / mDuration; + mFinished = false; + } + + /** + * Returns the time elapsed since the beginning of the scrolling. + * + * @return The elapsed time in milliseconds. + */ + public int timePassed() { + return (int) (AnimationUtils.currentAnimationTimeMillis() - mStartTime); + } + + /** + * @hide + */ + public boolean isScrollingInDirection(float xvel, float yvel) { + return !mFinished && Math.signum(xvel) == Math.signum(mFinalX - mStartX) && + Math.signum(yvel) == Math.signum(mFinalY - mStartY); + } +} \ No newline at end of file diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/SessionAdapter.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/SessionAdapter.java new file mode 100644 index 0000000..a9265a0 --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/SessionAdapter.java @@ -0,0 +1,84 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.TextView; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.TimeZone; + +public class SessionAdapter extends ArrayAdapter { + public Map sessions_map = new HashMap(); + // private final ArrayList sessions; + private Context context = null; + private ArrayList sessions = null; + + public SessionAdapter(Context context, ArrayList sess) { + super(context, R.layout.activity_sessions_item, sess); + this.context = context; + this.sessions = sess; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + LayoutInflater inflater = (LayoutInflater) context + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + + View rowView = inflater.inflate(R.layout.activity_sessions_item, + parent, false); + TextView txtSessionLength = (TextView) rowView + .findViewById(R.id.session_length); + TextView txtSessionStarted = (TextView) rowView + .findViewById(R.id.session_started); + TextView txtSessionStartedTime = (TextView) rowView + .findViewById(R.id.session_started_time); + + txtSessionLength + .setText(String.valueOf(sessions.get(position)._length / 3600) + + ":" + + String.format("%02d", + (sessions.get(position)._length % 3600) / 60)); + // txtSessionLength.setText(String.format("%d:%02d", + // sessions.get(position).length/3600, + // (sessions.get(position).length%3600)/60)); + + final Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis((sessions.get(position)._started + sessions + .get(position)._length) * 1000); + Date date = cal.getTime(); + + SimpleDateFormat sdf = new SimpleDateFormat("h:mm a", Locale.getDefault()); + SimpleDateFormat sdf2 = new SimpleDateFormat("d MMM yyyy", Locale.getDefault()); + SimpleDateFormat sdf3 = new SimpleDateFormat("d-M-yyyy", Locale.getDefault()); + sdf.setTimeZone(TimeZone.getDefault()); + sdf2.setTimeZone(TimeZone.getDefault()); + sdf3.setTimeZone(TimeZone.getDefault()); + + // sessions.get(position).date = sdf.format(date); + // sessions.get(position).time = sdf2.format(date); + + txtSessionStartedTime.setText(sdf.format(date)); + txtSessionStarted.setText(sdf2.format(date)); + + // Change icon based on name + // String s = values[position]; + + // Log.d("MeditationAssistant", "LV: " + s); + + /*if (!sessions_map.containsKey(sdf3.format(date))) { + Log.d("MeditationAssistant", "Session position: " + sdf3.format(date) + " - " + String.valueOf(position)); + sessions_map.put(sdf3.format(date), position); + }*/ + + return rowView; + } +} \ No newline at end of file diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/SessionSQL.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/SessionSQL.java new file mode 100644 index 0000000..9760863 --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/SessionSQL.java @@ -0,0 +1,42 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +public class SessionSQL { + public Long _id; + public Long _started; + public Long _completed; + public Long _length; + public String _message; + public Long _isposted; + public Long _streakday; + + public SessionSQL() { + } + + public SessionSQL(Long id, Long started, Long completed, Long length, String message, + Long isposted, Long streakday) { + this._id = id; + this._started = started; + this._completed = completed; + this._length = length; + this._message = message; + this._isposted = isposted; + this._streakday = streakday; + } + + public SessionSQL(Long started, Long completed, Long length, String message, Long isposted, Long streakday) { + this._started = started; + this._completed = completed; + this._length = length; + this._message = message; + this._isposted = isposted; + this._streakday = streakday; + } + + public Long getID() { + return this._id; + } + + public void setID(Long id) { + this._id = id; + } +} \ No newline at end of file diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/SessionsFragment.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/SessionsFragment.java new file mode 100644 index 0000000..6bdbaef --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/SessionsFragment.java @@ -0,0 +1,273 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.support.v4.app.ListFragment; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.widget.ListView; +import android.widget.TextView; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +public class SessionsFragment extends ListFragment { + public MeditationAssistant ma = null; + AlertDialog sessionDialog = null; + AlertDialog sessionDetailsDialog = null; + SessionSQL selected_session = null; + String session_title = null; + String session_started = null; + + SharedPreferences.OnSharedPreferenceChangeListener sharedPrefslistener = new SharedPreferences.OnSharedPreferenceChangeListener() { + public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { + if (key.equals("sessionsupdate")) { + Log.d("MeditationAssistant", "Got sessions update, refreshing SessionsFragment"); + refreshSessionList(); + } + } + }; + + public MeditationAssistant getMeditationAssistant() { + if (ma == null) { + ma = (MeditationAssistant) getActivity().getApplication(); + } + return ma; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getMeditationAssistant().getPrefs().registerOnSharedPreferenceChangeListener(sharedPrefslistener); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + getListView().setOnItemLongClickListener(new android.widget.AdapterView.OnItemLongClickListener() { + @Override + public boolean onItemLongClick(android.widget.AdapterView adapterView, View view, int position, long id) { + if (sessionDetailsDialog != null) { + try { + if (sessionDetailsDialog.isShowing()) { + sessionDetailsDialog.dismiss(); + } + } catch (WindowManager.BadTokenException e) { + // Activity is not in the foreground + } + } + + if (sessionDialog != null) { + try { + if (sessionDialog.isShowing()) { + sessionDialog.dismiss(); + } + } catch (WindowManager.BadTokenException e) { + // Activity is not in the foreground + } + } + + selected_session = (SessionSQL) getListView().getItemAtPosition(position); + setSessionDialogDetails(); + + sessionDialog = new AlertDialog.Builder(getActivity()) + .setIcon( + getActivity().getResources().getDrawable( + getMeditationAssistant().getTheme().obtainStyledAttributes(getMeditationAssistant().getMATheme(true), + new int[]{R.attr.actionIconGoToToday}) + .getResourceId(0, 0) + ) + ) + .setTitle(session_title) + .setItems(R.array.session_actions, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, + int which) { + if (which == 0) { + if (getMeditationAssistant() + .getTimeStartMeditate() > 0) { + getActivity().runOnUiThread( + new Runnable() { + @Override + public void run() { + getMeditationAssistant() + .shortToast( + getString(R.string.sessionNotPostedMeditating)); + } + } + ); + } else { + getMeditationAssistant().getMediNET().session.started = selected_session._started; + getMeditationAssistant().getMediNET().session.length = selected_session._length; + getMeditationAssistant().getMediNET().session.message = selected_session._message; + getMeditationAssistant().getMediNET().session.streakday = selected_session._streakday; + getMeditationAssistant().getMediNET() + .postSession(true, + getActivity()); + } + } else { + AlertDialog deleteDialog = new AlertDialog.Builder( + getActivity()) + .setIcon( + getActivity().getResources().getDrawable( + getMeditationAssistant().getTheme().obtainStyledAttributes(getMeditationAssistant().getMATheme(true), + new int[]{R.attr.actionIconGoToToday}) + .getResourceId(0, 0) + ) + ) + .setTitle(session_title) + .setItems( + R.array.session_delete_actions, + new DialogInterface.OnClickListener() { + @Override + public void onClick( + DialogInterface dialog, + int which) { + if (which == 0 + || which == 1) { + // Delete + // locally + getMeditationAssistant().db + .deleteSession(selected_session); + getMeditationAssistant() + .shortToast( + getString(R.string.sessionDeletedLocally)); + } + if (which == 0 + || which == 2) { + // Delete on + // Medinet + getMeditationAssistant() + .getMediNET() + .deleteSessionByStarted( + selected_session._started); + } + + if (which == 0 + || which == 1) { + refreshSessionList(); + } + } + } + ).create(); + deleteDialog.show(); + } + } + } + ).create(); + + sessionDialog.show(); + + return true; + } + }); + + refreshSessionList(); + } + + @Override + public void onListItemClick(ListView l, View v, int position, long id) { + if (sessionDetailsDialog != null) { + try { + if (sessionDetailsDialog.isShowing()) { + sessionDetailsDialog.dismiss(); + } + } catch (WindowManager.BadTokenException e) { + // Activity is not in the foreground + } + } + + if (sessionDialog != null) { + try { + if (sessionDialog.isShowing()) { + sessionDialog.dismiss(); + } + } catch (WindowManager.BadTokenException e) { + // Activity is not in the foreground + } + } + + selected_session = (SessionSQL) l.getItemAtPosition(position); + setSessionDialogDetails(); + + View detailsView = LayoutInflater.from(getActivity()).inflate( + R.layout.session_details, + (ViewGroup) getActivity().findViewById(R.id.sessionDetails_root)); + + TextView txtSessionDetailsStarted = (TextView) detailsView.findViewById(R.id.txtSessionDetailsStarted); + TextView txtSessionDetailsMessage = (TextView) detailsView.findViewById(R.id.txtSessionDetailsMessage); + + txtSessionDetailsStarted.setText(String.format(getString(R.string.sessionStartedAt), session_started)); + + if (!selected_session._message.trim().equals("")) { + txtSessionDetailsMessage.setText(selected_session._message.trim()); + } else { + View divSessionDetailsMessage = detailsView.findViewById(R.id.divSessionDetailsMessage); + + divSessionDetailsMessage.setVisibility(View.GONE); + txtSessionDetailsMessage.setVisibility(View.GONE); + } + + sessionDetailsDialog = new AlertDialog.Builder(getActivity()) + .setIcon( + getActivity().getResources().getDrawable( + getMeditationAssistant().getTheme().obtainStyledAttributes(getMeditationAssistant().getMATheme(true), + new int[]{R.attr.actionIconGoToToday}) + .getResourceId(0, 0) + ) + ) + .setTitle(session_title) + .setView(detailsView) + .create(); + + sessionDetailsDialog.show(); + } + + private void setSessionDialogDetails() { + SimpleDateFormat sdf = new SimpleDateFormat("d MMM yyyy h:mm a", + Locale.getDefault()); + sdf.setTimeZone(TimeZone.getDefault()); + + SimpleDateFormat sdf2 = new SimpleDateFormat("h:mm a", + Locale.getDefault()); + sdf2.setTimeZone(TimeZone.getDefault()); + + final Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(selected_session._completed * 1000); + Date date = cal.getTime(); + + session_title = String.valueOf(selected_session._length / 3600) + ":" + + String.format("%02d", (selected_session._length % 3600) / 60) + + " - " + sdf.format(date); + + cal.setTimeInMillis(selected_session._started * 1000); + session_started = sdf2.format(cal.getTime()); + } + + public void refreshSessionList() { + setListAdapter(new SessionAdapter(getActivity(), + getMeditationAssistant().db.getAllSessions())); + } + + @Override + public void onPause() { + getMeditationAssistant().getPrefs().unregisterOnSharedPreferenceChangeListener(sharedPrefslistener); + super.onPause(); + } + + @Override + public void onResume() { + getMeditationAssistant().getPrefs().registerOnSharedPreferenceChangeListener(sharedPrefslistener); + super.onResume(); + } +} \ No newline at end of file diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/SettingsActivity.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/SettingsActivity.java new file mode 100644 index 0000000..179a287 --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/SettingsActivity.java @@ -0,0 +1,745 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +import android.annotation.TargetApi; +import android.content.Context; +import android.content.Intent; +import android.content.res.Configuration; +import android.media.Ringtone; +import android.media.RingtoneManager; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.preference.CheckBoxPreference; +import android.preference.EditTextPreference; +import android.preference.ListPreference; +import android.preference.Preference; +import android.preference.PreferenceActivity; +import android.preference.PreferenceCategory; +import android.preference.PreferenceFragment; +import android.preference.RingtonePreference; +import android.text.TextUtils; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.widget.Toast; + +import com.google.android.gms.analytics.GoogleAnalytics; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; + +/** + * A {@link PreferenceActivity} that presents a set of application settings. On + * handset devices, settings are presented as a single list. On tablets, + * settings are split by category, with category headers shown to the left of + * the list of settings. + *

+ * See + * Android Design: Settings for design guidelines and the Settings + * API Guide for more information on developing a Settings UI. + */ +@SuppressWarnings("deprecation") +public class SettingsActivity extends PreferenceActivity { + /** + * Determines whether to always show the simplified settings UI, where + * settings are presented in a single list. When false, settings are shown + * as a master/detail two-pane view on tablets. When true, a single pane is + * shown on tablets. + */ + private static final boolean ALWAYS_SIMPLE_PREFS = false; + + public Boolean initialThemeChange = true; + public Boolean initialTimePickerChange = true; + public Boolean initialSoundChangeStart = true; + public Boolean initialSoundChangeInterval = true; + public Boolean initialSoundChangeFinish = true; + public SessionPreferenceFragment sessionPreferenceFragment = null; + public ReminderPreferenceFragment reminderPreferenceFragment = null; + public MeditationPreferenceFragment meditationPreferenceFragment = null; + public MediNETPreferenceFragment medinetPreferenceFragment = null; + public MiscellaneousPreferenceFragment miscellaneousPreferenceFragment = null; + int PREF_SOUND_START = 1; + int PREF_SOUND_INTERVAL = 3; + int PREF_SOUND_FINISH = 2; + private MeditationAssistant ma = null; + + /** + * A preference value change listener that updates the preference's summary + * to reflect its new value. + */ + private Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object value) { + if (preference instanceof CheckBoxPreference) { + if (preference.getKey().equals("pref_daily_reminder")) { + Intent intent = new Intent(); + intent.setAction(MeditationAssistant.ACTION_UPDATED); + sendBroadcast(intent); + } else if (preference.getKey().equals("pref_usetimepicker")) { + if (!initialTimePickerChange) { + Toast.makeText(SettingsActivity.this, getString(R.string.restartAppApplyTimePicker), Toast.LENGTH_SHORT).show(); + } + initialTimePickerChange = false; + } + + return true; + } + + String stringValue = ""; + if (!preference.getKey().equals("pref_presetsettings")) { + stringValue = value.toString(); + } + + if (preference.getKey().equals("pref_presetsettings")) { + HashSet presetSettings = (HashSet) value; + if (presetSettings.size() == 0) { + preference.setSummary(getString(R.string.disabled)); + } else { + List presetsettings = Arrays.asList(getResources().getStringArray(R.array.presetsettings)); + List presetsettings_values = Arrays.asList(getResources().getStringArray(R.array.presetsettings_values)); + + String presetsummary = ""; + + for (Iterator preseti = presetsettings_values.iterator(); preseti.hasNext(); ) { + String preset = preseti.next(); + if (presetSettings.contains(preset)) { + if (presetsummary != "") { + presetsummary += ", "; + } + presetsummary += presetsettings.get(presetsettings_values.indexOf(preset)); + } + } + + preference.setSummary(presetsummary); + } + } else if (preference instanceof ListPreference || preference instanceof ListPreferenceSound) { + // For list preferences, look up the correct display value in + // the preference's 'entries' list. + ListPreference listPreference = (ListPreference) preference; + int index = listPreference.findIndexOfValue(stringValue); + + // Set the summary to reflect the new value. + preference.setSummary( + index >= 0 + ? listPreference.getEntries()[index] + : "Gong" + ); // TODO: Don't hardcode sound names + + if (listPreference.getKey().equals("pref_theme")) { + if (!initialThemeChange) { + Toast.makeText(SettingsActivity.this, getString(R.string.restartAppApplyTheme), Toast.LENGTH_SHORT).show(); + } + initialThemeChange = false; + } else if (listPreference.getKey().equals("pref_meditation_sound_start")) { + if (stringValue.equals("custom")) { + if (!initialSoundChangeStart) { + Intent intent = new Intent( + Intent.ACTION_GET_CONTENT); + intent.setType("file/*"); + intent.addCategory(Intent.CATEGORY_OPENABLE); + Intent finalIntent = Intent.createChooser( + intent, getString(R.string.selectSound)); + startActivityForResult(finalIntent, PREF_SOUND_START); + } + + preference.setSummary(customSoundSummary(getMeditationAssistant().getPrefs().getString("pref_meditation_sound_start_custom", ""))); + } + initialSoundChangeStart = false; + } else if (listPreference.getKey().equals("pref_meditation_sound_interval")) { + if (stringValue.equals("custom")) { + if (!initialSoundChangeInterval) { + Intent intent = new Intent( + Intent.ACTION_GET_CONTENT); + intent.setType("file/*"); + intent.addCategory(Intent.CATEGORY_OPENABLE); + Intent finalIntent = Intent.createChooser( + intent, getString(R.string.selectSound)); + startActivityForResult(finalIntent, PREF_SOUND_INTERVAL); + } + + preference.setSummary(customSoundSummary(getMeditationAssistant().getPrefs().getString("pref_meditation_sound_interval_custom", ""))); + } + initialSoundChangeInterval = false; + } else if (listPreference.getKey().equals("pref_meditation_sound_finish")) { + if (stringValue.equals("custom")) { + if (!initialSoundChangeFinish) { + Intent intent = new Intent( + Intent.ACTION_GET_CONTENT); + intent.setType("file/*"); + intent.addCategory(Intent.CATEGORY_OPENABLE); + Intent finalIntent = Intent.createChooser( + intent, getString(R.string.selectSound)); + startActivityForResult(finalIntent, PREF_SOUND_FINISH); + } + + preference.setSummary(customSoundSummary(getMeditationAssistant().getPrefs().getString("pref_meditation_sound_finish_custom", ""))); + } + initialSoundChangeFinish = false; + } + } else if (preference instanceof RingtonePreference) { + // For ringtone preferences, look up the correct display value + // using RingtoneManager. + if (TextUtils.isEmpty(stringValue)) { + // Empty values correspond to 'silent' (no ringtone). + //preference.setSummary(R.string.pref_ringtone_silent); + + } else { + Ringtone ringtone = RingtoneManager.getRingtone( + preference.getContext(), Uri.parse(stringValue)); + + if (ringtone == null) { + // Clear the summary if there was a lookup error. + preference.setSummary(null); + } else { + // Set the summary to reflect the new ringtone display + // name. + String name = ringtone.getTitle(preference.getContext()); + preference.setSummary(name); + } + } + } else if (preference instanceof TimePreference) { + if (preference.getKey().equals("pref_daily_reminder_time")) { + String timeValue = ""; + try { + String[] timeValueSplit = ((stringValue != null && stringValue != "") ? stringValue : "19:00").split(":"); + + String ampm = "AM"; + if (Integer.valueOf(timeValueSplit[0]) >= 12) { + timeValueSplit[0] = String.valueOf(Integer.valueOf(timeValueSplit[0]) - 12); + ampm = "PM"; + } + if (Integer.valueOf(timeValueSplit[0]) == 0) { + timeValueSplit[0] = "12"; + } + + timeValue = String.valueOf(Integer.valueOf(timeValueSplit[0])) + ":" + + String.format("%02d", Integer.valueOf(timeValueSplit[1])) + " " + ampm; + } catch (Exception e) { + e.printStackTrace(); + } + preference.setSummary(timeValue); + + Intent intent = new Intent(); + intent.setAction(MeditationAssistant.ACTION_UPDATED); + sendBroadcast(intent); + } else { // pref_session_delay and pref_session_interval + Log.d("MeditationAssistant", preference.getKey() + " value: " + String.valueOf(stringValue)); + + String timeValue = ""; + Boolean isDisabled = false; + try { + String[] timeValueSplit = ((stringValue != null && stringValue != "") ? stringValue : (preference.getKey().equals("pref_session_delay") ? "00:15" : "00:00")).split(":"); + timeValue = String.valueOf((int) Math.floor(Integer.valueOf(timeValueSplit[0]) / 60)) + ":" + + String.format("%02d", Integer.valueOf(timeValueSplit[0]) % 60) + ":" + + String.format("%02d", Integer.valueOf(timeValueSplit[1])); + isDisabled = (Integer.valueOf(timeValueSplit[0]) == 0 && Integer.valueOf(timeValueSplit[1]) == 0); + } catch (Exception e) { + e.printStackTrace(); + } + + preference.setSummary(isDisabled ? getString(R.string.disabled) : timeValue); + + if (preference.getKey().equals("pref_session_interval")) { + ListPreferenceSound prefIntervalSound = (ListPreferenceSound) (sessionPreferenceFragment == null ? findPreference("pref_meditation_sound_interval") : sessionPreferenceFragment.findPreference("pref_meditation_sound_interval")); + prefIntervalSound.setEnabled(!isDisabled); + + EditTextPreference prefIntervalCount = (EditTextPreference) (sessionPreferenceFragment == null ? findPreference("pref_interval_count") : sessionPreferenceFragment.findPreference("pref_interval_count")); + prefIntervalCount.setEnabled(!isDisabled); + } + } + } else if (preference.getKey().equals("pref_interval_count")) { + if (stringValue == null || String.valueOf(stringValue).trim().equals("")) { + stringValue = "0"; + } + if (Integer.valueOf(stringValue) <= 0) { + preference.setSummary(getString(R.string.unlimited)); + } else { + preference.setSummary(getResources().getQuantityString( + R.plurals.numtimes, Integer.valueOf(stringValue), + String.valueOf(Integer.valueOf(stringValue)) + )); + } + } else if (preference.getKey().equals("pref_daily_reminder_text")) { + String reminderText = getString(R.string.reminderText); + if (stringValue != null && !String.valueOf(stringValue).trim().equals("")) { + reminderText = String.valueOf(stringValue).trim(); + } + preference.setSummary(reminderText); + } else { + // For all other preferences, set the summary to the value's + // simple string representation. + preference.setSummary(stringValue); + } + + return true; + } + }; + private Long uploadsessions_lastlick = (long) 0; + private Long importsessions_lastlick = (long) 0; + + /** + * Helper method to determine if the device has an extra-large screen. For + * example, 10" tablets are extra-large. + */ + private static boolean isXLargeTablet(Context context) { + return (context.getResources().getConfiguration().screenLayout + & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE; + } + + /** + * Determines whether the simplified settings UI should be shown. This is + * true if this is forced via {@link #ALWAYS_SIMPLE_PREFS}, or the device + * doesn't have newer APIs like {@link PreferenceFragment}, or the device + * doesn't have an extra-large screen. In these cases, a single-pane + * "simplified" settings UI should be shown. + */ + @SuppressWarnings("BooleanMethodIsAlwaysInverted") + private static boolean isSimplePreferences(Context context) { + return Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB + || !isXLargeTablet(context); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + setTheme(getMeditationAssistant().getMATheme()); + + if (getMeditationAssistant().sendUsageReports()) { + getMeditationAssistant().getTracker(MeditationAssistant.TrackerName.APP_TRACKER); + } + + super.onCreate(savedInstanceState); + } + + @Override + public void onStart() { + super.onStart(); + if (getMeditationAssistant().sendUsageReports()) { + GoogleAnalytics.getInstance(this).reportActivityStart(this); + } + } + + @Override + protected void onStop() { + super.onStop(); + if (getMeditationAssistant().sendUsageReports()) { + GoogleAnalytics.getInstance(this).reportActivityStop(this); + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + Uri d = null; + String pref = ""; + String pref_key = ""; + if (requestCode == PREF_SOUND_START) { + pref_key = "pref_meditation_sound_start"; + pref = "pref_meditation_sound_start_custom"; + } else if (requestCode == PREF_SOUND_INTERVAL) { + pref_key = "pref_meditation_sound_interval"; + pref = "pref_meditation_sound_interval_custom"; + } else if (requestCode == PREF_SOUND_FINISH) { + pref_key = "pref_meditation_sound_finish"; + pref = "pref_meditation_sound_finish_custom"; + } else { + return; + } + + if (data != null) { + d = data.getData(); + if (d != null) { + if (!d.toString().equals("")) { + getMeditationAssistant().getPrefs().edit().putString(pref, FileUtils.getPath(this, d)).apply(); + } + } + } + + if (requestCode == PREF_SOUND_START) { + initialSoundChangeStart = true; + } else if (requestCode == PREF_SOUND_INTERVAL) { + initialSoundChangeInterval = true; + } else if (requestCode == PREF_SOUND_FINISH) { + initialSoundChangeFinish = true; + } + + ListPreferenceSound prefMeditationSound = (ListPreferenceSound) (sessionPreferenceFragment == null ? findPreference(pref_key) : sessionPreferenceFragment.findPreference(pref_key)); + prefMeditationSound.getOnPreferenceChangeListener().onPreferenceChange(prefMeditationSound, getMeditationAssistant().getPrefs().getString(pref_key, "gong")); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.settings, menu); + return super.onCreateOptionsMenu(menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + Intent intent = null; + int i = item.getItemId(); + if (i == R.id.action_about) { + intent = new Intent(this, AboutActivity.class); + startActivity(intent); + return true; + } else if (i == R.id.action_accountsettings) { + Intent openActivity = new Intent(this, + MediNETActivity.class); + openActivity.putExtra("page", "account"); + startActivity(openActivity); + finish(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + protected void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + + setupSimplePreferencesScreen(); + } + + void setupSoundPreferences(PreferenceFragment preferenceFragment) { + String[] meditation_sounds = getResources().getStringArray(R.array.meditation_sounds); + String[] meditation_sounds_values = getResources().getStringArray(R.array.meditation_sounds_values); + + ListPreferenceSound prefMeditationSoundStart = (ListPreferenceSound) (preferenceFragment == null ? findPreference("pref_meditation_sound_start") : preferenceFragment.findPreference("pref_meditation_sound_start")); + prefMeditationSoundStart.setEntries(meditation_sounds); + prefMeditationSoundStart.setEntryValues(meditation_sounds_values); + + ListPreferenceSound prefMeditationSoundInterval = (ListPreferenceSound) (preferenceFragment == null ? findPreference("pref_meditation_sound_interval") : preferenceFragment.findPreference("pref_meditation_sound_interval")); + prefMeditationSoundInterval.setEntries(meditation_sounds); + prefMeditationSoundInterval.setEntryValues(meditation_sounds_values); + + ListPreferenceSound prefMeditationSoundFinish = (ListPreferenceSound) (preferenceFragment == null ? findPreference("pref_meditation_sound_finish") : preferenceFragment.findPreference("pref_meditation_sound_finish")); + prefMeditationSoundFinish.setEntries(meditation_sounds); + prefMeditationSoundFinish.setEntryValues(meditation_sounds_values); + } + + void setupPreferences(String pref_type, PreferenceFragment preferenceFragment) { + if (pref_type.equals("all") || pref_type.equals("session")) { + if (preferenceFragment != null) { + sessionPreferenceFragment = (SessionPreferenceFragment) preferenceFragment; + } + + bindPreferenceSummaryToValue(preferenceFragment == null ? findPreference("pref_session_delay") : preferenceFragment.findPreference("pref_session_delay")); + bindPreferenceSummaryToValue(preferenceFragment == null ? findPreference("pref_meditation_sound_start") : preferenceFragment.findPreference("pref_meditation_sound_start")); + bindPreferenceSummaryToValue(preferenceFragment == null ? findPreference("pref_meditation_sound_interval") : preferenceFragment.findPreference("pref_meditation_sound_interval")); + bindPreferenceSummaryToValue(preferenceFragment == null ? findPreference("pref_session_interval") : preferenceFragment.findPreference("pref_session_interval")); + bindPreferenceSummaryToValue(preferenceFragment == null ? findPreference("pref_interval_count") : preferenceFragment.findPreference("pref_interval_count")); + bindPreferenceSummaryToValue(preferenceFragment == null ? findPreference("pref_meditation_sound_finish") : preferenceFragment.findPreference("pref_meditation_sound_finish")); + bindPreferenceSummaryToValue(preferenceFragment == null ? findPreference("pref_notificationcontrol") : preferenceFragment.findPreference("pref_notificationcontrol")); + bindPreferenceSummaryToValue(preferenceFragment == null ? findPreference("pref_presetsettings") : preferenceFragment.findPreference("pref_presetsettings")); + } + if (pref_type.equals("all") || pref_type.equals("reminder")) { + if (preferenceFragment != null) { + reminderPreferenceFragment = (ReminderPreferenceFragment) preferenceFragment; + } + + bindPreferenceSummaryToValue(preferenceFragment == null ? findPreference("pref_daily_reminder_text") : preferenceFragment.findPreference("pref_daily_reminder_text")); + bindPreferenceSummaryToValue(preferenceFragment == null ? findPreference("pref_daily_reminder_time") : preferenceFragment.findPreference("pref_daily_reminder_time")); + bindPreferenceSummaryToValue(preferenceFragment == null ? findPreference("pref_daily_reminder") : preferenceFragment.findPreference("pref_daily_reminder")); + } + if (pref_type.equals("all") || pref_type.equals("meditation")) { + if (preferenceFragment != null) { + meditationPreferenceFragment = (MeditationPreferenceFragment) preferenceFragment; + } + + bindPreferenceSummaryToValue(preferenceFragment == null ? findPreference("pref_usetimepicker") : preferenceFragment.findPreference("pref_usetimepicker")); + bindPreferenceSummaryToValue(preferenceFragment == null ? findPreference("pref_text_size") : preferenceFragment.findPreference("pref_text_size")); + bindPreferenceSummaryToValue(preferenceFragment == null ? findPreference("pref_progresstab") : preferenceFragment.findPreference("pref_progresstab")); + bindPreferenceSummaryToValue(preferenceFragment == null ? findPreference("pref_screencontrol") : preferenceFragment.findPreference("pref_screencontrol")); + } + if (pref_type.equals("all") || pref_type.equals("medinet")) { + if (preferenceFragment != null) { + medinetPreferenceFragment = (MediNETPreferenceFragment) preferenceFragment; + } + + Preference uploadSessions = (preferenceFragment == null ? findPreference("uploadsessions") : preferenceFragment.findPreference("uploadsessions")); + uploadSessions + .setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference arg0) { + + if (getMeditationAssistant().getMediNETKey().equals("")) { + getMeditationAssistant().getMediNET().askToSignIn(); + getMeditationAssistant().shortToast( + getString(R.string.signInToMediNET)); + } else { + ArrayList sessionssql = getMeditationAssistant().db.getAllLocalSessions(); + + if (sessionssql.size() == 0) { + getMeditationAssistant().longToast( + getMeditationAssistant().getString(R.string.sessionsNotImported)); + + return false; + } + + if (getMeditationAssistant().getTimestamp() + - uploadsessions_lastlick > 5) { + uploadsessions_lastlick = getMeditationAssistant() + .getTimestamp(); + getMeditationAssistant().getMediNET() + .uploadSessions(); + } + } + + return false; + } + }); + + Preference importSessions = (preferenceFragment == null ? findPreference("importsessions") : preferenceFragment.findPreference("importsessions")); + importSessions + .setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference arg0) { + if (getMeditationAssistant().getMediNETKey().equals("")) { + getMeditationAssistant().getMediNET().askToSignIn(); + getMeditationAssistant().shortToast( + getString(R.string.signInToImport)); + } else { + if (getMeditationAssistant().getTimestamp() + - importsessions_lastlick > 5) { + importsessions_lastlick = getMeditationAssistant() + .getTimestamp(); + getMeditationAssistant().getMediNET() + .syncSessions(); + } + } + + return false; + } + }); + } + if (pref_type.equals("all") || pref_type.equals("miscellaneous")) { + if (preferenceFragment != null) { + miscellaneousPreferenceFragment = (MiscellaneousPreferenceFragment) preferenceFragment; + } + + bindPreferenceSummaryToValue(preferenceFragment == null ? findPreference("pref_theme") : preferenceFragment.findPreference("pref_theme")); + } + } + + /** + * Shows the simplified settings UI if the device configuration if the + * device configuration dictates that a simplified, single-pane UI should be + * shown. + */ + private void setupSimplePreferencesScreen() { + if (!isSimplePreferences(this)) { + return; + } + + // In the simplified UI, fragments are not used at all and we instead + // use the older PreferenceActivity APIs. + + // Add 'Session' preferences. + PreferenceCategory fakeHeader = new PreferenceCategory(this); + addPreferencesFromResource(R.xml.pref_session); + + // Add 'Daily Reminder' preferences + fakeHeader = new PreferenceCategory(this); + fakeHeader.setTitle(R.string.pref_daily_reminder); + getPreferenceScreen().addPreference(fakeHeader); + addPreferencesFromResource(R.xml.pref_reminder); + + // Add 'Meditation' preferences + fakeHeader = new PreferenceCategory(this); + fakeHeader.setTitle(R.string.meditation); + getPreferenceScreen().addPreference(fakeHeader); + addPreferencesFromResource(R.xml.pref_meditation); + + // Add 'MediNET' preferences + fakeHeader = new PreferenceCategory(this); + fakeHeader.setTitle(R.string.mediNET); + getPreferenceScreen().addPreference(fakeHeader); + addPreferencesFromResource(R.xml.pref_medinet); + + // Add 'Miscellaneous' preferences + fakeHeader = new PreferenceCategory(this); + fakeHeader.setTitle(R.string.miscellaneous); + getPreferenceScreen().addPreference(fakeHeader); + addPreferencesFromResource(R.xml.pref_miscellaneous); + + setupSoundPreferences(null); + setupPreferences("all", null); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean onIsMultiPane() { + return isXLargeTablet(this) && !isSimplePreferences(this); + } + + /** + * {@inheritDoc} + */ + @Override + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public void onBuildHeaders(List

target) { + if (!isSimplePreferences(this)) { + loadHeadersFromResource(R.xml.pref_headers, target); + } + } + + private String customSoundSummary(String meditation_sound) { + if (meditation_sound == null || meditation_sound.equals("")) { + return getString(R.string.noSound); + } + + try { + return meditation_sound.substring(meditation_sound.lastIndexOf("/") + 1); + } catch (Exception e) { + return meditation_sound; + } + } + + /** + * Binds a preference's summary to its value. More specifically, when the + * preference's value is changed, its summary (line of text below the + * preference title) is updated to reflect the value. The summary is also + * immediately updated upon calling this method. The exact display format is + * dependent on the type of preference. + * + * @see #sBindPreferenceSummaryToValueListener + */ + private void bindPreferenceSummaryToValue(Preference preference) { + // Set the listener to watch for value changes. + preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener); + + // Trigger the listener immediately with the preference's + // current value. + if (preference.getKey().equals("pref_daily_reminder") || preference.getKey().equals("pref_usetimepicker")) { + sBindPreferenceSummaryToValueListener.onPreferenceChange(preference, + getMeditationAssistant().getPrefs() + .getBoolean(preference.getKey(), false) + ); + } else if (preference.getKey().equals("pref_presetsettings")) { + sBindPreferenceSummaryToValueListener.onPreferenceChange(preference, getMeditationAssistant().getPrefs().getStringSet("pref_presetsettings", new HashSet(Arrays.asList(getResources().getStringArray(R.array.presetsettings_default)))) + ); + } else { + sBindPreferenceSummaryToValueListener.onPreferenceChange(preference, + getMeditationAssistant().getPrefs() + .getString(preference.getKey(), "") + ); + } + } + + public MeditationAssistant getMeditationAssistant() { + if (ma == null) { + ma = (MeditationAssistant) this.getApplication(); + } + return ma; + } + + @Override + protected boolean isValidFragment(String fragmentName) { + return SessionPreferenceFragment.class.getName().equals(fragmentName) || + ReminderPreferenceFragment.class.getName().equals(fragmentName) || + MeditationPreferenceFragment.class.getName().equals(fragmentName) || + MediNETPreferenceFragment.class.getName().equals(fragmentName) || + MiscellaneousPreferenceFragment.class.getName().equals(fragmentName); + } + + /** + * This fragment shows general preferences only. It is used when the + * activity is showing a two-pane settings UI. + */ + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public static class SessionPreferenceFragment extends PreferenceFragment { + public SessionPreferenceFragment() { + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.pref_session); + PreferenceCategory prefCatSession = (PreferenceCategory) findPreference("pref_cat_session"); + getPreferenceScreen().removePreference(prefCatSession); + + SettingsActivity settingsactivity = (SettingsActivity) getActivity(); + settingsactivity.setupSoundPreferences(this); + settingsactivity.setupPreferences("session", this); + } + } + + /** + * This fragment shows notification preferences only. It is used when the + * activity is showing a two-pane settings UI. + */ + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public static class ReminderPreferenceFragment extends PreferenceFragment { + public ReminderPreferenceFragment() { + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.pref_reminder); + + SettingsActivity settingsactivity = (SettingsActivity) getActivity(); + settingsactivity.setupPreferences("reminder", this); + } + } + + /** + * This fragment shows notification preferences only. It is used when the + * activity is showing a two-pane settings UI. + */ + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public static class MeditationPreferenceFragment extends PreferenceFragment { + public MeditationPreferenceFragment() { + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.pref_meditation); + + SettingsActivity settingsactivity = (SettingsActivity) getActivity(); + settingsactivity.setupPreferences("meditation", this); + } + } + + /** + * This fragment shows notification preferences only. It is used when the + * activity is showing a two-pane settings UI. + */ + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public static class MediNETPreferenceFragment extends PreferenceFragment { + public MediNETPreferenceFragment() { + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.pref_medinet); + + SettingsActivity settingsactivity = (SettingsActivity) getActivity(); + settingsactivity.setupPreferences("medinet", this); + } + } + + /** + * This fragment shows data and sync preferences only. It is used when the + * activity is showing a two-pane settings UI. + */ + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public static class MiscellaneousPreferenceFragment extends PreferenceFragment { + public MiscellaneousPreferenceFragment() { + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.pref_miscellaneous); + + SettingsActivity settingsactivity = (SettingsActivity) getActivity(); + settingsactivity.setupPreferences("miscellaneous", this); + } + } +} diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/StatsFragment.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/StatsFragment.java new file mode 100644 index 0000000..dc65aad --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/StatsFragment.java @@ -0,0 +1,149 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +import android.content.Context; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import java.text.NumberFormat; +import java.util.Locale; + +public class StatsFragment extends Fragment { + private MeditationAssistant ma = null; + private View fragment_progress_stats = null; + SharedPreferences.OnSharedPreferenceChangeListener sharedPrefslistener = new SharedPreferences.OnSharedPreferenceChangeListener() { + public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { + if (key.equals("sessionsupdate")) { + Log.d("MeditationAssistant", "Got sessions update, refreshing StatsFragment"); + refreshStatsDisplay(); + } + } + }; + + public MeditationAssistant getMeditationAssistant() { + if (ma == null) { + ma = (MeditationAssistant) getActivity().getApplication(); + } + return ma; + } + + public void refreshStatsDisplay() { + if (fragment_progress_stats == null) { + return; + } + + Locale currentLocale = getResources().getConfiguration().locale; + + int time_spent_meditating = getMeditationAssistant().db.getTotalTimeSpentMeditating(); + int time_spent_meditating_days = time_spent_meditating / 86400; + int abovedays = time_spent_meditating % 86400; + int time_spent_meditating_hours = abovedays / 3600; + int abovehours = abovedays % 3600; + int time_spent_meditating_minutes = abovehours / 60; + + TextView txtTimespentMeditatingDays = (TextView) fragment_progress_stats.findViewById(R.id.txtTimeSpentMeditatingDays); + TextView txtTimespentMeditatingHours = (TextView) fragment_progress_stats.findViewById(R.id.txtTimeSpentMeditatingHours); + TextView txtTimespentMeditatingMinutes = (TextView) fragment_progress_stats.findViewById(R.id.txtTimeSpentMeditatingMinutes); + + txtTimespentMeditatingDays.setText(String.valueOf(time_spent_meditating_days)); + txtTimespentMeditatingHours.setText(String.valueOf(time_spent_meditating_hours)); + txtTimespentMeditatingMinutes.setText(String.valueOf(time_spent_meditating_minutes)); + + TextView txtOtherStatisticsSessions = (TextView) fragment_progress_stats.findViewById(R.id.txtOtherStatisticsSessions); + TextView txtOtherStatisticsLongestDuration = (TextView) fragment_progress_stats.findViewById(R.id.txtOtherStatisticsLongestDuration); + TextView txtOtherStatisticsAverageDuration = (TextView) fragment_progress_stats.findViewById(R.id.txtOtherStatisticsAverageDuration); + TextView txtOtherStatisticsLongestStreak = (TextView) fragment_progress_stats.findViewById(R.id.txtOtherStatisticsLongestStreak); + + int numSessions = getMeditationAssistant().db.getNumSessions(); + txtOtherStatisticsSessions.setText(NumberFormat.getNumberInstance(currentLocale).format(numSessions)); + + double secondsPerSession = 0; + if (numSessions > 0) { + secondsPerSession = time_spent_meditating / numSessions; + secondsPerSession = Math.floor(secondsPerSession); + } + int secondsPerSessionHours = (int) secondsPerSession / 3600; + int secondsPerSessionRemainder = (int) secondsPerSession % 3600; + int secondsPerSessionMinutes = secondsPerSessionRemainder / 60; + int secondsPerSessionSeconds = secondsPerSessionRemainder % 60; + + txtOtherStatisticsAverageDuration.setText(String.valueOf(secondsPerSessionHours) + ":" + String.format("%02d", secondsPerSessionMinutes) + ":" + String.format("%02d", secondsPerSessionSeconds)); + + // Re-use variables + secondsPerSession = getMeditationAssistant().db.getLongestSessionLength(); + secondsPerSessionHours = (int) secondsPerSession / 3600; + secondsPerSessionRemainder = (int) secondsPerSession % 3600; + secondsPerSessionMinutes = secondsPerSessionRemainder / 60; + secondsPerSessionSeconds = secondsPerSessionRemainder % 60; + + txtOtherStatisticsLongestDuration.setText(String.valueOf(secondsPerSessionHours) + ":" + String.format("%02d", secondsPerSessionMinutes) + ":" + String.format("%02d", secondsPerSessionSeconds)); + + int longestStreak = getMeditationAssistant().getLongestMeditationStreak(); + txtOtherStatisticsLongestStreak.setText(String.format(getResources().getQuantityString(R.plurals.daysOfMeditationMinimal, longestStreak, longestStreak), NumberFormat.getNumberInstance(currentLocale).format(longestStreak))); + } + + @SuppressWarnings("deprecation") + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getMeditationAssistant().getPrefs().registerOnSharedPreferenceChangeListener(sharedPrefslistener); + + int color_primary = getResources().getColor(getMeditationAssistant().getMATextColor(true)); + int color_primary_disabled = getResources().getColor(getMeditationAssistant().getMATextColor(false)); + + /* Getting resource not found errors here */ + try { + color_primary = getResources().getColor( + getMeditationAssistant() + .getTheme() + .obtainStyledAttributes( + getMeditationAssistant().getMATheme(), + new int[]{android.R.attr.textColorPrimary}) + .getResourceId(0, 0) + ); + color_primary_disabled = getResources() + .getColor( + getMeditationAssistant() + .getTheme() + .obtainStyledAttributes( + getMeditationAssistant() + .getMATheme(), + new int[]{android.R.attr.textColorPrimaryDisableOnly} + ) + .getResourceId(0, 0) + ); + } catch (Exception e) { + Log.d("MeditationAssistant", "Unable to get color resources in StatsFragment:"); + e.printStackTrace(); + } + } + + @SuppressWarnings("deprecation") + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + Context ctx = getActivity().getApplicationContext(); + fragment_progress_stats = inflater.inflate(R.layout.fragment_progress_stats, null); + + refreshStatsDisplay(); + + return fragment_progress_stats; + } + + @Override + public void onPause() { + getMeditationAssistant().getPrefs().unregisterOnSharedPreferenceChangeListener(sharedPrefslistener); + super.onPause(); + } + + @Override + public void onResume() { + getMeditationAssistant().getPrefs().registerOnSharedPreferenceChangeListener(sharedPrefslistener); + super.onResume(); + } +} \ No newline at end of file diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/TimePicker.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/TimePicker.java new file mode 100644 index 0000000..0227519 --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/TimePicker.java @@ -0,0 +1,551 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import android.content.Context; +import android.content.res.Configuration; +import android.os.Build; +import android.os.Parcel; +import android.os.Parcelable; +import android.text.format.DateUtils; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityNodeInfo; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; +import android.widget.Button; +import android.widget.EditText; +import android.widget.FrameLayout; +import android.widget.TextView; + +import java.text.DateFormatSymbols; +import java.util.Calendar; +import java.util.Locale; + +/** + * A view for selecting the time of day, in either 24 hour or AM/PM mode. The + * hour, each minute digit, and AM/PM (if applicable) can be conrolled by + * vertical spinners. The hour can be entered by keyboard input. Entering in two + * digit hours can be accomplished by hitting two digits within a timeout of + * about a second (e.g. '1' then '2' to select 12). The minutes can be entered + * by entering single digits. Under AM/PM mode, the user can hit 'a', 'A", 'p' + * or 'P' to pick. For a dialog using this view, see + * {@link android.app.TimePickerDialog}. + *

+ * See the Pickers + * guide. + *

+ */ +//@Widget +public class TimePicker extends FrameLayout { + + private static final boolean DEFAULT_ENABLED_STATE = true; + + private static final int HOURS_IN_HALF_DAY = 12; + + /** + * A no-op callback used in the constructor to avoid null checks later in + * the code. + */ + private static final OnTimeChangedListener NO_OP_CHANGE_LISTENER = new OnTimeChangedListener() { + public void onTimeChanged(TimePicker view, int hourOfDay, int minute) { + } + }; + // ui components + public final NumberPicker mHourSpinner; + private final NumberPicker mMinuteSpinner; + private final NumberPicker mAmPmSpinner; + private final EditText mHourSpinnerInput; + private final EditText mMinuteSpinnerInput; + private final EditText mAmPmSpinnerInput; + private final TextView mDivider; + // Note that the legacy implementation of the TimePicker is + // using a button for toggling between AM/PM while the new + // version uses a NumberPicker spinner. Therefore the code + // accommodates these two cases to be backwards compatible. + private final Button mAmPmButton; + private final String[] mAmPmStrings; + // state + private boolean mIs24HourView; + private boolean mIsAm; + private boolean mIsEnabled = DEFAULT_ENABLED_STATE; + + // callbacks + private OnTimeChangedListener mOnTimeChangedListener; + + private Calendar mTempCalendar; + + private Locale mCurrentLocale; + + public TimePicker(Context context) { + this(context, null); + } + + public TimePicker(Context context, AttributeSet attrs) { + this(context, attrs, R.attr.timePickerStyle); + } + + public TimePicker(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + // initialization based on locale + setCurrentLocale(Locale.getDefault()); + + // process style attributes + //TypedArray attributesArray = context.obtainStyledAttributes( + // attrs, R.styleable.TimePicker, defStyle, 0); + //int layoutResourceId = attributesArray.getResourceId( + // R.styleable.TimePicker_internalLayout, R.layout.time_picker); + //attributesArray.recycle(); + int layoutResourceId = R.layout.time_picker_holo; + + LayoutInflater inflater = (LayoutInflater) context.getSystemService( + Context.LAYOUT_INFLATER_SERVICE); + inflater.inflate(layoutResourceId, TimePicker.this, true); + + // hour + mHourSpinner = (NumberPicker) findViewById(R.id.hour); + mHourSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() { + public void onValueChange(NumberPicker spinner, int oldVal, int newVal) { + updateInputState(); + if (!is24HourView()) { + if ((oldVal == HOURS_IN_HALF_DAY - 1 && newVal == HOURS_IN_HALF_DAY) + || (oldVal == HOURS_IN_HALF_DAY && newVal == HOURS_IN_HALF_DAY - 1)) { + mIsAm = !mIsAm; + updateAmPmControl(); + } + } + onTimeChanged(); + } + }); + mHourSpinnerInput = (EditText) mHourSpinner.findViewById(R.id.np__numberpicker_input); + mHourSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT); + + // divider (only for the new widget style) + mDivider = (TextView) findViewById(R.id.divider); + if (mDivider != null) { + mDivider.setText(R.string.time_picker_separator); + } + + // minute + mMinuteSpinner = (NumberPicker) findViewById(R.id.minute); + mMinuteSpinner.setMinValue(0); + mMinuteSpinner.setMaxValue(59); + mMinuteSpinner.setOnLongPressUpdateInterval(100); + mMinuteSpinner.setFormatter(NumberPicker.getTwoDigitFormatter()); + mMinuteSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() { + public void onValueChange(NumberPicker spinner, int oldVal, int newVal) { + updateInputState(); + int minValue = mMinuteSpinner.getMinValue(); + int maxValue = mMinuteSpinner.getMaxValue(); + if (oldVal == maxValue && newVal == minValue) { + int newHour = mHourSpinner.getValue() + 1; + if (!is24HourView() && newHour == HOURS_IN_HALF_DAY) { + mIsAm = !mIsAm; + updateAmPmControl(); + } + mHourSpinner.setValue(newHour); + } else if (oldVal == minValue && newVal == maxValue) { + int newHour = mHourSpinner.getValue() - 1; + if (!is24HourView() && newHour == HOURS_IN_HALF_DAY - 1) { + mIsAm = !mIsAm; + updateAmPmControl(); + } + mHourSpinner.setValue(newHour); + } + onTimeChanged(); + } + }); + mMinuteSpinnerInput = (EditText) mMinuteSpinner.findViewById(R.id.np__numberpicker_input); + mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT); + + /* Get the localized am/pm strings and use them in the spinner */ + mAmPmStrings = new DateFormatSymbols().getAmPmStrings(); + + // am/pm + View amPmView = findViewById(R.id.amPm); + if (amPmView instanceof Button) { + mAmPmSpinner = null; + mAmPmSpinnerInput = null; + mAmPmButton = (Button) amPmView; + mAmPmButton.setOnClickListener(new OnClickListener() { + public void onClick(View button) { + button.requestFocus(); + mIsAm = !mIsAm; + updateAmPmControl(); + onTimeChanged(); + } + }); + } else { + mAmPmButton = null; + mAmPmSpinner = (NumberPicker) amPmView; + mAmPmSpinner.setMinValue(0); + mAmPmSpinner.setMaxValue(1); + mAmPmSpinner.setDisplayedValues(mAmPmStrings); + mAmPmSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() { + public void onValueChange(NumberPicker picker, int oldVal, int newVal) { + updateInputState(); + picker.requestFocus(); + mIsAm = !mIsAm; + updateAmPmControl(); + onTimeChanged(); + } + }); + mAmPmSpinnerInput = (EditText) mAmPmSpinner.findViewById(R.id.np__numberpicker_input); + mAmPmSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_DONE); + } + + // update controls to initial state + updateHourControl(); + updateAmPmControl(); + + setOnTimeChangedListener(NO_OP_CHANGE_LISTENER); + + // set to current time + setCurrentHour(mTempCalendar.get(Calendar.HOUR_OF_DAY)); + setCurrentMinute(mTempCalendar.get(Calendar.MINUTE)); + + if (!isEnabled()) { + setEnabled(false); + } + + // If not explicitly specified this view is important for accessibility. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) { + setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); + } + } + + @Override + public boolean isEnabled() { + return mIsEnabled; + } + + @Override + public void setEnabled(boolean enabled) { + if (mIsEnabled == enabled) { + return; + } + super.setEnabled(enabled); + mMinuteSpinner.setEnabled(enabled); + if (mDivider != null) { + mDivider.setEnabled(enabled); + } + mHourSpinner.setEnabled(enabled); + if (mAmPmSpinner != null) { + mAmPmSpinner.setEnabled(enabled); + } else { + mAmPmButton.setEnabled(enabled); + } + mIsEnabled = enabled; + } + + @Override + protected void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + setCurrentLocale(newConfig.locale); + } + + /** + * Sets the current locale. + * + * @param locale The current locale. + */ + private void setCurrentLocale(Locale locale) { + if (locale.equals(mCurrentLocale)) { + return; + } + mCurrentLocale = locale; + mTempCalendar = Calendar.getInstance(locale); + } + + @Override + protected Parcelable onSaveInstanceState() { + Parcelable superState = super.onSaveInstanceState(); + return new SavedState(superState, getCurrentHour(), getCurrentMinute()); + } + + @Override + protected void onRestoreInstanceState(Parcelable state) { + SavedState ss = (SavedState) state; + super.onRestoreInstanceState(ss.getSuperState()); + setCurrentHour(ss.getHour()); + setCurrentMinute(ss.getMinute()); + } + + /** + * Set the callback that indicates the time has been adjusted by the user. + * + * @param onTimeChangedListener the callback, should not be null. + */ + public void setOnTimeChangedListener(OnTimeChangedListener onTimeChangedListener) { + mOnTimeChangedListener = onTimeChangedListener; + } + + /** + * @return The current hour in the range (0-23). + */ + public Integer getCurrentHour() { + int currentHour = mHourSpinner.getValue(); + if (is24HourView()) { + return currentHour; + } else if (mIsAm) { + return currentHour % HOURS_IN_HALF_DAY; + } else { + return (currentHour % HOURS_IN_HALF_DAY) + HOURS_IN_HALF_DAY; + } + } + + /** + * Set the current hour. + */ + public void setCurrentHour(Integer currentHour) { + // why was Integer used in the first place? + if (currentHour == null || currentHour == getCurrentHour()) { + return; + } + if (!is24HourView()) { + // convert [0,23] ordinal to wall clock display + if (currentHour >= HOURS_IN_HALF_DAY) { + mIsAm = false; + if (currentHour > HOURS_IN_HALF_DAY) { + currentHour = currentHour - HOURS_IN_HALF_DAY; + } + } else { + mIsAm = true; + if (currentHour == 0) { + currentHour = HOURS_IN_HALF_DAY; + } + } + updateAmPmControl(); + } + mHourSpinner.setValue(currentHour); + onTimeChanged(); + } + + /** + * Set whether in 24 hour or AM/PM mode. + * + * @param is24HourView True = 24 hour mode. False = AM/PM. + */ + public void setIs24HourView(Boolean is24HourView) { + if (mIs24HourView == is24HourView) { + return; + } + mIs24HourView = is24HourView; + // cache the current hour since spinner range changes + int currentHour = getCurrentHour(); + updateHourControl(); + // set value after spinner range is updated + setCurrentHour(currentHour); + updateAmPmControl(); + } + + /** + * @return true if this is in 24 hour view else false. + */ + public boolean is24HourView() { + return mIs24HourView; + } + + /** + * @return The current minute. + */ + public Integer getCurrentMinute() { + return mMinuteSpinner.getValue(); + } + + /** + * Set the current minute (0-59). + */ + public void setCurrentMinute(Integer currentMinute) { + if (currentMinute == getCurrentMinute()) { + return; + } + mMinuteSpinner.setValue(currentMinute); + onTimeChanged(); + } + + @Override + public int getBaseline() { + return mHourSpinner.getBaseline(); + } + + @Override + public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { + onPopulateAccessibilityEvent(event); + return true; + } + + @Override + public void onPopulateAccessibilityEvent(AccessibilityEvent event) { + super.onPopulateAccessibilityEvent(event); + + int flags = DateUtils.FORMAT_SHOW_TIME; + if (mIs24HourView) { + flags |= DateUtils.FORMAT_24HOUR; + } else { + flags |= DateUtils.FORMAT_12HOUR; + } + mTempCalendar.set(Calendar.HOUR_OF_DAY, getCurrentHour()); + mTempCalendar.set(Calendar.MINUTE, getCurrentMinute()); + String selectedDateUtterance = DateUtils.formatDateTime(getContext(), + mTempCalendar.getTimeInMillis(), flags); + event.getText().add(selectedDateUtterance); + } + + @Override + public void onInitializeAccessibilityEvent(AccessibilityEvent event) { + super.onInitializeAccessibilityEvent(event); + event.setClassName(TimePicker.class.getName()); + } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setClassName(TimePicker.class.getName()); + } + + private void updateHourControl() { + if (is24HourView()) { + mHourSpinner.setMinValue(0); + mHourSpinner.setMaxValue(23); + mHourSpinner.setFormatter(NumberPicker.getTwoDigitFormatter()); + } else { + mHourSpinner.setMinValue(1); + mHourSpinner.setMaxValue(12); + mHourSpinner.setFormatter(null); + } + } + + private void updateAmPmControl() { + if (is24HourView()) { + if (mAmPmSpinner != null) { + mAmPmSpinner.setVisibility(View.GONE); + } else { + mAmPmButton.setVisibility(View.GONE); + } + } else { + int index = mIsAm ? Calendar.AM : Calendar.PM; + if (mAmPmSpinner != null) { + mAmPmSpinner.setValue(index); + mAmPmSpinner.setVisibility(View.VISIBLE); + } else { + mAmPmButton.setText(mAmPmStrings[index]); + mAmPmButton.setVisibility(View.VISIBLE); + } + } + sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); + } + + private void onTimeChanged() { + sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); + if (mOnTimeChangedListener != null) { + mOnTimeChangedListener.onTimeChanged(this, getCurrentHour(), getCurrentMinute()); + } + } + + private void trySetContentDescription(View root, int viewId, int contDescResId) { + View target = root.findViewById(viewId); + if (target != null) { + target.setContentDescription(getContext().getString(contDescResId)); + } + } + + private void updateInputState() { + // Make sure that if the user changes the value and the IME is active + // for one of the inputs if this widget, the IME is closed. If the user + // changed the value via the IME and there is a next input the IME will + // be shown, otherwise the user chose another means of changing the + // value and having the IME up makes no sense. + //InputMethodManager inputMethodManager = InputMethodManager.peekInstance(); + InputMethodManager inputMethodManager = + (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + if (inputMethodManager != null) { + if (inputMethodManager.isActive(mHourSpinnerInput)) { + mHourSpinnerInput.clearFocus(); + inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0); + } else if (inputMethodManager.isActive(mMinuteSpinnerInput)) { + mMinuteSpinnerInput.clearFocus(); + inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0); + } else if (inputMethodManager.isActive(mAmPmSpinnerInput)) { + mAmPmSpinnerInput.clearFocus(); + inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0); + } + } + } + + /** + * The callback interface used to indicate the time has been adjusted. + */ + public interface OnTimeChangedListener { + + /** + * @param view The view associated with this listener. + * @param hourOfDay The current hour. + * @param minute The current minute. + */ + void onTimeChanged(TimePicker view, int hourOfDay, int minute); + } + + /** + * Used to save / restore state of time picker + */ + private static class SavedState extends BaseSavedState { + + @SuppressWarnings({"unused", "hiding"}) + public static final Parcelable.Creator CREATOR = new Creator() { + public SavedState createFromParcel(Parcel in) { + return new SavedState(in); + } + + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }; + private final int mHour; + private final int mMinute; + + private SavedState(Parcelable superState, int hour, int minute) { + super(superState); + mHour = hour; + mMinute = minute; + } + + private SavedState(Parcel in) { + super(in); + mHour = in.readInt(); + mMinute = in.readInt(); + } + + public int getHour() { + return mHour; + } + + public int getMinute() { + return mMinute; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + dest.writeInt(mHour); + dest.writeInt(mMinute); + } + } +} \ No newline at end of file diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/TimePickerDialog.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/TimePickerDialog.java new file mode 100644 index 0000000..ee7bf72 --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/TimePickerDialog.java @@ -0,0 +1,157 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; +import android.os.Build; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; + +import sh.ftp.rocketninelabs.meditationassistant.TimePicker.OnTimeChangedListener; + +/** + * A dialog that prompts the user for the time of day using a {@link TimePicker}. + *

+ *

See the Pickers + * guide.

+ */ +public class TimePickerDialog extends AlertDialog + implements OnClickListener, OnTimeChangedListener { + + private static final String HOUR = "hour"; + private static final String MINUTE = "minute"; + private static final String IS_24_HOUR = "is24hour"; + private final TimePicker mTimePicker; + private final OnTimeSetListener mCallback; + int mInitialHourOfDay; + int mInitialMinute; + boolean mIs24HourView; + + /** + * @param context Parent. + * @param callBack How parent is notified. + * @param hourOfDay The initial hour. + * @param minute The initial minute. + * @param is24HourView Whether this is a 24 hour view, or AM/PM. + */ + public TimePickerDialog(Context context, + OnTimeSetListener callBack, + int hourOfDay, int minute, boolean is24HourView) { + this(context, Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB ? R.style.Theme_Dialog_Alert : 0, callBack, hourOfDay, minute, is24HourView); + } + + /** + * @param context Parent. + * @param theme the theme to apply to this dialog + * @param callBack How parent is notified. + * @param hourOfDay The initial hour. + * @param minute The initial minute. + * @param is24HourView Whether this is a 24 hour view, or AM/PM. + */ + public TimePickerDialog(Context context, + int theme, + OnTimeSetListener callBack, + int hourOfDay, int minute, boolean is24HourView) { + super(context, theme); + mCallback = callBack; + mInitialHourOfDay = hourOfDay; + mInitialMinute = minute; + mIs24HourView = is24HourView; + + setIcon(0); + setTitle(R.string.setTime); + + Context themeContext = getContext(); + setButton(BUTTON_POSITIVE, themeContext.getText(R.string.set), this); + + LayoutInflater inflater = + (LayoutInflater) themeContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + View view = inflater.inflate(R.layout.time_picker_dialog, null); + setView(view); + mTimePicker = (TimePicker) view.findViewById(R.id.timePicker); + + // initialize state + mTimePicker.setIs24HourView(mIs24HourView); + mTimePicker.setCurrentHour(mInitialHourOfDay); + mTimePicker.setCurrentMinute(mInitialMinute); + mTimePicker.setOnTimeChangedListener(this); + } + + public void onClick(DialogInterface dialog, int which) { + tryNotifyTimeSet(); + } + + public void updateTime(int hourOfDay, int minutOfHour) { + mTimePicker.setCurrentHour(hourOfDay); + mTimePicker.setCurrentMinute(minutOfHour); + } + + public void onTimeChanged(TimePicker view, int hourOfDay, int minute) { + /* do nothing */ + } + + private void tryNotifyTimeSet() { + if (mCallback != null) { + mTimePicker.clearFocus(); + mCallback.onTimeSet(mTimePicker, mTimePicker.getCurrentHour(), + mTimePicker.getCurrentMinute()); + } + } + + @Override + protected void onStop() { + tryNotifyTimeSet(); + super.onStop(); + } + + @Override + public Bundle onSaveInstanceState() { + Bundle state = super.onSaveInstanceState(); + state.putInt(HOUR, mTimePicker.getCurrentHour()); + state.putInt(MINUTE, mTimePicker.getCurrentMinute()); + state.putBoolean(IS_24_HOUR, mTimePicker.is24HourView()); + return state; + } + + @Override + public void onRestoreInstanceState(Bundle savedInstanceState) { + super.onRestoreInstanceState(savedInstanceState); + int hour = savedInstanceState.getInt(HOUR); + int minute = savedInstanceState.getInt(MINUTE); + mTimePicker.setIs24HourView(savedInstanceState.getBoolean(IS_24_HOUR)); + mTimePicker.setCurrentHour(hour); + mTimePicker.setCurrentMinute(minute); + } + + /** + * The callback interface used to indicate the user is done filling in + * the time (they clicked on the 'Set' button). + */ + public interface OnTimeSetListener { + + /** + * @param view The view associated with this listener. + * @param hourOfDay The hour that was set. + * @param minute The minute that was set. + */ + void onTimeSet(TimePicker view, int hourOfDay, int minute); + } +} \ No newline at end of file diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/TimePreference.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/TimePreference.java new file mode 100644 index 0000000..1b6bc22 --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/TimePreference.java @@ -0,0 +1,114 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +import android.content.Context; +import android.content.res.TypedArray; +import android.preference.DialogPreference; +import android.preference.PreferenceManager; +import android.util.AttributeSet; +import android.util.Log; +import android.view.View; + +public class TimePreference extends DialogPreference { + private int lastHour = 0; + private int lastMinute = 0; + private TimePicker picker = null; + private Boolean is24hour = true; + private Integer maxhours = 24; + private Context ctx = null; + + public TimePreference(Context context, AttributeSet attrs) { + super(context, attrs); + + ctx = context; + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TimePreference); + is24hour = a.getBoolean(R.styleable.TimePreference_is24hour, false); + maxhours = a.getInteger(R.styleable.TimePreference_maxHours, 24); + a.recycle(); + + setPositiveButtonText("Set"); + setNegativeButtonText("Cancel"); + } + + public static int getHour(String time) { + String[] pieces = time.split(":"); + + return (Integer.parseInt(pieces[0])); + } + + public static int getMinute(String time) { + String[] pieces = time.split(":"); + + return (Integer.parseInt(pieces[1])); + } + + @Override + protected View onCreateDialogView() { + picker = new TimePicker(getContext()); + picker.setIs24HourView(is24hour); + if (maxhours != 24) { + picker.mHourSpinner.setMaxValue(maxhours); + } + + return (picker); + } + + @Override + protected void onBindDialogView(View v) { + super.onBindDialogView(v); + + picker.setCurrentHour(lastHour); + picker.setCurrentMinute(lastMinute); + + Log.d("MeditationAssistant", "TimePreference onBindDialogView: " + String.valueOf(lastHour) + ":" + String.valueOf(lastMinute)); + } + + @Override + protected void onDialogClosed(boolean positiveResult) { + super.onDialogClosed(positiveResult); + + if (positiveResult) { + lastHour = picker.getCurrentHour(); + lastMinute = picker.getCurrentMinute(); + + String time = String.valueOf(lastHour) + ":" + String.valueOf(lastMinute); + + Log.d("MeditationAssistant", "TimePreference positive result: " + time); + + if (callChangeListener(time)) { + persistString(time); + } + } + } + + @Override + protected Object onGetDefaultValue(TypedArray a, int index) { + return (a.getString(index)); + } + + @Override + protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { + String time = null; + String defaultv = "00:00"; + + if (restoreValue) { + if (defaultValue == null) { + time = getPersistedString(defaultv); + } else { + time = getPersistedString(defaultValue.toString()); + } + } else { + time = defaultValue.toString(); + } + + /*if (getKey() != null) { + time = PreferenceManager.getDefaultSharedPreferences(ctx).getString(getKey(), getKey().equals("pref_session_delay") ? "00:15" : (getKey().equals("pref_daily_reminder") ? "19:00" : "00:00")); + }*/ + Log.d("MeditationAssistant", String.valueOf(getKey()) + " current value - " + PreferenceManager.getDefaultSharedPreferences(ctx).getString(getKey(), "")); + + Log.d("MeditationAssistant", "TimePreference (" + String.valueOf(getKey()) + ") restoreValue: " + String.valueOf(restoreValue) + " - defaultValue: " + String.valueOf(defaultValue) + " - defaultv: " + String.valueOf(defaultv) + " - time: " + String.valueOf(time)); + + lastHour = getHour(time); + lastMinute = getMinute(time); + } +} diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/WakeLocker.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/WakeLocker.java new file mode 100644 index 0000000..5d38fe7 --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/WakeLocker.java @@ -0,0 +1,36 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +import android.content.Context; +import android.os.PowerManager; +import android.util.Log; + +public abstract class WakeLocker { + private static PowerManager.WakeLock wakeLock; + + public static void acquire(Context ctx, Boolean turnScreenOn) { + Log.d("MeditationAssistant", "WAKELOCKER: Acquiring wakelock"); + if (wakeLock != null) { + Log.d("MeditationAssistant", "WAKELOCKER: Releasing old wakelock first..."); + wakeLock.release(); + } + + PowerManager pm = (PowerManager) ctx + .getSystemService(Context.POWER_SERVICE); + + if (turnScreenOn) { + wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK | + PowerManager.ON_AFTER_RELEASE, "MeditationAssistant"); + } else { + wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MeditationAssistant"); + } + wakeLock.acquire(); + } + + public static void release() { + if (wakeLock != null) { + Log.d("MeditationAssistant", "WAKELOCKER: Releasing wakelock"); + wakeLock.release(); + } + wakeLock = null; + } +} \ No newline at end of file diff --git a/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/WearListenerService.java b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/WearListenerService.java new file mode 100644 index 0000000..ac99180 --- /dev/null +++ b/MeditationAssistant/src/main/java/sh/ftp/rocketninelabs/meditationassistant/WearListenerService.java @@ -0,0 +1,55 @@ +package sh.ftp.rocketninelabs.meditationassistant; + +import android.util.Log; + +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.api.GoogleApiClient; +import com.google.android.gms.common.data.FreezableUtils; +import com.google.android.gms.wearable.DataEventBuffer; +import com.google.android.gms.wearable.Wearable; +import com.google.android.gms.wearable.WearableListenerService; + +import java.util.List; +import java.util.concurrent.TimeUnit; + +public class WearListenerService extends WearableListenerService { + + private static final String TAG = "MeditationAssistant"; + private static final String START_ACTIVITY_PATH = "/start-activity"; + private static final String DATA_ITEM_RECEIVED_PATH = "/data-item-received"; + + @Override + public void onDataChanged(DataEventBuffer dataEvents) { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "onDataChanged: " + dataEvents); + } + final List events = FreezableUtils + .freezeIterable(dataEvents); + + GoogleApiClient googleApiClient = new GoogleApiClient.Builder(this) + .addApi(Wearable.API) + .build(); + + ConnectionResult connectionResult = + googleApiClient.blockingConnect(30, TimeUnit.SECONDS); + + if (!connectionResult.isSuccess()) { + Log.e(TAG, "Failed to connect to GoogleApiClient."); + } + + // Loop through the events and send a message + // to the node that created the data item. + /*for (DataEvent event : events) { + Uri uri = event.getDataItem().getUri(); + + // Get the node id from the host value of the URI + String nodeId = uri.getHost(); + // Set the data of the message to be the bytes of the URI + byte[] payload = uri.toString().getBytes(); + + // Send the RPC + Wearable.MessageApi.sendMessage(googleApiClient, nodeId, + DATA_ITEM_RECEIVED_PATH, payload); + }*/ + } +} \ No newline at end of file diff --git a/MeditationAssistant/src/main/res/anim/fadeinma.xml b/MeditationAssistant/src/main/res/anim/fadeinma.xml new file mode 100644 index 0000000..befa346 --- /dev/null +++ b/MeditationAssistant/src/main/res/anim/fadeinma.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/MeditationAssistant/src/main/res/anim/fadeoutma.xml b/MeditationAssistant/src/main/res/anim/fadeoutma.xml new file mode 100644 index 0000000..4c07b2b --- /dev/null +++ b/MeditationAssistant/src/main/res/anim/fadeoutma.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/MeditationAssistant/src/main/res/anim/spin.xml b/MeditationAssistant/src/main/res/anim/spin.xml new file mode 100644 index 0000000..41b66fa --- /dev/null +++ b/MeditationAssistant/src/main/res/anim/spin.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ab_bottom_solid_buddhism.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/ab_bottom_solid_buddhism.9.png new file mode 100644 index 0000000000000000000000000000000000000000..337da0f0fa5f2ab28c750bc2b13b3f4c0009ea8d GIT binary patch literal 205 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P1|(P5zFY^Srg*wIhD5l(y|IzE!GOmla1Xnz zu>m8mv4Mi|1p`Lo3me@HT)gHwI~IKmj@S9TgKbTA^`!pIV#@aw|615HAD;92#;41z zu{krQ1tdM+mu4uoI>#_+YJh5+MAE8;S<90r-6DwW89hZHCr@XD^`=@kb}s zcdjn4Kl@oLH13E%Fzc0?mowsdzPexhzEL`^auTy)!&ZKv`xrc3{an^LB{Ts5)m%=i literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ab_solid_buddhism.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/ab_solid_buddhism.9.png new file mode 100644 index 0000000000000000000000000000000000000000..9e77a28dda8e5cbc605008852e3b8862f954a3a5 GIT binary patch literal 214 zcmV;{04e{8P)!|I0iA5fSSiK zh^YkBJdXX2ShU-Py40t698>Z7CzckqtNYkC57&K+Vh?4ziCNy&S6ZL21BuC!17Ftm QrvLx|07*qoM6N<$g5}s;U;qFB literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ab_stacked_solid_buddhism.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/ab_stacked_solid_buddhism.9.png new file mode 100644 index 0000000000000000000000000000000000000000..d75b0f2936312fef839e8939751c07668cdd5fd7 GIT binary patch literal 200 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P1|(P5zFY^S`aNA7Ln7SY-Z;qHpdjFKaVgKK z&ra-NiR^JY{YC=31!+P)X3vV}xfy(I`X0vGBp+s@4sLy*(-=Hm{an^LB{Ts5XhlwJ literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ab_texture_tile_buddhism.png b/MeditationAssistant/src/main/res/drawable-hdpi/ab_texture_tile_buddhism.png new file mode 100644 index 0000000000000000000000000000000000000000..39a71de4e355106f83f29685acc33edbed2343ec GIT binary patch literal 140 zcmeAS@N?(olHy`uVBq!ia0vp^Y#_`5A|IT2?*XKOJzX3_IHHqzPOkm^|LJZ1w%h#k z3>28%M5n*_|4Zr=PyGJc^c{acXvXvf-n4vWudJ-hyh|m5X$eoPkY1zG&%f-bP0l+XkKDnl_O literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ab_transparent_buddhism.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/ab_transparent_buddhism.9.png new file mode 100644 index 0000000000000000000000000000000000000000..2be2a4791a836b390e7815a9ec93ec33cf4b9891 GIT binary patch literal 202 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P1|(P5zFY^SCVIL!hD5l(yIIIzBM4-~a#r|5XV|$^1jkJ!(uFIHY^Ul^(H9+j3A-n&B(EJ@d@H6T*NdFnGH9 KxvXFKv3>~qoUdABS)4@pE&WOn#K_h?jANH!OR>k1JP#(f)!2XHci%K YxWD8CvubY5Dxi4`p00i_>zopr06eiKkpKVy literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_check_off_disabled_focused_holo_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_check_off_disabled_focused_holo_light.png new file mode 100644 index 0000000000000000000000000000000000000000..09d155b6c79953aebf6133b0f4de15f54333f6d1 GIT binary patch literal 390 zcmV;10eSw3P)*-E+=+(^WgRG17dl0X-w zc{9^w7JWbHE|a`3lLqpEQc9_Fb|F1*11ZgK3}yvJa-b-{2JV0d;4)+?2S32e3f}t; z>wO#{TH0bJeBtL9URM(F;q>`Xdv1BT`~2EPC=87K;{fm`4nI6tJS2tUB<0^a)u z_6BHI{t>tazJYLXdH>6R3*ZBI>e~s)kubm|P4Ul_wKJb(lN==zf-jxh1FQC%h7kgE zLS^mD&F2r27Y|?nUs<~@ofGeJ)JnE1Z-5tI7gt}e99YKg?vSJ4fn8nK+W~X`R1`(` z?kL%qMWmnsQqusbX@Jx;Kx!HwH4TuO21rcGG literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_check_off_holo_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_check_off_holo_light.png new file mode 100644 index 0000000000000000000000000000000000000000..b1b52b23ab9202afe71be968c2c86d69cb2e3f8e GIT binary patch literal 242 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpUtot`d^AsLNtZ*1f|Y#`A3(B4g1 zLU++l8>dx06L#kHiX2nsn5^U_%<-b-sOfv=@_m|mO<|Q=yUr@RI&I|v*&DX5_nd`3e37}N$vnG!*~HZWjd#z)F>kG(8nkb3 z>@@B6js*-CMHFT+xdb<4a0&P_F4A-`VeMGPaMA7F5zZ5Dd8?P6Ibd_I>DIp9%52f_ o`22?E^Y_wTC1nTYgRGCwFX)n)7-_vq1n3C{Pgg&ebxsLQ0D$3Kh5!Hn literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_check_off_pressed_holo_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_check_off_pressed_holo_light.png new file mode 100644 index 0000000000000000000000000000000000000000..e5f0ddf5012044700f9214ddd4d5d43110165f20 GIT binary patch literal 423 zcmV;Y0a*TtP)fj*}~d5{#2Z0t=}NyW7Uo#+|6>tv%>_ z){pTZ0)WkCGXt;yFayB2Z6W{<;IQ3p&(w#105H|fCB_4IXLN5qx9~uhdBMmt{1-C@ zV6;>G0>1SPdyyibO%c#0djZiA8e?SV+)nRavWQ3HGNhwXOwQt6l!GjDTgs^nZJxOO*ycCEiOeT~4d_LbxYro@k zItA~&cviFD#6>`xBA`tX(547zQv|dr0@@S-ZHj<4ML-+zKXFRQv~9aO9*$?^`RwizE+QYij^6V>h-WHKHKQ9IL9TWwFL3`%PQ~v?&7G z{0o6=e~|u?$ms4I$p9eTTo;J|KG0vc`2>p3an892 RnQH(5002ovPDHLkV1ftlwow28 literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_check_on_disabled_focused_holo_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_check_on_disabled_focused_holo_light.png new file mode 100644 index 0000000000000000000000000000000000000000..50c2ee5d21585a7b6609175fe7011ce1b9f6d2ae GIT binary patch literal 784 zcmV+r1MmEaP)6I@vZk#EEm1^--o!%jD4{raFZv0351u@D@H6-k`Z*Mlo`e^~gZGLjTT3Y= zlvYY0Pd9?$l!{%R|32)8!*>^;WqFRcmNy&Y00s tX- zDHQ>TND>m%XTZ+D9klrOTfJT~ilQnd#LYAv|Nj2b(TKA%0F+W);2DrArM`>EsV`Q@ z42)}atJh0pdHHb(&3SAia$v--q748%}yXABfgIoKW9Gg11P1w zipXf%k3$S()%>Z5oD@}>g(JStg?P}V`w0Eyn`)p^EmtK+{5h}#d=Zg9c`;^YAVBW?(=m6{E$kQc*mF-Ncq$vnHz#f!%43J|jN2Y}Q2f*5E1n#@!#l zL1|H;IM47`K;QhGCEk|JLY8=w`FY?C@D`nrTq+xwSb**tftO57luf31VAp)l>I$lk zN(Pit9rQ-eU4Z5=i;_|*_K4r+BJ(k@va`6@MXx=HxtcQ|A}O#3>>EKAYhu-T%@c36 zbj@l%a!fR50Kf>?K$n7RV!;T1o+EyDO4!u7a;fDe&M|SzTo$kR^G?Uj{Ph@sToYq$ z_%m;5WCpy!a!eEvUx?aQ;tUgI#Rr}I8re!rm}pEqG`JTsCO!h6>Mk3XB7332h{%4E z@nOaXnmYLB4HP=mJ9L#&b!)k@gAJk3p*~I$`~FFp!9sAxxHR@OiWulD4Tlk%n?I{I zwx$s$NxC!~MieM*pMey;Gdx7M7T+xmhh)vg%sm2nPa!jK41A!T=58pzfzN=q z_f)36ZX2_8&xDPcqBDO2j0T=Ff!6?x+w69b>mUUf)Ssl5mX?;5%lrji{UP@1;Y)D< O0000(`ups literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_check_on_disabled_holo_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_check_on_disabled_holo_light.png new file mode 100644 index 0000000000000000000000000000000000000000..cd02122bea74a53223ec5c31f35faf9ffa77c6da GIT binary patch literal 624 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA0wn)(8}a}trX+877l!}s{b%+Ad7K3vk;OpT z1B~5HX4^3^F!p-7IEF+VemiZW-(dq0SAQ=r8L>2#I)+lFmA+CR_cg9h)#RSk9_Ezf zd}hKnrqX1Gm0DMMmT2($<_2$k+Sgg!_cty_^46Bj%g@w>ymq{CYjX-H(lzG8(%k1by&^#BePQL zXiCiWkH0yu$z>egvgpO7uLrIFx|+6%-z!{vRYb1h`P`Vmiifs+T|pB+KWZ+w(K6$j zS=62QuRu1#(#d_^h}6Vqj2epWv87tC-go%^zzmxTgk(>{5L$gxVq-` z+ubg+&2n#5Jmt2Su~u?^o|q9ZhEz*jBT7;dOH!?pi&B9UgOP!up{}8Uu8~EEp`n$r zxs{2Du7SCgfx&vy-RvkDa`RI%(<;$5m{}PcK{Q0{4_OA(APKS|I6tkVJh3R1!7(L2 gDOJHUH!(dmC^a#qvhZZ84Nwt-r>mdKI;Vst0It3DQgKV~lOkEw!8j85lhi+6_sn(CQlre@A5ue7`!yfmr zhl&zJ!3SY8t##JfSxu?+BT1_a6uY!`TH9D_tnoI6o0C1cX@TLiL17f~+TmZ@T?2QRvh_eECF@&qr#Jmv!DtT4_TPO&$ z0+QFPh%z06l>smSFaax&>}PUlgK#(s-=to)&OV#@Xiv5Q}VQ? z0tkSE%rknAB~EMlo6uRvI|BgB06qusE`SJfEGQl1V`@#w(eaJ+_Yhz!1IWifSS2i~ z?dS{#Bw&e&|qMIVtEt2o&Z)XwznVH(BIz> znVtp!tUZ0&IktDNc=6b=15RZo_^73O4e*vG83<>)=3R#+ZvqzcHvll+1x(n!efRq7*Bf6jZW9Oa z#A*%xR#9=hYjpI6N-gEKsuNv-z%T#_spO?eVwni(0V|fZxB-A+3RpF`V@EfDl~9tOg{#d$!1S!O_3KTS zFK>G>IjQM<+F}WwwcAg01Om4JtOD>pl(oW>FIs>CK_kEbplk|QDY;xfZ0+m&?9Q%T zM<#%`dGeEhalWOcYxCfsQ(_h@0r1db3HCW0ZkOLr-R4UGJE8QG=0@ztT%iKe7U=_p z{Esyrk5iT;tn2C7_Pnj_;5bA6fgqS>o10yqUb)inlJWTj6w5Q@7XU<&%DP!yr&s}O zJMr)3%Z+z8Z94SPnKSi^v$IIZGG5KkV?%$xGuqVDHYEtAN1|w)Zfa`VGCbVyQcY4o z%JS!{tCQrea?T zV`Jz6{sv{7%aI&T* zx^-gWn-$@3740w@3Zcg9{R*OpNGPNs|G2z7c+TN)cck1#0wBc&0V?U3`Z{%?tlP>$ zU5L+!GJx35Kw!jERn`5}W(&rdm!orYh%)4503nNIyw`4bcLV|&@&KYl5UACufLJc_ zg$htQNoWL65mA@lf5T(9yF)fxFw$Rvgp5d{$5@AD1!+3oJo zvSmRT>Vmacg1=T)x;vB%8-}te(vSxr6Y(w9NHTPw&_&G80Nw7fkoWt1gWa{Y(Jug3 zoDg^_D!RLF-yTtkQ?ZmdEqvbw=s*!sD8X8ZC!bu{F2DcJQ?<1*5|78a#>PgFisv-W z^W+KFw=OI-jM9y|hP-+|+Uob8=brH;#yl$uMXdps)=vqv)}-zc;R^5b?00_7Q2E*g za09ZIrvzEDe4*sCejXG8Jp!`se_feR&-locj516~w&BPZY|x@M^>uZ1kLmqW+Gk?^ z+Z_0m( jCFO<^N+_X(5_IEVzPs1eyZePY00000NkvXXu0mjf(~cO{ literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_check_on_holo_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_check_on_holo_light.png new file mode 100644 index 0000000000000000000000000000000000000000..98659d0db132677e714caa5c58148cc1a11618f1 GIT binary patch literal 1461 zcmV;m1xosfP)Z0k*yMIfKB4XX>#Os4MZc&jrI$S1Cub`AA6OI&NU-$a{*w>AR-bKH`)i@`g|?bTsk~0FF7JJk`~8?31yv<`)ki>I2B42>0;t2fx+V zZ}Z*1e;Fp>Q>=hOBv~P}_wDMt9Fze21Hid-@ZdK)u3TweipK$xi^@kX*UUh9`A^?Y zPmd$N9^{euPsnfTu2(@M}%YslLg{TPk@y z_ZK2!1#H;ZnbyHP&zl_qC|l|1=-qka#-3$C&<7>}7F@2G^L2Hn`=Zft03ve5%TUD3 z2(5`getc^lw*#=pfa;O<_5gs*0LlS4nYLU2%AW7v|5ek~t9zE`<_zPO$;$R~>;whj#JdC}Qg#p#=eO^;fo$v-6v3VcUTZVwe)f#~ zA&R$WGnp+_isG@W_g9`g!Pe{7TcfS5>F0pmcl&lrDi+iGWdO`qR0x+mo}fP*);uqg z>;{e{uWzNzPG-dl&=*usH2V9Qh6ZW(?CjT7$z+{2pp;0UVRZBh@H|q9gn|6yiVESP z#}n+yg^dV6%y1m6kO!=X5L*#t0O>EI(TPx9UEo<|rI4ZiEG;ZRqR7ht5>DsL1-Coc z6O9_k1CR*E5i8^^3D5^o3<9*5Nd8FVR>Nq`D^2DJRFd2FdW9Gh7g2mY65+C?$8yM%`{rf1172RjS0v?p^FMjUSHV$NaWA{#>OQL|X zdLOF<&~JRkul=!40VvX5LtpDNv2LFh*)JEb6DB2;P(leMlu$wm>x6#+S5CJDJz*m? P00000NkvXXu0mjfhXuk0 literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_check_on_pressed_holo_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_check_on_pressed_holo_light.png new file mode 100644 index 0000000000000000000000000000000000000000..313698a8829d46fe4c18b57cd3bb52448fd1b561 GIT binary patch literal 803 zcmV+;1Kj+HP)ll`6vzLzWB2OZa6$+%BE)b))v4+iX_;7&m>C#QKLYB=7eFl?Vd;v*!oq@3#YFiC z2vw(Rou+Z)$8ZUR&|WT=YXCg}8UV*)%K-=hoE{w= z1uTKT4WQF5S80U+esYYz{IbCVW9A;ma>A$59Dvt0MFsIiPuN1O479D4fwr|!28f7T zYc&x~%~k3MB_bY0QICjfJ9>o>=Tgdmh`2Fk%Ub(LO8M6J{jZEMS2Vs9NEAiAi;Iir z81G!+Wbm;nFU_x-~%@IVa)G6m=b07pc7`6AR5JWw%&@+S!qZ6@dUAiWOc;J0pq z_dGASyu9p{xkgkr5QgDhYwfel8O}2%Hk@jTdDK7gCRYKI4EEMx^H8i5CDuEaN(Xbc``psAJ1i5<@Q zyQbiQhPra8i71Lbt*xznYYHA{u&t<+8Y!hdH#L8%h3ZPoqNO)5O9**!9N!7Uu-5R4 z*p9L*_BYPbLmo{KvTy z9(%ud@Ws{=b1+FMOj3%;*F+0vpazZ^9Uj1?fi4!1s$>n6K%em_L!Ky6$rcV_fHf#X zzEPqVM!5d(@8^qMSbztg{FiL=3BKu@iM!<$EN^UYQ4|%D4&sy3EnlSlyeU8B@B&IyJGA^7&kz6r N002ovPDHLkV1nnQfAatU literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_default_disabled_holo_light.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_default_disabled_holo_light.9.png new file mode 100644 index 0000000000000000000000000000000000000000..6a2a92cceda58a1cba91389f6fefaf1d9999e7bc GIT binary patch literal 422 zcmeAS@N?(olHy`uVBq!ia0vp^nm}yC!3HD`7Jga>q*#ibJVQ8upoSx*1IXtr@Q5sC zVBqcqVMg6T|wK3?D;dFrt2j0EX!Qg@q+Jw zaKp=hm^Y>Q&K%EIvM@HxOk7*bsVLH+qNA2MLvkfc{SE2lZq+a8l5U zB_djytzKRed!M}ee*b1l(bpV>E1Nw%&1S~ff+c`zo+xA%O*o@8x$xu_*{w?-A5pnk zZEy8_)s(-U&tsnMl^2Y>e#~m`mD0QG*1dkcNaNfS(ftx_iEn<_u{S(Rs*7GWmuUw} z!6t=o5)ud48^Rgh8#AuHZ~0>5Tn(W4KlSD|i>CaGyXY=|%6-+18m0ij!qZb9osdyQ&=NN3)lMRVGIJl!v$^ z@!+_m5&rEq!zHb7Nh@5^3YWAZ8A%B5>Kksj=5L8SE79SI~xPVv@}YZh%MNjA_Pi z2fPDM1kzN{=)Yw3DV8&C?2e@cn$UW=CNRD6y+u=!kQ4|HP8mN*`}3xJ%;5vU?>q|P SwGgZT0000r2cxkIEG|2zMZ*|_mBgR>we)D z0p8#Z&R%8-ttC1Q5=z7#^2pcvr2S7^68yCq#EgBFT85j+s`%XnO0fe4y#{TX?N}Hka4mMJZV}mi@|x{ zEp71yF^rc3_Pi_XKWW$d%y6Sx?4(v!&;R9@3p~ZZM(j}GHl7qU`>J7@*3D`mi5E9# ztW0@d2$hVOAi_OKP3tH7B&I3*C#;yAF2FsnF_|^xR?_zH1|!y{wJ+TL=ICy4IeWI| zWG-WllcVW|;t$EzT6!m)8a_y?%+J3hC4cI;%sY)!nnK4cJQ{%k!QkoY=d#Wzp$P!n C*m->b literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_default_pressed_holo_light.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_default_pressed_holo_light.9.png new file mode 100644 index 0000000000000000000000000000000000000000..3c414bfe098ffd1cae5f5cdc1364df9fc5442c48 GIT binary patch literal 306 zcmeAS@N?(olHy`uVBq!ia0vp^nm}yC!3HD`7Jga>q<(t3IEG|2zMZ+7_mF{z>v~;} z#v^PzO)j1%nQk_)N;I?HP~Z*-QZi%}ZDM@E^l7oH)3%>?YUHYxcRgADc(i+31^eWb#7R1nPPcUUl&9|e?t1Y?f>UgJW$4*C#qANkK}EcGj@7Ie zU&j!3z~I_EACIV6d^_tx&Uj8vS?GA_-dz))Nv)on3_QiuPCE52Nm*^><~wQcap!~c zdS|Ir_rqkGmt0m@sdUnQLeA^c%Gb{;T&-aAb59VG^0~vD$TBC`^yUV$17b4|{y9<0 zsgu;Z=)w7eeQ#IHP~m1jGGF2Q&!C@Q7uKA5$XNeCL-3&1 CQiE&& literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_radio_off_disabled_focused_holo_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_radio_off_disabled_focused_holo_light.png new file mode 100644 index 0000000000000000000000000000000000000000..6589f5f6186617e19ca6533ea4441e62e3b3564b GIT binary patch literal 1329 zcmV-11$`->F+8u3Nm7esucOkF7= zx@W9z^M#C2w8WZ)5JL!E2{EhT5`A$_%(b@n=4XqLFNBcfdCqgb=f{1{Ie{UD7-EQ% z#HoG@OhX75MczaDbwgjSBkz4fUkIc{;W)4W%mULu40uA9JO(O28OQ-UK(QZWdLp3K zehzpAcp8Wx-!%Z2mV#cdG=LiLD{vFo>V-(x1kx}AybipeidBK%fuDgaP(rL80-}hA z=7B}vDTJ&G+yTCEpl~b%)aow*SAc{nx(WP zZF!;-0vCYy_3%#}xP3L1ij~I4=k~+lF(i~qz`hZs{sY^#L%>~$? zL2^dgP(B2_3!DYM2dGRBz4ohT2G%jN3HWO5HU4aAelWaZ;r?w1vq z0+xVNEAZe;_{&dD$nQtR5|U(jV13QDLxssn3$gr;F{bXj+XuRLM`g|F)9Z6RYZ*ud z$?zqhH|zynx9LDR@#xX4J2DbM!lrBGn@|~9B)O*@xjPJU_QiC7jzJzs0M8&oe_FMy zNb$^>382_%%=T)Q82*i*ZvFYA0a>EV^H9ce05pOh9hps#TQqMQb-{$(BpFBRO zAJD0xI&@8-uieui5JcclT@%sI4aCKRLYRLWEu=aeX-Gc;F0F>7nap)sWCnqVp5c0W z>pglPP*x%HM(Xz(l2n6245;Z@mg={wx*Uol31~f@*N+S7mawR8+hcuGS)nqcdIm@d z(*W{*y+Ke8WDu(-kt@BTLgT$EdHU$wVBGZEy@VpjY1*B$)_N=l( zWhH=uo^cN8J$@sgC-5cUNbKE0EVG=JWG*9@%)Ay}y(%9@>YXZ3)(ZHN{(Lj2wQQ#! zxDVVz>Y_Kahs~nN-3tki@}o$3?jkd$XOT(AR*;N90&0N`#FZ}t7mYDBU>kYtEp`)5 zx@S>kY-?YpJ33$gUb>IfDv1Z#KxiLc* zV-+2Cy$D>@{eu~+93XL758DLRfzq0kz%iu!Jvi8ED4Bl-TgI4rTGqdfgyy~)rETRq zCg36A9W54-3Ef?E;;i-j!5ZGxByEmqmVj4P#_^064-lC}hP&qxQWc~P%pf;-bGQp) z={Qmz%p<*SGnDQj341)lT`&4DUcUuAIFa$X7kc?55bIh<9>jnrb;%#J{@}Hqf{Hs}it8_{F zBQKe~yaJcX5+7dD(SDrhdV1x711j=?)uzAB%kkQz>C3-Te^>gY=lAEtNC*3ZKF29f zbW<~Cd^`TFw72c_8_TPAe(-OJ@mdr7$m_J@4C6V>7YZI7%lT{EGhH7M4^Hm|MNxQF~?8%Gy^!Gs~y(dZ^A?%HZ3%#UerR8t3U5f$lkh5&~;`w!9VV zs}H}ep*2xSZV6xaT*WmOQ>sqLon=;8C!5`RO>@c98>MlPXBb`X%(U9PdD@1@XRgEo z`QMwD&YV|Pf5-o`jN+Aii|Ym-Hg9>z^Y!_%zBiR;zOCM{=BH5xZn>xPPZU4?>KMzra_7v6?d2JJ{++7$5M&sB>CxK9 zVbQr??O%weIS@^ujDFP;*NBpo#FA923VtQ&& XYGO)d;mK4RpdtoOS3j3^P6g4#)t10!M)hLP} z45&vv)CMGg7g4fV;1uwK4?|CdfLVP#umxx~MNa@{fmEM!Ia96{wK}Hg7?9}|sj_vi z0PBp{5bzCfa;n~#5&={GUEpo>^C{qv52>D2tLERWsc9dL#}mLJ^bFM6(hTaMYrr|+ zQm@FUDZd$5VEcC{TV2YR#{KpZlDvoqO-zhCA`NL$}Ih-~wvZ+qS$B-Eu3? zvoZ>N2b}E{83Q%~-9R<4-;7d{C#FK63)qfY>I)x^Z|>}D%~V%!`*-$i4-nuOFf1b3 zC&_TmRihEA3vj?6z+MqaC3RbVfEsF#562@TUdZ+>!A05MM>Za$DHiNeP(i zTI_P5&p95{7eIrpQ{s=})c85i&)95y84ckUx9;iZNb{2JU9a_U&nk>$j1Cu#` zhU{828D@d`Oq3*#p%{S%G$Rh1&_!{#KzR(vhh8 zWQ_7~5tuU_rcEHy?rA1ajKF=nCttgdp)Q>%)Y~)iXDntqOlrt50$C;+k|qb&rtR5e<%VoVH z0R3oYZi+#Vh86A4V#dUT6kvhB0dt_Q-_ z7E>aHP7fM@m#ug^0=$ma^HE{3$vh$=X|!K%M7z7to*cVwNb@NHIPTAp{ zn_sTxCSx0FsIyi9Z?vC}7Hcg_*#`Z<8MH2X$9mX(z;h^x#xj&|1a_FLy&{r9XG|}l zla33;WEAbl4#0Rf+&~-h1d!Po1iyNociA4+?s?vI&-2oyc4f}FnCE#*fRE5xXP1Z! zCRM(VZks(m+$kojtft;Mw-9yz5+<7Zk&vc7KY}c5>i3DrP*S_EPne0O-Ut+qRUQBb zfx~?|X;=$vLNoScW0e*j9;%LDWmben^p4D*pF>F;!4O1r4?Lf=7gq1a6qzA7PW=^H3TT-;KmxF}Np z5G}Q%hEhU}A%uWIyO^;i){uLiJTWfrca=QMoH@U_bIzGF^z`)f^z`)X9|uNluxXlu z7+@S@_2&(&W36r5XQNziBm$bIfg?DHS$tUkAFo5!u!;xx6$@Bt+jiG$?@B;*e1OmJ zH4fnq+`=N3>(B{I;S^>RF+bqC@>PcRVQ2x>`6-;makTgee`DiSr|S53F^MnG;4UuX zuVFO}5(zH6LJ;~N~tCEOoI#5>Umn|A&p9${YD!RK9Vhvz+sKO6i^w_#fl9ob%I&or96Vb@xvz zfq2==Al(iBR9naKX=T z7Gr*OqsGD_-m^yn#;W0!kY_PgZM_8UNHmDwIwAsIT!}+zF36#}M&}rd2v}E+&s5N< zPHeiOJgIASA|hZ-xzC?ynx^v^4KSwEfQR-%KrJ>ml#)Lg^{xYx)%J}@k&FiM9c6b; zM~cl(R9k11Bf1co8+BqCSMU|4qZhB&QEg0Dn^y$WbVxugHrMbc&f#ce{x%#{y1L(S zJ$gYLrXP5!1ls4APAM&X0=hyF5^8$sKRQ!`AC~(@%>%Jv}`=Jw5x$zf&9X UTTG}yy#N3J07*qoM6N<$g2T&vsQ>@~ literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_radio_off_pressed_holo_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_radio_off_pressed_holo_light.png new file mode 100644 index 0000000000000000000000000000000000000000..065e49a129bef09b2d2008e92e51af1a5e7ab616 GIT binary patch literal 1574 zcmV+>2HE+EP)>oKci;iB=ra z5wcBW9A_0)crrWvtEwJ{u8!BcGfegDZj3*vE;Cb8-|Kqyetgx0OQI+W0YC#VVQ2sf zfCvKsd>9r$2cQX~E6dVfW_{XqVo?+tz$^@Nj_@{&1~mXy09IvLcDwMHY(P;I2Ebkz zQKv5J5z&wnrAbuXBAqxPDvMg=Pq$mT5qL=~L$5U6iPIwG% zbrQ21|I>hQK=&|^*H=O>9vy%a3~sgYpvz5P1oCqL-v^LfIlb+W7%K<9bhR8{p% zbb96xhfsNdVFz{sGYjXO@!o6iy#fFsgcU+`Qp$#iE|Yne0FKXw*z+zj$By zcbs!?GP5C~FN6^HrIg1)h$R4c@AsT@2j2Tz%=`)wt)!G68Dox=Qj;<-hVc4mEIrQd zz#J0~ZPPRdZQK5mnGdCuA8V~YO_Jn92(ivh{^7m&*PGBuN&LOA`Q@=lQCtDmRAF*%b2O$^V9kj!NW%(Cnc zM0C=&?XR1rIf$JfxXu7ThRE|0fHY>NwRTq5^{)Wf*=+WK);jjdU4WFb6+%4d`~Jty zx!X#qN(d2C#1R0_^ZfK|GZKZmuJ17O%`{E#UWWV#t@R>J)4R-k*fh%N4pSS2V=}5A;jOTwQu!(ADe>|03$G=L~h&mHUN{R>Cq(<(la0; zueJUZz$~m01A#L;uoWT0zDh**lO#FWK4TiR)+a>tg>&vzW{&MSv_NF^an2b4FAE_a zY>4xhLMS)x1NcE$D+VgM5%=C3W}ZtazuuYU7Dy?NnR(B9A6pH?8xXctkLAI2fQVKA zG&4u%r0ec)uN?wI6TKB7>U7@wolEU)VCETy$~8)n0N|qy5JEIWv~bSd*qPxLIOh(C zXeoq<6}h~?pv7#3l(GTvmG}Nf-uo+eJ@38p-roZ7Rah$qR$!>Fw}Obgl=5?CzSZ~r z{?1G{pzFGQW`0FV`Pqad*$E8#WYmN-P459{+P1wjA=zvNGmEb4ehOd})`)?}R0EPE zSx6~A^4|ZVX_}im^1XnjX@2Ove?uwt*9onr1<;Hx6s-(rS$0H3kK49=uj{&vdQB|4 zuA8@Q`yLTJG{ziFnF^qjRaJ4G=L$nnw^b_@Li7M0S!;i8tvwV%{8LKV?n=I{>jJ>{ zj4^-FT0e=L>H$0{%d#H*c!|hp1OUdE<1|g*XXb;tu76wC_2HB=!OWtr>%+RPf6vS} z(lmX4Vqa`A2*5*6Tve6J^IT)7OrsR*BuSnCc;KA7WvzYNTAKn`gnY5KFZSN6uIu(! ztJPc9+INZQ#2E8ImStZ~An!5A@81B=R-y|GeP*<*VvKpLl={;stJHPPbZEUsSPXu@R>E0pK)91y;Q1S21BZ?J)BpV?-=-%&;)TCv-FQoR z7U5v8!k;S)hVT5E!UlK%J%ImUARpJKOkL%LebwMRUf7pC&STB%HVW$nV|!*?+3Pm{ Y1w2dLYuMTNQL;wH) literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_radio_on_disabled_focused_holo_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_radio_on_disabled_focused_holo_light.png new file mode 100644 index 0000000000000000000000000000000000000000..0169d83fe4ad682697beec87430a7d912193f023 GIT binary patch literal 2314 zcmV+l3HA1gP)MF0ihGvHm|(%leQ zGl5=c0@{H+8dx3}1+D;BfeDn?4IqSy&^F*+U@MBO3!DYsO2NoCLO^@{hrlC1g9iFO z@K4mVaFfa8E!Ti$S#B@*b-(+8A82ADz+ZvE)kb4g1T^>#;9(8!EN~(PV~1n0;7lk~ zJzP^0M0wZ0h=8kq1z-l4J7`(127dr}K)-)81%LZm2rL5s2w($$2HrWIOd8EoQ?cRN z+6Z9!e7-!8HBGZ%nx+Hbx~|`K-5?N=Qie3x5n$?|WeMORpi`6ni+0K#MPfAs9t3`_ z2mgHv-g~O8Ej&?G)nfbo0mCpRLZQ&a?%liX=bwKbzu*6r{3>0*!cOYufFPPj~jrI$z;rn7cUx_OvV6+Mx$cq&YdC}jh41nVcRx` z4jnQ_M@P2_Ap*cBIugGGeo`81rKxl$1ilZXP>0ZOk0+B^)AQOq)1;}X>68BcezycX zolcv5eSN{f!NKa8nVH&Ru^0dhzu#YoMx#@E_wJqP>gp=QVzC=Uo_z92b98j{UMZyj zJ~?PvLEs2b4fLeo(sKC9Rse4TkD<1`w^H!0J>hU{E*OkdR8)N0-`~Grnx^4-o^kTz z$-oOQywG&v!iDdZm6hEW4u=!raQHiwm6c6_Kw#^_!b0Q4ix(@;oH^r0A`!c_wbe5W zgN}|4?~OO!m@gKKTY+LvIz8P9n@|Vj=1w?20CG(PI@R2N1eFT>DISY?pEWdWH4J0& z*=L`f-mzl`K-sBNrvfj&_+l)V%RLZ@L=v9oRpoNI!0hborhGoX$#I-=(=;n8Dk^HT z*=*JM^XCio_4V_KM8Y#oQ&d$|6$b|g4JqZ8csxFHUphSn>;|I1#{-bN9Y*7JFSI34 zd-@l^Sh}Vr449Rbl~WxZ9iXSp%P+s&FgrVYe=rz~WwY7M)6>&s^YimKj)UVk%+Jp= zJw08P$z(PMgTdJB?CkwLJv|NSblL=r&dyFMD=Vi^5f7)-BK`t(f^S<6;B5)$#oMfJ zhf*N2p-|Z8^X1#y+wD^SzP`TTwQJWB<>lo~xm<43_3PJ>^5%$3DY0#vTrRh%yu7?= zWMm}K*Vk9dooH`wxAhrPt-E}n3B`Js!MR)nOjK6s0#|i<5cK(cbKTwD0LJ9xq-j}J ztq`KwbzQ&XILmxand3MVi$%W>qS>;n+R4dD6EM2FyYcyab3jm!bxDt1t+A|$Kp3@K zOz3;RX_|#ngUgpM8{^~S)jppuTr3vLZsqxSZ{sI_fWo0Ed8<|YTux&dirSuDN=Q)@V0x6~6w(X!kD+~br?Zudc z#;|4rcZ5nxdCPgf+V)b)mGInTD|J}VZG!qpBsUR4n0(b~hQ@GPM=nRecyub=TeZw~NQf#35yZ?3++ zerEgj?Ki;bZ##gyNLy#`hCpd=-e#%%y&$Cwzx2{e0AkCQEp9TIoH7h!*z>$Qj)LcT zj$s(X$z*b>uCC4nL{Co-Qpzw;&|}3kz8Q^Wbp&)0HLPzF+9NYk%FwA(rvm!9=<4b! zw6wGgIgT?Tgea~AUI5=-Sk2IZg{zbZlyIagxZ1P zsC;M+5V>5gc3@xtK*VA(_weDvV~vfCA1*8`q&?5O&aJ1D=Xu`sg@uK5V`Jlo&ph+Y zSShI+7#JXz%hhVYbJ|%u^>{@vgq!41HyuAGL=H})r2M!$g?C8;>Q@eKUaty-| zfH-*Ypg)_<-h+~<|NTumZ2(=UMDC9%7+((Kngq@9WHJD>X+blzRM1RMPn(x6UHXck z*|B4XsHv&Bp#vPp;pwNJHb+NC6I#$*(Sqh7;1|H(f#Y{AXf%mt;4q6MWipuz0r##& zQojEB>%8*HDmi_0nw@FsBbcrppd7p%(F*s{y}i0*gp2E-j9sDs&&9 zE6zHfUz)?a`h+c&Y3>7ltiSQilopo|X+{-yA3%|sL&?A))CpcH?t=1k9qK&UhN@(j zrqVg!<{907*qoM6N<$f>lRsGXMYp literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_radio_on_disabled_holo_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_radio_on_disabled_holo_light.png new file mode 100644 index 0000000000000000000000000000000000000000..6e61b528781bd5126cf92d3c0c9f949291496f99 GIT binary patch literal 1169 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA0wn)(8}a}trX+877l!}s{b%+Ad7K3vk;OpT z1B~5HX4^3^Ft77;aSVw#{C3*e>^ZJ7$L)>JpU#_i*LTy+XKNKRZ{4_ZB{(o-!rn}O zt}4w*-Cv$9P2gYj-zi@yq+iLYC2miJK#`!>LZw9-Qon^(&R&)|E5&^FS-VQ3^Tx(< zyOt%Dy;XbZdh`7qxwL1-`ybAH|D8Ry^y=06_(hjHT^qYynAn_yHu>`eu*|pn#PY+! z!O6#?RX612iUy?}GLJ3htq3l54tIQ{&iL2N`;6^1Pp@`%5ygZ_b805keyI7f@9XUQ z%IiAbU%Ks_)?ro7;oZ(GqIf)0kiA^bOs^q>Zv+2vnfa-QJYN^hu6p^PL5XF~#EUQ9 z&p)=$L230leZNqrdp3(dOEq`Cam{}^#j|*Et>{}uy~~Fz>pp*$=+vn$KKQlKOYxoK zkHosiM^EKg2qqikS7~1kE8aXsh9jUwP|b)t-sDn{_2-xU?pnb&KbH7aB|KWOZ*NFM z&F_EO6BjFgc3WoXJoES3?1Cs}zaMiZy?(!DzNp1#TX~-=^IzMq{rzg?tle+5?w?I# zGq2u%Uoy{TY3%Lg>#WNu-{lw_QOSgY@(`9sZjJtCFz0!o@gP%gO*1UW7;l;}+rB``bZ|+@*X>gfy zU$m61Yf&<6%J-XBtfxJ%w(lB4uU8d=_2PE(lD)BVe5&*Ke~mSz=y*3?Nen-ddqI_-YaMOv+?fyGBak$6Yl>zuX^2;{rm9Kr_Ee{Rpa|_ znRu^VyGYg{`R$GV==Iw3C#Nkb+#S}NoXL7EOZKQ}-rPSwKYcnq@yhLQch}5%qPMl^ z^xS`U*X?~MeO*N8XS@0IpJ@rD3S0`ZeBp7c&Y1bBWSn8G|Ju{bpL6}}fyyYi#ohI+ z=h{AJ8yB2=)pRUjO6}?BnMRp))-Dfh?2Oib^i-R(MQ%Hv=*;R+6X*Y}FZS-e5FR6V zU(WW+Y>w%UZiPq9X20{>ocnU&{WQ;r#J3)~r{$g`KAw8;Fr$ef@2V^F93Fo)?>Ufb zwam5ro>ke^(D484e>pF&TYq}_kHhM~EUa4M8c~vxSdwa$T$Bo=7>o=I4Rs9-bd4-R z42`XfO{`2!bPdd{3=Cd;*?JL0LvDUbW?Cg~4Kr8r<^nZHf@}!RPb(=;EJ|f?Ovz75 fRq)JBOiv9;O-!jQJeg_(RK(!v>gTe~DWM4f56%&7 literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_radio_on_focused_holo_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_radio_on_focused_holo_light.png new file mode 100644 index 0000000000000000000000000000000000000000..fa5a3e067583fdc2758dd7718bb4427a615653f5 GIT binary patch literal 2204 zcmV;N2xIq&P)Fh<5k>qUI&xSb(_KVxD}LVDW&PGyzqt{_E4ta3z`f>0S?7|skcy?9>AtPKMwYMSsQ zCuiQ7bDsD4KOgV&F)&Z_G*9#NJjpTF3>!cLoXA~MUnkX-2+4iUXifk$h``H$QXl{< z0dfJadSn!c01p5Q_$Saa7hs+UfYNq3Pz}5Q_>k|CK!QmD)2)&OqQEVn5omuBAdd~8 z0agIpfQ?G9Vc=`vI&cT*MYOH~e#An>KoD4ofK31wfzLv4|Cs<#T7MPT1r#VjzW^=) zJz>L0D&ahc)=`4SfM~sGI@NpM23}FX?gJkJ7iMdXSpiVO{{YyIe7*>r4nfcBYt}3t z$<8hx_IiWBDkKIx>eVP>p}W8pprhV2hn4UfCjCD>4j_{fd#-3(=_iiz;}Tk0|USxLeMjvY*{l9UQ-*b2F?K=B&(`c{oC)~2i#lP z-~a9pFJDd}{=86uSP0|;dFr!YfpV$KQ(;*{{eJ(KLq1;-VCcGj?Vx3~*2#MnfTIrD zPC_b^eA8N>0oDQ`BnkaKY#32TGI=1SY0j1X{eOC`z1;&WMuIkXG!Q7e6b$a~Po)C! zWYP`b(lk5Y;pndF=s4`{?rukp*9b6hro7z#IxlY@5*L3|r_?VM&x0X}rzt6;1yqLJ zjU0QQg`nl7f`YAam#YdmqBOq*(fabH+S=dT(Dl9FDk@r7UsA%3ty{INYuB>D<4HZt z$;oT>`@h$>V#T^uckWyQ#sNohZ*R0!*KYvd2OuQ$yO#BCM<%gS@o3w2?o72rqf0w;b2k=sbu|HTfC|g%Yt?lPctzLsFDopo2iSnPVB1L;no34( zsvi`UB1x$W=!tl}F9N=7+iq5Z`+(f@wYBe1P*Awrn~EmX_`>iN|A1X5E>Prz9Sa zT`Vo#ulTwZ&rZZ`JxK5-kYILB#b`PJxyTvbtC%iAGVH`T@9DMez}m*f#4LmdU~OY# zqSv+q>AV#0Jirr@Qz@xrcq|Km)bkVN@5Ck%MEg#_J(5VcV>vmq(LMmNoE*SAo6qyM?g2{$tiDDcbiAnLE=)X_WY=veI3s zY1dU<6a`|6X9>`1nr0Fy-;+Rhrruz>80b_R=twFwsK{{KQxrEz25O_>({56gF)?T ze!gRs!*QdgvGG?(ZW#m~gbl-wG&3KXrrA*k>yQTL25|PVi@B4KtP@{f2jthm)mB}< zjnqi%`f_tG7x(tsNLd~)?CNSP*0g{0=jQ5GBH?e%%X3}J&({VWj`(7SBT%Cx2~ODd0^cp}il1e`S(!CjEd0>_b|>Gr+rH!&m|Q3~6YN zz1H6DL{h#l?fRdV5*0V<8u+}dEO9SCe-E%6IH+37Ex=EJ&w=oCz45di*-1#%K_AkP z2Z888%WBcZ64gUK-%G8!e!ar79w3{=k@9;ODT4=*c!{K~`@)9dAM*L$RKSmzrrF&f z{6k19`CceP89hNy)YKbdi9N`q!OXVprX5$V#HMQMhqJR2r(S;9_efL!zG<5G8{kFY zr#y|OUI9oStJuIP;FGXnxPeW;R>XCt8mk2O=2+!ZpxHFdXoI}}7IGjwow3RzAhxT` zz5q@GyhQ$-$OSy&6Sa=q{2=uA8PAX^>}j1K&YnOBQ~))K$FmtNJ_00w40qQfpdv^c*okEDiQz7Yrk5f4q!@7{zXJAm z;FD)I+)bxB7_a{gXnQW>^>k9>mjXn)g-p(ga?~RuO#Z>qjaaESG_%?%BmLk1#WYXz eG*9#NeCa>k*Cxy>gG7}80000xG8{^Gxmh5g< z#AO%WXiSKS`(YL{;Y6Yg5D=>{jBrHfz!H9z!|9>j#W@|t_@hTrx#%}(+S9&$p6C0% z&-1>|_k}F7$Rdj@vdH4?!M5H8B}ozhH{b&7=GQu)0x?;Z6YJ@3-3UmMnkB0dj6U-qn2LMl64M*^V*$PIIURs8a<6i7PvIx|SV|4*&`H8#pJ+ z@}oCSK$4^i;7ec@IM-sN#AY+_RQ?O*@B~I3Xc*}xp-Cs67-UY+~b}7o# zpePE!`=TiJDT=b3X-vY4hpfR4z@4jU-Dco!z0cE@b<_X&j%zV_>*O#m7 zeqhs5Fj#w|u<-cNix-#YdwU(vD=Hf>-`i^|yLC(bD-_yR9*++?=H?~=tt1+a4hI4O zz%Pp8fTAeLOyaV#0&XAxjCfVmiLuAKuUA%{2*u+ntEX-zaE0P=^?GIH3Dd6Av^k1# z;AL#f3IP{J+B{@+pLb1aTCldWQ@3CTfZEPZeNxkc>9$PUK3)@nl#@A(*|!7EMO}BQ z9*>pT2SD|BT#LG%T1mV4zQEch@P)8i#2XG)2&7I^FGfqC1DeNf*IbK>s#V9X#YNR) zw`=LPFq%Qte9j0~2&fq8Q=H~R-R5*o^w-yCyyPkL*Vo$%9gc}~Tc+(<^K(Y9LLi3G z&xhw+uGGxM_K%LXMUqL^Y+<36si6g*Pm3gz?z+2o+f2KfX)_F@NUbjcQ%Ma1p-VM2 zZqsorZ(<@+DhMOLS5-O5Z0Yr1YigXOf^f&|i(-Ik+6)1MR#cnSBEAEt%TDJ$46zae z<_>gpoGeTvl(P*D_UEm{g3qU&ZD_D>U0G2Mbab4=NXZy5z3g<>na?9u0ECPo^71}630+haC2l32 zmlZTYRt3$urwE#qs97T^*$9Frjl{DgrJL2$HC>Ty97&l%ny4=apC#%S za&z_HcJFpSA?nY|vi$I6V_2_il{%maWA>kQtrBGIwaOnr_glSINr$P{!mPd6a+^QL zFt*717-z|y4Rf*eB;NGZVis9skwq3+WbrofACTTJ>&58CCIA2c07*qoM6N<$g4#Q| APXGV_ literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_radio_on_pressed_holo_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_radio_on_pressed_holo_light.png new file mode 100644 index 0000000000000000000000000000000000000000..7f66e282fe4c088ce29728d8f4b4c9801c3b272c GIT binary patch literal 1908 zcmV-)2aEWLP)BS2N4M55bQt@OE4PYNQzP9_2MkndS?1p)q6g4x70g3-zD87uwkbMCA zlgY$&d8v~Dhxz%2m-S|QS>H|7LrMx{6^}3?~u!qX6)*f`d?m?~m z27s>t2u@tRqoGmlI44O`Os7*>^`n*U&{BRAmA^kJm|BO8bw60=&yCwWN#z?D0Gs3S zc%>1CT&O;x_sVCG*Yz?6yPfvWsk>%B;On6ve10iu25zh{!V{vVn(@t01C%BKk-vbu$dZTR{-a zjv;1H>$ulUJlKIc!=6UZaOs>IWLb96d;g+{L`3wVQtGzWdRHkm0{~_odGEKF`J9M6 zOGFE;_1~i?+BU}Y%Dkw;>%FG*Xz#!VdLG&=%eL}7|AB~{(OSQ2t-T%u!JblTm79FP z%55w@CD2jG_h;1r@Pk{Om*M(WHsFSAYnLN*bN<=;k!`}}E zgKcBXoQPJ&YXBf3HpVQhwYLG>^4`DTocpGT{5J@K{f?pufKHNRF`Z6*6GjJpl&@F* zCq%Rx$MMxTj_>w4oJ7QN9N&%O_)Q|(%k%ulS(a^eeZSUq007iC@;K)P^ZERWh?v1( zaMfCSXyusMIOj&p907n*Dl^8+lv0NZw4x|B7K_CdA}WT%;nf~zVg_Kx;9)b;32B;M z6p_I7 znE4l|N|2*)ikV+a(==&MT5I=+=tJ-Q1rh1mb6ACr(Z_oq0eD6!b*CNYnc37nf3~Ag zh{)NpEHAfrp)NOW1NeF^s|!r$Mx2==5!ujMf6|^W%W@DiOIZnsN^Jr;4 zBch$Yf{AEHDRqDg5|II_%C!?C0f0Ljpp?ppXy1E(AkqXuFe9Sts3?)H;5xA#NQB<| zEh3sN8}>#2qq+*#T4w-0X6CcZ{J`~;QZ5LBYeaOXtM){6CkTRT?TpOKhMCU+__&tU z1x}%=ue%6kt@TY2IaikDX8Tzj$2XNyZ=f!5kHDT%>Ww&#Z?q?iqSzFXXSLQhdK89* zLd8#ZdLazMTL7{=&o8!T>tzRdi53qVy9TDBqTE9LV4*%3%eGySbQCtGB zsAY5k11NNoBtTV(9vP9e)_GZ$VCI(r{5uGO&)P;fYc%Ke8No_G_WNsYPq;%v!rGBL8Zr#iptxqLZQ)7ig_Mu)^PKa(4?~{)NU- zC;;p%-`X5vr>E0tnIsA0%ehYK3J2hSlgVVh{9v7eGgJg>p9=GF!J+c|mCW5r1L`}e zeLQ(1T&=@e+VTJXl5gG0H+br=S=ZiDwoxDKMg8XnmEp(!OkoWeb%lva`EGqmUnx)R urv}S-YCrZ^#){8v))B_8HBRhvo6i9x_qHoRa6U@_0000EalY(fD?zVb);>0S5PW zfp<)v=|MX_DSw*w<)_o1=9+_hGmR#~@04`JsfleqG;_^xrf%EO=UW z<8tTj(4!Sk9_-VSN#62AT9@TdPI}e}i931T((|9RFgI#P^H0$`Or_BY6I(TQ{BHa%{$s&%1*S>2y{{d3 zvn(O{7k6Ff*}wNR#hH&w|KGl%i}NJcCH-{MzZ1Samw)HXSKZs_A$Fi`#xh_yGI+ZB KxvXq}Y|gW!U_%O?XxI14-? ziy0WWJ3*My{N(AiKtc8rPhVH|yWCu25+(;_j{}WlH1KqB49U3n_U1vaBL)I&59%+) zPS3KvY5wBmbb&oxc0Ruq-rlbGy69e2oWL(OZI+-H>pUg=o7lJC+SSNwU3^MWB|d$U zlhC32&HJ}%7R=w##29Aiz^Zv7x%*Ydjq^!nT?F61W9MVwQP90##EBa zyj1Sy-6oMG3apwQj$EHgChE+zQC0C&19Oe?o;;e+Z0cM5`>NjQPoAe_Lw7E}x9Y6! z$NhO%dkmx3mdbsq3(B4=oxH8sIP>W4sUq9>z!o7-RtkS&kSc+ z$1sOArbwRQ9^;$3KNC3o_&(*RpIFQzb=%S8?*y~o2W!uK;5^h^@nETidIB&w89ZJ6 KT-G@yGywq43#(`V literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_toggle_off_focused_holo_light.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_toggle_off_focused_holo_light.9.png new file mode 100644 index 0000000000000000000000000000000000000000..3c1e1d3f52008550917d14878e842884b029a908 GIT binary patch literal 368 zcmV-$0gwKPP)ZrE5Jexz1#%Ik^ch_G0O?ZY3hp^Zn3f_QEU;&&H^v{8BU{k_AP~(D< zl|R7_cugSJ2%7Uhg4BKHp`EkHfz5rDh|Vo#7Z(*bj!8;kl2VwY6ecN! zNlIaoQmB!1tyLqVW|EU9M?oH=W|EV~B&9G(DNIs|Sj^I!?Nt=BzKu`@p<Pu}PlrN$&?xNE$Ub)_qQ)g4k=?3|Ik6d86nx&;zeQ10NM;aToLT>mw5NZ##~dzK7cnxsqPYzK O0000bqW6u-e{BIKGO;Y*qQ=Vkb*q5(0&4vB$)?6a1Y>y znfd4sCn5kJbzMJ%VfeCZf!mrfE~=_plx6web={jOr001K5iJ0`0$6S9r$gFBQP{rk zFAezCDPrcX>y~ZXI=`0Hp>vXkVX#aAH=r1X!O~4VS>1vZq#y+;NI?qne32}fJSQYc zCIu--K?-u(Nc)(B#c_Q5*N&p-Ny~Gc`>!%d+fRx3AS@Ql)A7oagzS>$)}(eH%bpec!9LZ65)sUH$fD$N>-lxHLHB zz5vt!KDWNe1WpceZ70Z+4AQM2I{c6}`odjj_yI^+hla0?>{S2&002ovPDHLkV1hUN B!-@a^ literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_toggle_off_pressed_holo_light.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_toggle_off_pressed_holo_light.9.png new file mode 100644 index 0000000000000000000000000000000000000000..9f68344abd332993fe588644d47a5eedf92ee69e GIT binary patch literal 419 zcmV;U0bKrxP))RucD2 zBXZxQ;n01YB_o{_j)#7X)x+FhmN*8HYSR4xj+g^~L!lqpGU(Y&L7B5Ci}s zg0;4F&P6+yrZ3L7CN&Z1sRZ{B5q3ESU4qy+BFTkFav_pjh$I&x$%ROA5sc)tXE6qX zspQ$C5kNmCm`a{KBFTkFav_pj_IZl5oyxV@!mB1}fmMWLuWyi!tUlNs=pmy>FVP`P^=|&j8w? zm_x_31V9Ghnp5l-9{_3$ba^R&n}a;tu_BUOC}4O8snaiMqaWOT4qxx`c_6A_Q)mDH N002ovPDHLkV1iK}yCMJp literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_toggle_on_disabled_focused_holo_light.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_toggle_on_disabled_focused_holo_light.9.png new file mode 100644 index 0000000000000000000000000000000000000000..c8c5f76b21a93bc43709aea0441baadeb81da45e GIT binary patch literal 398 zcmV;90df9`P)u@iTSW42kT&>%83=2^m0-}Hq)$ literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_toggle_on_disabled_holo_light.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_toggle_on_disabled_holo_light.9.png new file mode 100644 index 0000000000000000000000000000000000000000..4144b6123fbcf326747c5b47ab4f8459254f4c2b GIT binary patch literal 512 zcmV+b0{{JqP)m}L@%ryGp*dPwrajkm3k8(_TcQb3(uyc)Meq_Zo6XLL!{H?novLc6 z^ml_3K~>*ZtJULVGI^;f(_Ua7?3}yu-ajWvvfPIx0C?|5&bey}5)4s@oI z2M?nIc}!;4ccLOf1V;(4xyOzYZgSG7D$+C^Wm%So>O!4d&*$@}@pybO z7z_qvG{4HID)Kzf7mLLcfOTD6Xk-R30&oW4$k?yU2Y@#KOH{0uKSn_cuP zaM*OwRsE?Qc)f|=7ES4dBmwo4liI(e{rZD@$l((a6Rm5Og&8#f0000#NAcKa$7o!^vWT#|TkOi~Mz)WRgS zFi9;;QVWyRA{j|PIBL%%lgWc8CxLoQGMPMhOi~Mz)IwV_Cv5Un<4P5bsT>1mgmOs@ zd;nh>fwd$H-~zaB+YWdl$o{z+r+HhBdfF=SH6^zL?b%GZ-Q_@k0lX6~+yQq$Gt+A) zutbeeH|)?bU#gZmCCP?R>Ahw5dDCRu&J(>r=`*bWu7FEIHkVlV9U+Tvz$-nXUaFb5 zoDhooYHw->N66$F`0N|t6WHF^zeQD&kjx(K;kC2^@&~=w>jugDk0dfLgz+@Q;!gOT{Hq;UnWKwH9ziixK zh&6HCCmO+g8;Q|l^zmj!f8GdAhX?1gnmr;sGANRn1W9|6&I7!lqBxyyGv?57b zktD51l2)`vve|Dj16q^GcaNe4^_bRV^4*gptw@qq#3~qXB8b9^Dj_Oha123>%10)W zJ5dOLZtwvI^_(CI3sDnEFCC{~&~IOFo*O5V>z$}7!#`V^%*g;nfV}AISlc-mbrPU> zIj+ar&LKM7-g_kpk@)M~apwg9CX?&K_Ra}IO%mSwXtH7#LzZP9^E~gpR{rbk6Sh^S zfAoXfs?$>z4N2sA-pjJ=0yPCxAf8D-o6YX$^ZDm~zwboEyc|tZH=B(wisBA{uZw%_ zGp!5Ya(`@!Er4IBsq(S~e-3He&Xgo+g#h&{NZ$UFcJ_vQ%;5=-+_ND?%xLrg0000< KMNUMnLSTZv7V1L) literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_toggle_on_pressed_holo_light.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_btn_toggle_on_pressed_holo_light.9.png new file mode 100644 index 0000000000000000000000000000000000000000..a0d649d24d9bc99ad049dcf4633d8a92b5440726 GIT binary patch literal 556 zcmV+{0@MA8P)oJ&KIg5Ddl@~d~kZbq^zCw-=atAN9$~AI?EP_E8<3+FrBnzxYM3U8& z%}f{u>oJ}d89{$5A&RPxqFZ#A1p33zp2fg1b@NmE!!Q&>q; zSV>b@NmGnQa@ez&0Y=lwcMo9%^O(_e^4()4O<^TX(Kf;8jSvDv1lM(mh)8R#tE$pk zYnT`=7?GSzCYaCXaq^hc33A*aEN$NCB9U{`c@3&^D>l(-7QN?kbzuetj6h%R4 znmTA0pms@K!Z7@qrs-$T^Cq3uZlo;BI*#KX04_~2UB@&Jzzo2hNwF9F0dPXYl$S?v ubFjbdjAA8CA%Nx`Bwl|>yZMKEo5Nqe;Mjh=;?)QM00003Rem~DO7zDH{)vjpTh>TCp?_>b?a~Q2h&}GJC_Ohs?PE zF=WxoSucVo8J>K6RxcoBWzkb{dw5K~*70B6P?Fsxq1Dje+?au8?= NgQu&X%Q~loCIF5zAl(1} literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_list_focused_holo.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_list_focused_holo.9.png new file mode 100644 index 0000000000000000000000000000000000000000..bdd137cf8409708467cd3343240d157ac20051d0 GIT binary patch literal 139 zcmeAS@N?(olHy`uVBq!ia0vp^+#t-s1|(OmDOUqhL7py-Are!QQx35FpLnB(=f#|v zJUqr5Gn^P-^6+H(w1_A&PZIs_E`0mcfdd;Py@XAE%1iZz8w%@Lim`cgD73eki!m3> m>Jgr>L_*B@gpt zeZ9QStbhZ@dZo>c1%q06Ji`9WU!YawtLAB_>=zopr0FXc*{r~^~ literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_list_pressed_holo_light.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_list_pressed_holo_light.9.png new file mode 100644 index 0000000000000000000000000000000000000000..895e51bdfbce75c9a99029f87636af33be58008c GIT binary patch literal 115 zcmeAS@N?(olHy`uVBq!ia0vp^+#t-s1|(OmDOUqhR-P`7Are!QQx35FpLnB(=f#|v z#_3Xt7h9MvUA}zYNHC~{$0O{|`~_M?zG|L^%8sEX9s(?cuyC{kcif|*Eb3_81S$-+V)J@yPBVWyvqG&GeYz~KYxJdw0eeyIoHJnOEfn# R{sUUY;OXk;vd$@?2>|r{LWckV literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_progress_bg_holo_light.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_progress_bg_holo_light.9.png new file mode 100644 index 0000000000000000000000000000000000000000..3f12166d259dcdc95934640b92dde89cb5c92ce9 GIT binary patch literal 175 zcmeAS@N?(olHy`uVBq!ia0vp^96&6^!3HF|1ZAax6icy_X9x!n)NrJ90QsB+9+AZi z4BVX{%xHe{^je@`pr?yth{nXLlQ;4*DDp6$f06$4e!a}HkLFV*1TYBY1^rNo_ENg- zVN}bRkixWsMU6poLZ;&p#s`_7&o<=8x4)cZ%Iv-?S-kZ}hPaDHmCWs5j5C4+1GOX$ R^#BcL@O1TaS?83{1ORa(Ggtrs literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_progress_primary_holo_light.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_progress_primary_holo_light.9.png new file mode 100644 index 0000000000000000000000000000000000000000..8be1726f5723454220b0690f030c4f76fd04a2a4 GIT binary patch literal 360 zcmV-u0hj)XP)zdM&ThYj6!t;6?POH!+*6*_ho8Qh%_N5uxqYXy+wU=s@7X@CG^}Mlw2f z#JJq$Uoe`z8AzxiqY1jg)c@7M4r{=YZ8{Pm^%+DRHp)0pgqXwv)(Bs#o(KiN1Ad6* zxJbs;2Q!61+~v}5gugHPd*BS5fYSh%*)ZL9pf*8mlD@E-Pqqc%1327#@#EmNvT|mK zthLrImgVzA<_?7AF5mFu&V$f${xx}8yjByA0$>b?MGvqmpXlPWd<0000iDmdwqQIfHYh1>1KusG&C(r&leBSbB5p7zZ4($%f1tH0 zmQIuXypqT(km#3dn>zkG+isFPOItYh6XLNd1OIEYB->7;NphMtX5t3((Kdmxbvb33 z-Mq5ScEHu;l+$eU3ZP%EZR+@U+g~PGHc39_@L9BD)vwk+_12%JEwn#G++a@HCNQS{ z8TzXvU(*h}R@oMeZVA$| zUQP6KRJcF=a$S?gUm^qm0AP^n|8D)6i25_D0d;7bz?iywcl!4__NTB14%08!HEH~t zB%kBv)KdSZ(wpobfSZUL%uU+_#&l>RoNf}Faz?_d&F4*o1H1Igbxj@ry@_yM#x%I4 zL(|tTWBOpIP1^*zAGfld?K%aez~@(@?PbbUlAK>&=i9qi58T$%a*tTt9u#qd`DmNK%nlWjz=nRguBqc+ zerIv!rxl@@2FHdp`v002ov JPDHLkV1ndpZ(INX literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_progressbar_indeterminate_holo2.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_progressbar_indeterminate_holo2.png new file mode 100644 index 0000000000000000000000000000000000000000..62970e3c1ff508e595efb733b937c08eca20bbcf GIT binary patch literal 862 zcmV-k1EKthP)$O7V2L4cGgybL!k3|E7JFc4gb z&wApJmPVo}!aN5cBkS*2PWIw9lP&9LKs{QavWy_+Cb= zVQ%U%yY9SKk6B|E*hfBrVd~^*j2Y*3vS}EfRA02Aj?>*i+*eD{REwPk%)`2~lyO_e z^kp87TX_=bBcDJ&b@DXEj`L1FYm!`N(>Qj&%;S`evr2N;K9<+Zj^atXTxA(<6LsuD#@xz@+SQqCx?A3BfUuS+qqT>*z1oZpR-N8S4o~lo&+AR zS~R{kEiJM}g&FJ+w8Gmza6e;i;?H=lH8F@&X3Cr_h} z>&bC$lDv%zvQO1_f$v>*cMx|;{%fDRz!&DBJ8{LQ_OXoH^4i;&2nYDKp?p%;2)9vp zu{`SJY4lBmb4r|dCc?S6*~|=R>gUt-O>tXx7N!!0dFq=Yzit}casxQjq4~ruH&`Nd z@-)Vb^MhM%+_pceqd(rhn`xH!OSkW)r7#csZpK}YVK?IjzU49bMBT-bsFSBLcAR(e zS<`-T=)*i-_j;(JY&1Ivn4fNK>lS_h$NHL2)Lkr%I(Zsn#<~8ji<{He4FCXuAC%L-0000C(li19 o05C|?2mk=UAWb6x004u&06-CaYW3w4!~g&Q07*qoM6N<$f^Flak^lez literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_progressbar_indeterminate_holo3.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_progressbar_indeterminate_holo3.png new file mode 100644 index 0000000000000000000000000000000000000000..14ab127bfec9a28f97415c1a875e5f90bf70ad9c GIT binary patch literal 970 zcmV;*12z1KP)#@I2vgY3%donurTpxRKeRdrH008KB{-Hkr0002frDy~I0AP@!5dZ*y zL5fBI000L4S2SMT+~(@$cJv$Hr7Zxoj3YozPT;vMF~*)!-_?)Lu9H=FzZ8($>UNub z=T$prDVIlV0At7%Kuu0yO6oYQSrB#${!jZYe81@7k}b_H+DF zIkasSu>tgvD}b7uz*MwF)23RARSx4ZIqi5H(+7w8;okdJNnT`EIF^;)cT2MSGFM41 zy0(`&{6d+pI?&ch?z-pO*m%+1iVaw%vAM!H0?QyLFeP;?-gmd<`BFHQSgiMFPg&gu zkJWb<-O?6~>m=({l5exCF3Upj9ud*L( zVgr_COs+7Fz;eh5Ohq}fR_dIell+ujK~)OI*GWFl;aRs+)t+H&>$`FS@#`EOxY;W> z&#sey1~&3(lE1R6NH3Fol;pSf_GfUaK1=d@_G9CdJaj;SqU4HlcELCT%O)o<6+hu=f3=apX<2|)px(<;ULbC_3Duq>mxq(W9a*>x7Yw$ZLTnmz_Q5+Ohwsu zt=6328004mZ sNYMxY0KgzcBLDyZgA|Pb000d77g!m;hbeVHR{#J207*qoM6N<$f@~4jBLDyZ literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_progressbar_indeterminate_holo4.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_progressbar_indeterminate_holo4.png new file mode 100644 index 0000000000000000000000000000000000000000..27a9019a6fa246f456e0e77ba0b54aa8eae4c494 GIT binary patch literal 1019 zcmVFK%qPUhEP^8)|AuCm~%V3xV*Lf$$7GD zp6}D^c-<_i9_#N~?D@USkF*4grQCq|s`LJJXI-85l>zKy%JF4v-nmXT4aOJM219;; z?vB>gQY@=Q#$_962^dSc0rPgbz68-}>@SIk&QYwM_DD`diGqc35`$Hpw5&j@M~_%ukcN%7<5a zpeR>1%9W0HNq$Y6z82Y}r7x14rA?=av;=c?SGgeu!SvPj&{dKjll)z+Kh35?$y&l9xG5{g!$AD4UM4I&DoUzI>my&YiRu zTwXWNYpZ4MuXNScE$w6Ks^$6U{`cURuHFDoqp!RWgJ3?oJ&E;QNpK%iZ{u|TyI9Vz z*Hlg#004joaEL20<=)ute;vC+xWX>oQJv}qpif_UAqK&G)OFDEdcA#f7;NfoobKqU z<@|arll+kT4}?<&!Kp{&d0XwnZHDye8_=RJE&Z0{pBM-SxVzja!A=Z<>FN%I^KbK5 zmkn1LU%!REfpDf2U%CU~T;+D7v5ZFiQ+fu%IXO>0&S9q9C_6p&;b?hWeM1|U!rzn| zK%ZUZh8P6X)i>ovJ(!0nH@J@}$Cth-H@4-S-YGY(nhyAWr#ePsaqm~wo%EAK4Q-uhiP8naB3sm?Ag^X~Ic9^zo&PCL@xOEn&~oFE4hMK%ZYsm-4vaPB_%a|r+{!yiZni%;f8c`y007{49c#BL0001wK%)@= p0D!GD8UX+R*h-@j004lk{s;E~!g8Pu4P5{L002ovPDHLkV1oXP@pk|K literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_progressbar_indeterminate_holo5.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_progressbar_indeterminate_holo5.png new file mode 100644 index 0000000000000000000000000000000000000000..817442025a970bef8ffab4d2f8bbe187051aa3b7 GIT binary patch literal 912 zcmeAS@N?(olHy`uVBq!ia0y~yVD1I7B{+bp zGiEoW{6BJZ)eWiBZ=M@YbWfNL)f-cE>H7M$r;ZiQeBwMwe^b4|a-F29Pck>FzMZ_& zr)X#8pM_ZsZj+BbU$gl~%%7TxrDC&f;+CCNcDTOrXUfcPThG=oT~6)^PUf?G`TBZM zeeu@ZhUuPlXCCtXxZ=8I(w{3g>t~i;{&l#))Zx-R-mFa(^Pg{r>(8pM-tyn`htETlLJu%EGC)a!a^O=1-Eunt$liTHMxM$2Ovh%$4^GWce_xDz7JV@y&%&M9BWc{0O zmceH{FRwQ}`_}tXoTsFBrRl~$<~?hFOWrEB`ONHdcwyxenfpyFf9!#lo{I6YRA>La zd8I51Fp`v|erv^-f4%aK%h_PsJFmc}Y#+qhpH2L308-*?x!N-n$z$My;vW8tZ`SpG}y2 z9T*bPc{X`vd>4OyyQ{P5&6(NvrB|_e^xbdRdT0NspZ6L>E9$p?_AEYj6Bs8+z&OzZ z#Yx!pa{itBcY1BglbS7U!53Nc-Se&3O`Dz1zpxm^gHn=N^N~*O1=Em|(p28$O?A~- zla}m$9CGhddHX6xsjZTeT^~q%W;rw4(686>$&zOh+rSCBWbW@&V3uOIH*uLD14BdH kEH@yhDpLxW=3ji3|MF!O*R@*bY@ir}r>mdKI;Vst01H^WW&i*H literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_progressbar_indeterminate_holo6.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_progressbar_indeterminate_holo6.png new file mode 100644 index 0000000000000000000000000000000000000000..6a7f5fb0a69d34ce1e3a93a9dcbed400cee12d53 GIT binary patch literal 1007 zcmV1fdA2hSuv&(*LRabpgJzaIS2mk;844X|I00000?J{Tt003Z= zK_dVF0HX{V0RR9PbvJ0dxV)M&4mfGMUSF<5VBfSW&?eU=51FcdjQ!oSMKWK1-O63Z z+x3y^HRzwE-tTfwn*Me z7uZw*_B+0t>L}*bp)=%IsN2B4-S&>srj+((md!S0>I4Mn$PFH+ZEbfleYuatcr#D( zG|7{J;0~<>woLMBeU$U11AMYR&eO#Ut?SqAWp#d*Ree5>x()26?#!1-uGi;F!Z}aZ zrnJz%1Dm$x2J+t1({H;=xtFppIbq#)AG+M@80+y^=1IQH@QC)1`XkyGNq){M(3^A@ z&ihH8WpnlvT2*F`%1q76BtN99@3XAx_D4xB(p`&*x(y7g`^;sMZt7gzy)c zzJCWcJ(L^Bdrwz?yz_mM->Y+_?fx{$ySYDLJoKH$Qa8UU=jTa2KTr^_>z8!5Y|F*- zEXik61_f{Ed6J*9O7!ZE;e#ZfOc)n%yuM5FZ|>h|e42Lqci_G{H%R2YkHv3E{>#XYKtkv0ya$CNhRdHLMQ_z3D$jl+|riS{<`Gda!v}7nJkoTUx{>M*S zEcd(qq@|z$003xAt22@1v$Xxs{`Qxpg=5oSm1=CsWq@7P{bl+7X8gy2#th{I^4`NnVxresg zsQ-zU9_Cn$Ew60L4dDM6+H#{L9*HeC;23Pn4dlJ2=UBJgSZ2LX;_@mlKYVAR zxZt$ydVRSLfqm1iK$~2fJY=f+G4^-w28{p!0MO@lHvj+tqYN4W0001KIqEP)T`s@7{OtI=SOx$905;p3x&QzG0Mtv;2mk=UAW0(t004s|jQ{`u z3|c3RFON^AEXR%RQoh>j0s#LL<1*AkJkGn)dlFoOQhHJzf^u_HtE+U8oC; zO}qeO)6YOX#N#~F)Q;;iG)WG61?U%~CYQx>(JtKwxtCR4n$%wx7@K$j#-^WvdWgq) zsHGjtr1c`nMU&)FR*7T30JZ5C`m9~jt|zOq?`Kty+Uo*i>&MG^lGFC}GF~3FkKzTm ztK0T7#$_0vc$|lt@}2(o=`6`vljL2lXRWmO9GZBtLuG z_mezH@}_<6h$C=Ux9Mk$%dj2daURNi=Y5i2z3tm-$MS6F=OmvN%jC}k?`RvIC;6SL z4E!L;<0RiED-qP|Rg&-dH(s74`7&9FfVt`VneGgSaT%r~9_Qgjk{_AA9X}>HY;Js8 zo%-2ze;v54JQCIYCm!ITl>Llx8Kxs1=b@H%+)L6pEe!wwz@S|{>QK%m)U5;8b+OW) z4NJTL52@^DjLR?`@i-5)wBu#k*;9{F|3$Iog`uapo;03jH|hdoD=&!u)joC|P50VS zOoRj6&rm;OT!!rvkMmIGJHIncJ8qf?=WMZD&7xTQ^t+p;pzZ$%HkB}3*);X`rg(A7 z4dA|R+s_!6VSM6o9%{;WHr{gMv|XwBY{N}AyS(VVulBmY*zOW9Zt@Gd2V6b9hm24O5*Y>^^Oj$soT7MzN@>WY40z&*Kyr0scw_)d%n)H-#?sE z9c$~(V|A>FIpA3G3`|FS&D*K#nsu@%7~fPIUsCbZ-QgdrrD&=}5Wvfzpa-n!1j9Xp($5azn4tU)grEm&Sdcp`u30tD|IcESZri%*_H$I2PTz0p zFDd5$)9dD$()$6tocNlrlh-v0CIA2c23^wGg7TZ(?zN8Hp@e~P)bW;VV-8>}-8|DB zO%OPq_?oYi*ELO&k6Gr$tbGIFltFNwF6wO8CkDcSm+D?X|8IL+zF^9_k1-GqaGaq$ zQymw`Oi6sr*E#B%oqeIncEbB5f8gEgs*2Lsc6b<1H?gJjcS&$!4mg%P1Je;- z^LFaGW}R%hEgzHQ-KWp_=ZEh`-2SW3*Wkc(x?ey5V|&Uo7kX?1Qxaci^h}$NUf0ym zcXc<`RsjG2SRCET0000CQZxbp05C|=2mk=UAVnhp004vj2OeyE&nE22$p8QV07*qo IM6N<$f)*aExBvhE literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_spinner_default_holo_light.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_spinner_default_holo_light.9.png new file mode 100644 index 0000000000000000000000000000000000000000..5b06f8e5f27677b1e502a2b866ba2a9a2e1fd806 GIT binary patch literal 416 zcmV;R0bl-!P)C3<0004JNklv9hwXv-1tCMXW?bf|XcUScsMH;j>&Ja$GF3#TuBI zY;N;|?pJNd%+AN`WQ#a-%3$q`*uO&w<;u_!Az4Nu%V?B#NI#6KGozBp2;>`BB+E!- z8Hp?-k!2+QuS@}}+WX#Q3Rnkr3)mP`#)}*QSHMJyQ`?qMn0+ILHt8FbWd1n+6vtCk}K;%^j`RYX`5P3%aeCOI8NoFPxd7)ZM zh<6Mm=!_RR0GiBC%`?h({`VbRx=Zb+|jHfP3pO5nP6BS zfwkCtji_VtBB#JxYLO@zFLDN4$K=JJ9#irAQ@sE#ea?*PHk}%KEP!vno?zU-*35j= zVn2;|i@7Fb$s8_Oyw2iWkSRy>Z!!O_SIIIG4&+I8>SH^UTJ8rm$vAe^_+(%J0000< KMNUMnLSTZ1OSG;4 literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_spinner_disabled_holo_light.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_spinner_disabled_holo_light.9.png new file mode 100644 index 0000000000000000000000000000000000000000..d0d94197b9cfce3ba9113d5831ed8dcf2ec0a36b GIT binary patch literal 378 zcmV-=0fqjFP)C3<00004b3#c}2nYxW zdh{zN0QM%_4OoDs@ms2sOBF{iL4U-_Z z8c0`+fxOf{rwb-Q-q%37U<~AS?f6YGA~FGQTOds_26EXtZWD}w%zMV%jY*IzJ1Wuy zlfE?zu_DFqPFIYG1Y$Lo77&1GBV-~@-igP)C3<0005eNklYE9LGNwL_+Bx;^YIk6%i>84o*ThH*r!BDILT?#KA>;3}2-95)RTAaPbu+NNF5$ zzk0U4yR=EpfcY-@f8S5OclnWA6mF%)y7HV`SPI}7wt*h73&d5M8cKjS;H3{AYkFr7 z=mJqd5Xf%4D;omSF+h^QFp>73!n6#K*FZoqu&klhz5QR>?FlRy8m-H83_cFgE>bm_=`vQ-y?yfgOI{x91cJMm|X{ zaHQjmtwfLm;0n)IN7czlA_HK<=T{|64D695(#~^1Rox^Y4>S9>To+Z5j19!=S2m1* z+*^)+g@O@~TkPFGaWzoZm=TaWV0~4;GGJsj;l=~vRncw|kV_n8KCfSqWMbeDI0rTh zv{M*HK>FlMMC3|FtpX#1^_r54=CX~&z>x+iUCY44z%g)E1qk?I%sJr`;FPT26S8XB z#{Wc)4KHT}_Q5k;toIp3$T3&;oaSkQb{6D%+(q&}FC6VwZn3H9$_&PQMpeNf7K zC<#zv!i+RTMA*M7kd32}2{Y8oPGFcsgA74WyQY>|a^>7yO%5;h4KcVk&C3<0006MNklQA0i0-03zb#U^f>>zkrK_h*Jj#ad2>OaCA3cL?~jdUqLu5 zvB z0hD`8DlozF-Jat7N(T}syPoMUU(Y)yz)XxG+I#~$V>3oqUtabmJ@1SF3xm${XBY{j z7SoYXI%h~?n6Na|^DYt5kV%!OXKcpkYNN3qY-p*1013)uGe*~*pAU+i&Pm!3v0!Y* z`p2>BPfte^A0NlTn6?0VLBB+~+Y3I&5wQbnVKyHh@1;x2x2%SIe}MBh-z$}rKw6l3 zrE-`&pIV=Vg722gzrqMWXkp&x=Gtk(M9IiU6@RD{LH-a%+vPc^3z+zdM<`Y)(OwQF bO)l~U0z$V6yKmf#00000NkvXXu0mjf#A61w literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_tab_selected_focused_holo.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_tab_selected_focused_holo.9.png new file mode 100644 index 0000000000000000000000000000000000000000..4ef83dd33095682f35fb12e650db7dcc28c680c4 GIT binary patch literal 111 zcmeAS@N?(olHy`uVBq!ia0vp^tU%1i!3HFsuehcLq|7{B9780gCZ{ws{O92~aN^K` z10U+un41lKROU85v=?R;YY3gt+Su4Ac-H5Q7W+a4ak&Z6JKIqa;R)eW8N#6gN%*hD&SNMEf<~*8}x3c)I$ztaD0e0s!Up BAk+W= literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_tab_selected_pressed_holo.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_tab_selected_pressed_holo.9.png new file mode 100644 index 0000000000000000000000000000000000000000..d2d4c5df8a00ddb98fbb9b0b58c1ea8365c41505 GIT binary patch literal 113 zcmeAS@N?(olHy`uVBq!ia0vp^tU%1i!3HFsuehcLq%1sL9780gCZ{ws{O92~aN^K` z10Vh$Zs&h#Ajrtr_}_;of+5UNjE#-$*ir$Sj0L@_V MboFyt=akR{0IY%`KL7v# literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_tab_unselected_focused_holo.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_tab_unselected_focused_holo.9.png new file mode 100644 index 0000000000000000000000000000000000000000..13d2a9a64254ff3178a072c775a25e698276505b GIT binary patch literal 107 zcmeAS@N?(olHy`uVBq!ia0vp^tU%1c!3HD^Kbl$tDI-r8#}JO0$tevD|9LnLoH%sg zz=wJ@=4L}5mAQ=%?S+}e8iFSX#!g`Mny#f*A^p}#xln>#}IRAtVKf7X5|vfa_baAXmZI| zr-PbpshtrTAz|9&lFO-KF2~RF_dL&g`SU*S^Zt6N9&V1im2{K<0N9OkLZG+Zahu*C zg>AhMicJRqc{mDT?{&3gt~e0yiGgt1EhX;tQG#dwzVA+QWUIrw^N1mPcx96@&(E6M z$=N47@QLm0GQXUSRx~r#QqwnHn*b|r9$0Wt_i)M}i}TsMjOtWp6)M$EX?VVc{>oZF zq5G6hMfb#A`@WEr_chvQ*|L4Ptz8;P;#&ihH{sB2WL@CZmaj{K-J&6cPdBaN1cH(`HtNd!) zC6jW(S1*1pMA=Mp?1gyL#nvdTGpOAVmDM+P25K~9hLPD{{(hBL*u6;BDX9%eux^|b z->~tHnsau@sGC_!`CK(~I{c)kN*w>)0Wj_C=&+vO$SP}b4+%apuX*k#4J~H6g~KH6 zE6r*&`lvWXDrhR6+5B_R)OF@411TtM1`q#)=z}J{&24}`ODB_#tAGq~J`YQ^0K4fL zrYGJ9K0uTa6|Kw{u&Q=S{R6~(AcsiCxF)kXgy{bx4k%m+_2KtP?Y{H2a zbJn)2b!yjKpoj1GsYm~?VkEh8maDR739X~5*ug;Oi&Th%+y@wj`vpThaufP2W>6YNz$aq+L{{t==Rv#C6xsy z-SHdX-iP^=y%LN!qu3&Q=$JdxMvXX+@#I@2F2y?JRmc}rVw&4Mob77|S-~()LoBt= zHkRqw*NiNxY*4l}n4FyCLY4BdbyFDz46?Ad_dGJsko`D}BNm&OKP96M7Z53di0M<*Qv~k4~ri$fz>sMM#a2{duXqT`@B#K45t3C zhKl9*=#{fYU4B|e+I9fyfF58EnviXSj>=N@O0{VgTr`cP}uTL?K5ux`t*1!%T^zXG literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_text_select_handle_middle.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_text_select_handle_middle.png new file mode 100644 index 0000000000000000000000000000000000000000..08b92590b729b4d4b34b01665f71b663f88ead50 GIT binary patch literal 1499 zcmb7^YdF&j0LK5K5?RG!V-uD8M2i~c*0zSS5K0~;cj}NGq7l|4x8@d=j97?Roe?1` zCEHv>s4bMrWwU9mAr;5R^Ywgq-}iam=lALT@MgFX@G450N&o<;I6GlI))T+3lZu_Z!<%g=Z#y%3d&Rla zi3KVRWLxP>!-3ova`EViHFUrdAXO7-JDhhFCE#S6bBbQ;8&p?!9VxgpAdgTj8EO^v zBx_Q&`Bn#){eqE_FNBL;F@nLzB8SB(#SKRFlmE=~+$J?T{J&KU&n32}54w(grsqVp zOS~uF&R%@kFS+n)hXVPT-`eW;^AuY)rQ;*6>m3rfcT-*6WvGic_^E~;#SoRkpp7aV zb(rIJPH}x3+8z`G-?oV|0}aGU?FS$x2n3?;ffl@YwJioSP*6_xv6=3*q3S3GjW=yW zpWKBdC{Q{Y%wC4MyNpLRCj^Q({_|p<+gRtTunF?_%stx=k1o6uwrGl$k=qqZg0oFW zev#b4dd+-zEj$SlW&BW(_+j#{!o4ryAAWyQOwDD|cC9deOsw%1mdZl1O)nRYxx45& z=Nm^{-xPAU=TIEge%4v%xWnZRUF_b4dEP?X&^W1koh5leOkHYvz7nrRTwgiSw{zr^ zBrNVs3XzIQcj{iUP|&pTWl4S}o;3v@$?_27?=|w2ny=JV*6u@&@-3AOtu}TWfp*|j zc?mjiAmOW{Gg6v`5?wE|;za)a@5N-hmSAZS=TuZE%tf3+Ov7MZj2EwHE|<5@WseDM zxsZgu%vi5`Ou_1zM(-$PdjV)>tDylZ)q^RaQ}k}}#ifg+b^}P@HE+fvxse}BN`G0} z?9OSm4!H>fe5iXoT#T2Jy@@Tde(0mIgbxw7Tcqg$CYG&H-fY~W3HmQ2eR91WwPs00|^ zfJ#?m4`zIx?Tn6@LRtU6+K0TyBr_mlbKyvh^mZxNqF**r9=1F0_Q5u4p`L2SobVyW zy+H^W_rw6^z>veVPlq@t(Fb`4p_^*{z;_Oe;|eiF!9hsq<&cnRqZIq3{`*nJ++|b> zDkaqXq8@Zy%}LG)D3UkS9UAgr3%+-EE!to4%(LAzX5n{QC&#R=UhAlA{1={j9JfAo z{8fY-sayzst;?AL%P9he?)Li}FCEW@+s_6E9Wr*6hv3vhz%TYPQOYc0?*;Twnlq4I zgW+(*RZL|AGJE7C%IDXIgL`SZUj~R sGB=u4aF*EnSrU)d&SC#I%+CH%X34Z27*1JX>!%Gk;|N&BVgIZD0xjE!gofuB zo)~F4OK7AVEyv=O<4w==@B8z8Ki}ie@8|o^H_5@y5+W=k3;+Pc3TNhYoR-IO1q&X# zOOV@R01!yCGBa_GD&8#ey(4Z8XZ9M9$z3E3jTxV@-DD?WkgCJ{q;pmNITg{kIdNEh zewj}4z9tS#vrZKC7oVWcy_6CgB+1+AY_p^wsK5IhMb!pxpA5alnJ`{B+Ke<T>E9O-0?!!y|h69^uP-F#?0!%xFg2kr37CS_FCdW%To46bjUUY zk1r>biv$vbBd*)mGtDXKybr&rE${x3=24T27^P=Gd^m?nSGG;DHl6@< zOwl5XeuM#3tUOMGLFp04L+{MjTh=G3>AO%hwA~%WQyyS^dA#1AVZ@oFH}Qd0f$7B} z&BO3nPnRV^+yb%dwR@s1wBc6ggP1JtQfS}~oAwDj{WeC_b8Cf{r(@xYLI7CN98*d-N+@qVPwENpWYlaR z2e&Y@x#*LM;8?ZMojHvj$=mGt$WstiG5^eOka^-TN_kBp5itrOV~t5q9sS9=Mht_i ziNQ9;Pt}9~1*=J;e!p)~GxP;z7SE?XS6r2gUUowRSHbGXK!?@wHpm*X^3zDorq>}* z^o4K!z}E2VRV=7vyxe3cuBW(dTMj8roWQqw(CA=%&tAkP)@!|{JwsoT5`@0SEQkX zSX%0l2fb1AivG)cPclb7;B#egRZh5bS%^Zn2d$A3Sq?c!wuUQ3Ci( zvg@jH&gw?&mipTJ?Pu}~E5-lZ@4vCP7aS)!hIio#!31FfWi4vd2DmQ86yO8;Upw;m zrF<|>YCM7C&j)Go`$_fbQS^W`^GA2=DN1asGn{k_RJ&@C2zuN0+I4VigCB+UOFq#S zC4L}{mRXIVMpcWX)BMwmRVJme+S~%J=VEnZ@{9baYUC7iv4sU!_)7%;>`4de{5ko& z9CaKPY5_fo?)xA|SAW7O`4OsBI)G9|k&(>DIdHK{+{-iL_nY9*gn^|nz5fPum2fx3 Vxr;Wq$vOUKz{=dttkKjj_Fo($x+eet literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_textfield_activated_holo_light.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_textfield_activated_holo_light.9.png new file mode 100644 index 0000000000000000000000000000000000000000..43b72ef7e80046e77ecfde3bf097b0df12995999 GIT binary patch literal 194 zcmeAS@N?(olHy`uVBq!ia0vp^nm}yC!3HD`7Jga>q&hua978f1-`=$5YA_IBxY%3q z|K83O%56aJLD;G)2er%a2qO98cxU<=CQj*G1k1ilr z(=DiHiG*jQn$hglY|&|xn0|Qw-mk3G?`OUL>snQ{OqJBm6MMHVxc+SA%(_XI2Pe$h svrSpjQ&aG}^@=_FBmUQD#%EhFDx4R0`Z@h)2GCIqp00i_>zopr0B!S3M*si- literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_textfield_default_holo_light.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_textfield_default_holo_light.9.png new file mode 100644 index 0000000000000000000000000000000000000000..5fa1d0315a012bf2a90a30cf5294a2b0b93b7276 GIT binary patch literal 227 zcmeAS@N?(olHy`uVBq!ia0vp^nm}yC!3HD`7Jga>q*i&lIEG|2zP%a9)odW*a?$+K z)1Cj{`q;N9u_m`hpKZ2`Zwl0JT;L*ldUtZ5d1&a=x0?&kPuyd3_d~Z!kdWs~ft7p{ zdDAZC2}JUy1yw$75c2d?QJpviBnM^Oa`D@>gTe~DWM4f&v;)F literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_textfield_disabled_focused_holo_light.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_textfield_disabled_focused_holo_light.9.png new file mode 100644 index 0000000000000000000000000000000000000000..b70db4e101a8f7e0a53a10d0b3dc0feda850ccf2 GIT binary patch literal 1208 zcmbVMTWB0r7~UizNwg`HmTKt3anc%!-I+NvyV=<>(sldL#t*labZ51q`M-3-ZG zGIP?MELws>RInOFs0x-sLF0pcSSUUivBeUIeQ3Ra*nr@bD&lHTABwj#$!_!^^ud9d zbN+Mw@B8ob?C8kQj?V7RL?W>xKdctWdXT(a`|ad=X=eRAS?A8ebzeb~_HZ>oW7UzOS)DSo7Iow>=#NA~;2>;($eDISF_NeaUXkqMV}=47 zDtJnwHk}&RM}gu62&8E?X|jDR=z}!mQ<+TW5a3wIGAzeHE(tRt&xtGx8V^OR1y)Hc zs9M7oktAvoV_#&LN~J;%*PvsO|gH3GS4YA>xsA<a`T7@Z=YGAGZlQV`m!^F+;pJr(ukq(TvTdhxot>Hl~nV5i##+C2h zw8&W9$g6|J==zVZu5~>H?p!!HbNK1{-_Kl;-(I<+cA?hY_1Yiraq5lo3-h~w=qz6? zPJQ&mJ*BR9_E67%+0r^Z(7G<4{NSb8>uo*v-k08o_YJh}TAaUaKWOP7ce@tp;e`W_ zDj()gRR>=Fb?NjHSH5|3et-S(?u&bVTN-)?&RR$Kex^)dghaP6UQrO!V1^o3*dEs6D=%Fj#fwR7>mB%d2m&&$W3 F{0G5%lraDR literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_textfield_disabled_holo_light.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_textfield_disabled_holo_light.9.png new file mode 100644 index 0000000000000000000000000000000000000000..a77d66d990371079ac3626ee54891cf0fe6e35b0 GIT binary patch literal 1116 zcmbVLO=#p)9FJJU7K?Tfp^Gdr-5yqUlJ}CCNhWqIGs$E-(9}Ae#py*%lh;n@Bri=~ zJL!nHlp+c(dg(z53JN_q(4!(AbXkxU^son^dhi2EQFqsZ3x&Px?#pzhdMG^@NZv>O zzu)iw`QG%@mBE4Y0}R6qmM8QIT`$pBeDVqUy}tC%E?tI6sYYh-JZV}XVhRqPLu}cz z7ElFQ&g#;4XpCVVpLeS@QZpx28+*K!*zmCzP&C7gjmLpyFCxOup#|5^bBAAj&9SbN z=U&U0zzj50cPCmQnrTf{?bf25bGY%B*|Auq1Rf$58+#2uQsX?=;Z^BAxfVFKV?q}5 z+_6(NbDGs~h}aAdQZ~o}HVb(urDa*Z%!&X40f+(=Q&3hVQ3ZhQJ{(mGoq4sQ8(l4W z%5!x>0#y*2%_iTJcpNSWFqg|E9HN+_7O7~}Csv&Dqmdqijv_mB1L9(zO&F~?yiD>O z_4GIdFEGs$Vn6C8il$76tw4Z05Iir5t79FJ3i{WLQ>~-wYJh|aituu1(|XL0^uRQC zXA32U)Eo7c(4|GO8alR@J>-+Jp6BQv-fUD|rFv&zRV_po!C@8S zMy~^=>zLrEjssSk$*`tnyMA&`%5xm8jzV_@IYx**wv%7gJw;zB$wo%hB@rIST{IL} zltrUh1Q{Ks0oTPk|0ibxbw)^<<3G*PyP_SKY)@LB9!`b_`E+7JIvT&-Y~QA1wNcg! z)%fQ-KNSY9fv5Ca8}W08Z{HZYyR$v;PF>Ip% literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_textfield_focused_holo_light.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/buddhism_textfield_focused_holo_light.9.png new file mode 100644 index 0000000000000000000000000000000000000000..f3df1f96ca0a8fdf41055d9466bcf956ab77a633 GIT binary patch literal 288 zcmeAS@N?(olHy`uVBq!ia0vp^nm}yC!3HD`7Jga>q@H`aIEG|2zMbjF*JL2#viw-9 zqTb%c+5V4ay{=?)jtLZ(Qhm5xL?UX|ndpf@R{ds64wOH5#D2Wb=3Cvz2Ky<~JRB$K zsA#rmw3o?9O-fPp6hkAfdi**W*Sa!It-SxI`8HNR2C167MeG-18^x_{43GD#>=&Qc zYdGKMqNL@s@^WDb^DFzNJdyD(x=}X!#qPE%GT}#?i|1V4$*LFKd1OVB+Uf~Dk?(## z6FZ<>c4^X^kMkeOG==@^4{%*`T17Z%%KS~b&ko%Yt7Xm4)M^MSbf~y{_s^kUj~3OO bdC2?gllC{&39*xbUS{xg^>bP0l+XkKIZSzL literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/cab_background_bottom_buddhism.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/cab_background_bottom_buddhism.9.png new file mode 100644 index 0000000000000000000000000000000000000000..843d8aba56462405d12d1ef5af7c1e3399983eeb GIT binary patch literal 207 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P1|(P5zFY^Srg^$JhD5l(y>XDYK|#RfqUuK8 z=nX8VH+Y=hz!JTISJ*{Wru4bPruOqw4fEt4J5H)yAG7VU|FYBHK3__fe8+fbO`&Z( zFI(|E&lY+FvzHBzgfN==9~TH_y<#H^ zme`uS^UsG>{ol?8*Ig9{OW(Ij6MJ2^CdMQF#Hk|YJN!x)fi7h5boFyt=akR{0F=*9 A(EtDd literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/cab_background_top_buddhism.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/cab_background_top_buddhism.9.png new file mode 100644 index 0000000000000000000000000000000000000000..9be957e760192eea673c27597e938f7d4cd93b40 GIT binary patch literal 207 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P1|(P5zFY^Srg^$JhD5l(y>XDYK|#PJ&@<<- zn9e~Xol8bK2gPy@vrKQ0D}C;;sr~#^#dZCb6WiWT&9(lUvMc9$|2c0-g>zQlmK{tu z=k0ig^XoAIXCKjk&m}yDp$=y+8y*Q^H1$6&5X^eTMixn8dtYjGNMQfBv%z&&zYAJl xH@x!u#+KNxwLJ&tgiFPrsZ$9#o-?n6*(I!qdGGx1DL@x8c)I$ztaD0e0s!pnQQrUn literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_accounts.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_accounts.png new file mode 100644 index 0000000000000000000000000000000000000000..2282659e635262ea84e4c2181f4be42248268809 GIT binary patch literal 621 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-s+XH+;T!HleAqWJzR(b-RZd(%M z7tFxK%)-je!^wz591@$JS6o-$+}1u}%CzY-=FVTRWck_+ z+jj2Wv-jYkW5-XPI=fY5?_vf9Mh#CF#}En0w+CNGF$PMoT@Zh)BXxY{ruI&e#DH_} z|Hg;ExixwDv&;YDvmeSAecg6_)v`qO%QIyvw{d1~cyLbAx~1~Zv%2%%fvnf>ew>{u zd3{Iqq}2xt&fYlFsAH`Da|UZy^08eLN*(r`2{mDGBLAoaB^|+ z@{5W~$jYmzs%se-nOj-g+S$AL1%<`OCnTq)rsWhA78Vtkl~+_&*EY3ucK7y8oHTXX z^cl0V_f5RQz`&^C>Eak7A^G;;^{_(@BCHpLtyo^F2C9h&Zd`E5`uYF=UJ`RpT#A`f zepmYcgjFVcsubC*KR$bLU~=ht4(_F#&cE}d_V2v;@s3IV>2*KP-Z`rJRQ9B6{f4BB zISo2?ik0(OHl63$s*pV?Mx}7d?F$i06{RM=ah5iE;yB4_f{a6T!U}%RR`=C9eRp)7 zgFU2dDo-)K)83yW!(o#(`{Cnh>DxFtUiEBgS#rQbf5MS#J(t>69M?$g=&Jr_QmpXW zsHsWEIJJdg)1NtlA}Q}?0Ey0PUB`Od8n`dryIZn3df(R5eTx6p0)7!ctl zL4Lsuj7-cdZ0sCd+&p{&!XgqfvT{l)I))Zj4o)tvZtfnQULm1jQSnKs>BVK`Rn@h1 z4UH|WZQVV+lcr3aK4amcWh+;$Ub}AnhK*Zy?%uQS;Gtv3Pn?MQ+pdtYe#MUi~%7{`Mw) zZtc07zhx&b{1>=+bDXieRln21*IWCAc24M6k`U_RwDX9A!r|JO5Z)}WN8eM}n4&M- zyUlpxX7=H04hhrs-hT7sU6wqtVGh$Cn>!Kb8RmE?2zj%AbrGDUI{VwrqzD%$ZuRvE z(`N;gL@Kd5RKC+rh%0>+Rmj*QR*>{(O_BV9)E#e?_^01}+9$(Yx&6;Zo&L$ThN+Ha zKGWAuayQGdcyzj5=I6h99q*RZb=*6+jV*%x-J)Hw zF00nOyd}O$u#nNHYQZAbU(-w;_slMR;KVG$aAonYegsgW*lDj?@`~hDc;#8 z%WbwFdoCN>|2xBOF>8#*`?q%`7o6IY+z|B0Zc*y&?@m>}s$EXMQ~q_B<(|~`IG+RS z&;Ge|q9!_3Y5Bgh5tRnX_sib@Za2CT|AJX{bM}fI|5xn;#xaAZtDnm{r-UW|xM%YQ literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_brightness_low_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_brightness_low_light.png new file mode 100644 index 0000000000000000000000000000000000000000..9ce5da1833337081e84cf143a2882d62702764d3 GIT binary patch literal 768 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sZv%WnT!AzkI5;>M8yjnDYpbZJ zC@3h%$jCsr=H})QhM}RMo}QkLjt-Eaudfee8yFY>*(N3?Kn75ak&zLQ3uHrNA#5NC z6bGsSl0X3A0!d``a4Dc(AOK2109+YRJ46I-0+4|$2;>44Ad|>kpg0h0zUu>U&)17oqLi(`n#@wZdonlm|y z9D852(lf<*#T1QGN=l3NY+0lG&5R+-gtB@T ze)D~mV>o%!62=d|3LfucxFDcCRrA~{N!=G)YuVCga|(9m&)L^>|DEIM0vE=HbFb1B zYE9QkdrCeu-)*&ByJJE2>s=mqH?Ezme`o0t2aT7U z+oPK9w$=uFo<3M{i+PsRA;pID*XzGlD*oBJ>dr>~-M`vbKcDI-wfE?SOFt?Wzy8Vb zsQYWR@J#USk3CzvycY|;o#Fnan{$ut-FCyq6=t8EmAiAMM!NT& miD)%=e4Le9OOWfW8O2?kAelF{r5}E)T=oxtc literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_chat.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_chat.png new file mode 100644 index 0000000000000000000000000000000000000000..d1c182d3d31f0c620eebf6507b4fb0ecfc74a009 GIT binary patch literal 302 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-s-T^)#u0Z-fl|b`MZg!w?k|jZY z!3>N{%v=K62G%Zq{y`zdWz`*vcI@7F-63+2En6pd%POUHx3vIVCg!0R9t~DF6Tf literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_chat_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_chat_light.png new file mode 100644 index 0000000000000000000000000000000000000000..7118f293fae4c9299c343d43a015f86b466ced63 GIT binary patch literal 297 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-s9sxcfu0R?BR8&;7wY3cl42+D7 zOiWCGB#;ec7=i(i3uge?KwxZajLfLM%3cRFNTMXjFPMRmiJeD5MaS66+Ri>KGB&NM ztG9phv{_dk1@!>cRCu~LhIkx*d*wD)gMxr-;O=zu&6ocD_itWwMzOf5GW*)+n@t>C z2PGEnaXGneL7ZXRljsF^`G&`bXNE6UH^^1LoVsoho&gk-V+XK z&u8B0yS2r?aQZ&6M-`?nRa)K)f~@tY9x!UYFR^sLE!!HkIL;kK=YZ*Bv!{z=NJZS+ z%UAm!8webDDCs=c>h6~Eokow1jOC3%;NSD*YlK#N%~kte#{b(k>Q}Ful;l6}+dNc~Q)TnQSfvb^q0NUbg?=ZcpLd+T=AZ$KD8GZH#WBMvTZ2L!!-9C!`Bpz@aR{Ha(?s}3plHvn z7prXPlB_>#wAJmL#HGir zf1~j0tklS|q=fMN1No~Sh%Szspwf}?<_hZ*J&kS~8-w@0jYd62Iv$giN;+qU{XZbU zUwdCS&^#l+LGobahe$8GZ5)-4SeGt$d6>3zGuPf}^Y?2U@_xvYJ#**v%Z1l(zbxlo z@V##9*MpI*wR29?t#Vp%=DEI6Z*)rSQ|*@7zm8qxHQ)|hvM>6@f-;#!KNV*RUzsd$ zb;*JVg{|`iZuV%*$aWUEdqCgu^auSq@qa(!w*6(D)nVxB!aDsEFflQBy85}Sb4q9e E0GQyUy#N3J literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_downcloud_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_downcloud_light.png new file mode 100644 index 0000000000000000000000000000000000000000..283f20a830fc4ad8da64a6f216c8431fc855bfbd GIT binary patch literal 1814 zcmbVNX;2eq7!HS`prRlu%ILCCQ3%=HT#z)8CfP(%5=01)6m`h4LWE>PvXBHkAnJ(L z3&m0u#@i98DB^)Y6$eVCw4zckJU~TlsRsz-HCDS(u>IlqqdT+vUGMWe@An?FtK(v4 zkM^AGNuf|iOQX?va)h1lh~eZn+4a>ba_}d_N+JPYNLbZoj3UtC8Vryc)M;2erqY86H4EU`xFmrABh-M+kZH7VZG7-OFPEGRCZ$f17 z!4FO;<#B)rH)8;c28U~5HVm*48p2>kL_|;lI*h;&OotG9I1<5S(77-S3_c*KX4Wm_ z#-ox!Epo*N(+R@Fg&?cdO0zO(xH%0%I2?|XgH8`8Ey68!BcZm18!bUY3@B#Nn)N0^ zj~f9eqgsP!6MT^L^urYlCb|40vC%RZC^BS_O>Ke@8Vnf>&U?MLwh-~yzixce+M=+V zFeo0g;Mry^nU94*Ltrv?pBHi(lHPFVnDt~*)R`!*%{E|0LW=T1@`R?->$pOg$rdsr zV5XQ3vm+6NLl?p#0h=R61WXoFz!~EB6qdISFBrHUNAYvqv$q`Brj({PiGer!6 zUxL@UvL1$c(88+^oRy%%KX1OUDV^l8&1IQ34A{)*E%W)#6Of zhr6PfS)YUHBxc+IypJwd{|R*zMuif(P$-BL3&jY62v8v!35!{Dj)WuPFi~(2tNT9@ zgGgr}XKDPWRED<5`g2Y{7CyQ7*gBYz>=!fH80@9{y2*ZvmZAcMt>e+QmW+hCtqx5wAG^|Y^adn~-^=~?@SWE{12?7Y|0YRvZ}0qpf&A*e}t$`q2dM^Wxb z7?;(o*}ixBy3T^9g2naSw_cd>;Wm$@dxIa>y{LOwns@%k^2Bn5rYy5hxhf?X@EJR@ z(EZqzP3m_SP8jSe_bZP3Z&VYyJ#5|!92;swN?Y&ucy%?sp}IZKH>A=wE{beydwn)% zqeokVq4!W3Z{x7pr+S9P9!s)4p;R>3d)H`69LyPx!vo58_kn!hQ6s^+lPL1xh*qbNScs0vIsz&9Gpg#DeqJt?ihVkPb^prGYo?hmYNe@qDD3e2UZ|diE zb(cN4*s`6sGQg!(<~iwyuNAkRm)NU1iz#*+$}0!(aD`pYr)F= zeVo$aikw{wl4M(!ZkqDM^$3PrJUI zQQ47pWb^p>VNouz{Y&OgJyQSdQcOdncW9{LoGUxko_zInjOAtIy(P)gyA!Ek=<*W( zsYcoFW45*(Sd;I~Ys)!)ksW&bO;gap_%BY2q2P}02f-~%4;%>n%II6EFswXu)IF~% zuS-WJ}A zAa)jgSyn-4zgv0!dg$NlS8s~h;J+pmY-&8C(iT^yIObKzHqIJzY%+CVM1|*$x`NHG zS~@h{vZ7H%3K8#-EbEzgLt^oX7n4NMN&Uq$T?CM|^=6r5=5454+^xzDyfVhMlr|6$ zvgKg)=E8>7u0t2Y!ycV1K4Ccgb8FwVcN6Q@XZOQPP2H}n&cK$m zh;51cr&O(?+Vr_XVUJf$`b!_#c1l&uTFb+`e>qzAvI2KDNaq|itz%WIj_zK@Ds)F( dxi{X9geiU1ZQj1Qv@YkLN-B;;D}||!e*j9xxYz&y literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_flash_on.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_flash_on.png new file mode 100644 index 0000000000000000000000000000000000000000..dcf6d1b59d4a81a9c0a3b57fa8ae1a351a368061 GIT binary patch literal 583 zcmV-N0=WH&P)?8}e9y>da zJjQow=yv1YJDvZ`+^KWw)Xdy-|MPwS|DW3(CsyRcDRTap6)1ECZ3S!vG&5jZNHc-j zx7!M6r%*G1t$;g$nM|gQ?=t~Oy>c9!*{{Y@+pFW?F6yN}t1D5tVz+YT@_rNbuk)*DW$WsV` zIzTpafVpICKLXknkrLM4aEoJin{=Ak{ibLTs24n1is@L%9R|nizRDkST!! z;;Xj$8Ml1sK|mc~(IGBC`&2-9?4neU$|2w{M9EE60D&fAFS=m&fL}5JuVR|0fcszB z9eczPP;a6}h6#ZUNb8yE^3A?^vYl$iv6)+D@m3n5TT&@JX8vkQTz zViV{DcvMZ`)289YE07Oh?;hfZINuUhAm16cEmY`?+X~nU2xq`PMuiiabGV|fz&D0c VhA|s2Vu}C&002ovPDHLkV1l|l1zrFE literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_flash_on_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_flash_on_light.png new file mode 100644 index 0000000000000000000000000000000000000000..7104e3f19ae07c2bf5148a854e73929218b0fd03 GIT binary patch literal 721 zcmV;?0xtcDP)8?b-+;f~cK~&DvPRgn+29Y$Y~U%gVCV zB5UV1BKaK|NFa!ccDok&AxunWJSie$NX9#FZg2uGU1sik?>qOL_jsfD=KQD3IloT| z_}>mn2c!coJ0K(EvVpFLO9x!H(B%Zu0c!)J(dhX=AaLs+P5n|Tm7ch4{GZ{h4kQwZ zYnb_p9o%3rcvG!b_q{6MKER^W;1op}bUK|!wOZ}SlLC^-WX?3r1sgaO@!8;lAI`%T zp-3dM5DW&hc5@;=FA<-Qo)i#|$Il@m_iW(wX0y50Xf$+B3cv=w3b5sAaER82a=HA9 z6P`6f$p0NcCZ+)*J}(d-&9egFKn8H9CIKQ^N5x`s9q$ZJ3J8b8CqkjnbDIrp;$7bg z54W}usrPOLv7AEa{uzKgq{6_F&u}Eq;RuTWy%Hmen+^ zM+KwSu?tA2(q7>4n#QmJe^fpSvIF2MR# zh8P{TTCK<2H_*Qh2PbMNwaEVifS*OJiIZmor_LwJIMEtb2k=pI3?DVa{0AZ80C%0& zqF~f-82DM6`}o0In350l$KcyNQik5ruLxj#Yq@g}G{_0Ip7o z&LbTV?Ht!Q=>S(JMdy(Yh<1)^oOFPzlcMv?y#v1iGStg4SV13F00000NkvXXu0mjf D&0Icf literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_forward.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_forward.png new file mode 100644 index 0000000000000000000000000000000000000000..5516b5ccae4ac6fb67b7aec6d7a69440d1291120 GIT binary patch literal 605 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-s=L38~T!HleVFXrm%yS2N$+aZN zFPPzMGVAe^91`N|Sk{Pc6ka8@f=6c4S}&&cBFB{crsQqmUdo?+boo}nnX2Wdr}HVN zi#ZhUa8hto^PZ8BS*3DVZhw9^W15bm-+7>cKRjI=Ln`9lPC4m!*g=4G_lF)?>lqU1 z%;~C}iivl>*Z%yUe@IB7C0X#-1MewTd!jur8|O!f^{MuHXs*c#naZ?pxyXu2ug0n+ zA{x`DFg@HDwBV5@tJZ2S#`@q-g)!H8kN8eZlX9=wJkP$;ev4V=*0oz@UoP8uyno{~ z^^(TR2PJ#-mbKlVQrvTm;~4wy0|DPoZnCwmWY3U~dT~_!%%-iA1F)fuYBG|>n>J>yqWcJZ&G-w@}#4QC)uyQ=dX!aBKaQ}1`M9AelF{r5}E*e C>T-1e literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_forward_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_forward_light.png new file mode 100644 index 0000000000000000000000000000000000000000..c97ad273a0cd124282b6019277f7de98f28e2b9c GIT binary patch literal 592 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-s2LgOTT!AzkXlrXLC@9Ft$QT*?vKtE-!vn*-Sf1_rvix z4O9T+0tJBp$Oe)?DIf`yg(!fi1hRp$5D~a6gbNXeu;B{eYJdzN_?bBU56}Y+B|(0{ z42;YyY#f|i+`N4J0)j%qqT&)#(y|7IMiy4q-adZ*fkDCHkue$h1%*Y$HMR8(jZMw1 zZS5Uh6DCiYI&J#QSxjd<8-Qm0_jGX#@i_i=%56U;LlIZ&%SMY1HSooKXnGJEcu>-z zRqp!#|5N$1dP?@paS=|AIA5)5`}U<-+QIt8cLTVpD}yyBEca>*TqUw2SA(^!bg4sN zFc(kI(gO>YiJS^z~If6Qy<1?Ik0 zw-_k3Fg8Q>a$y7bk9HC-dJ~seVf+ed=5{>O&8hp ze3z@p%e-W;@KiI%HkChAWANqH-tUiJE&RSO+wZUOr<+^duHCwEX{C_8Yby~x=v@Nd7)_Rpn>i;-x!+3dLaL_T;Q_7%p;pyt?lE B%Ub{d literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_full_screen.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_full_screen.png new file mode 100644 index 0000000000000000000000000000000000000000..5e68541e3e21c3459d270beae922bbac3b2df754 GIT binary patch literal 589 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sjR8I(u0Z<#fP&cjO2I%!XqN=} z1v8xG=jB<1^;uum9_crACv}OaIlEtlJ99vtiY})<*e`9vi%o**Ccc*i=pYfFQJfB>xvqi5a zV17-pR{F0>TczTjy%uMM+E?k6PSWYM?fD$o+|TH^W9l6<9+lVq+rKJ^P89c4Qn2m4 z6S1VsMfIfL216-j(UrYRC#?~EGkuvNvnN}1;Zoiwk(VbVG+catFz2M|EVlO7+u2v$ zh|~FLDdWq`tK<~xdR0(NtdptBgu^rbi5bUC^T6}jo*g9>`^0NMEL!yH&?<(?39}f& zLuFhlG#)TLE8G)mv?iwOAHz{r-YE82jk{6}zPq_?Kq-$P%7$kB%6pWXM};l{B!qW_)joY%0_MYeuX`VFH5pm z{)NtKZ`WmSPAqG8;I3j@RnT=$*7$VuoBNAD{Y{K{Ui|o9$l}n4&G8Sr`R~YlPvHbc O34^DrpUXO@geCwi6g)Bj literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_full_screen_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_full_screen_light.png new file mode 100644 index 0000000000000000000000000000000000000000..1e484de5cb727219b5f834d6787a2f495c0c5e4d GIT binary patch literal 585 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-s)d4;su0R?BR8&-CWMrhIr1bRk zw7~$#00JW;BSS+&2x(wops%kFWCH<^ZES1|Bq3ZN8^|y*F#$3lY#Z$nO&H5>4xd^|L1N}EF_vtkb8|Nr9G5^hdt_dWf3p{0v@rH*ay z(v3Q=Q~gu_9o+0&zD@j>wn568?9D2CAB2uN&PmBV992ec&mBSv+ zJJazJ!;Q=r+a9e_@}3aFlxwPgTA@+TaSHbr=gAWszDk{)5zSC>P36d^+O4Y^Q*63T zIT@ELGv$40^gnuEFhl6W1%Vj7h@AxsmPl^Mo2MD*sQP|Ut>8zSX-lFQeLf#jUTr6J zcSZP@IlR7wVShb$EU&xBuzBZnk6nSC^^2pUU;kVEc4^DH{7bfVyX=o&j@tV5?>Vk5 zf>yrm_pUtXD}VRwgw2jXsTK3Sd@%KTY_+pBd(trtyQtL)dCGi_qzwBYRjrwYvq~ked1RyXofYiErbk?w-C;K5y;s=Km`3FH;ll Ym(8_Wpc^)CHYh=Oy85}Sb4q9e07jjI%Q@Bc4usAn|jENA5T z^M8KBjJp5!4LdnF@9mCu@Oi&m{DR7iUS08x-Z@ z;x+tjJ+waWyLFLpAzR*XacS0@(hzOi8_`<+2=km`@QV#W(fL>(q MboFyt=akR{0Jwy!sQ>@~ literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_go_to_today_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_go_to_today_light.png new file mode 100644 index 0000000000000000000000000000000000000000..55f96775a93188aeb6921fd2f5aae3dacff2058c GIT binary patch literal 356 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDB3?!H8JlO)IbOU@sT!Azk7#kaFYip~hsOahG z0U1Cp5Ey|0grR*{tpcc;za+>nn1PXrnU#&5o2Pi<Eak-(VLtg zF{$C`QN~Uurak5T4I1-zi%)Q!Ic3V1d$GYxO?S%sr%Vw^c+|7G{QbS}@6P5aSbTr? z_1#@-)&)XqzTaEeu$|GMb2lST&HHr?GxoigYuL%bInUVJ!DqcO`vsL5y}S-S0}{RF+FL0jXWPC7Ld%HYm!)#c`=@-0|w&-Q6$NHO=7TaVW9&nBK61U8C`x)`H}Q z7iVS~--u1k$?3Tp>fo}I#b&_;RfTm;Dgmb!Z8H_&bWu=wch{BigUTrj@z6(VcS0@( fhzOi8_`<;O@X>2lgU)3$Kw;(S>gTe~DWM4ffHHv? literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_group.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_group.png new file mode 100644 index 0000000000000000000000000000000000000000..7f0ce906ef5fc4b8b5f45bfa313bf68124760cc3 GIT binary patch literal 1079 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBgK_VC)R=32_B-|Br$}5CUO7j~jrI z(OeSb7tFxO%)-jX&cVaW$1fl#BrGB(At^1Rps1v*qNc8?rLAjVXl!a`YiIB1I($ha-;-o24r_Y!*d(PbX z3zjThv2xYwwd*!)+`MJ$w(UE2?cTd@|DnT2jvhOH;^e8*XU;C_isJyLkz1ZFjv*3~ zZx7~1Ut*A8yHLGGDTv4Mipr!VYo4fHo~EZ0a=>ZwqQHnY*I5%HA`S(Kv^<}FoXw(O z_OGpa=MT32?>uX4`gG&NITHD+yh^Y7%dtH#cq=RGJ)=O)yX{uZ<_A1)v`T-RcvK=Y z_k+YO9sNy7YFAQkEEN9Kwl2W!j9$crgEQ4nZkQe77Nc^~`r@%2zLPFJRaj|bEH@$L zHpfwxliLK8r-q-Hn8Va%adK0Iv)1~Lb5ja6SSGzqY79~GX-r`f5&Si4-S10(Cxra5 z&AhpuL!|Fj@rg63w>I4t`D=gruI+@F^OhIXq8>^n7_@A6u@On^QZ~$Hc=J-@mZ5Qd z9Y=PnXGC|%$3>}o!ZsuY-4P7yHs-OKS$k&&=Yfb;zGfYj@Mry}_!(x{%sJn~SG!T< z`39?>=e_rSnA%~~c$-=Ipv=@gFJhx+mqq0lt&EWG>wOp4{o>dGF4HTM{uXp!*<{|O zw%bEj`f)fTPy3|TuTTDrX7K4ZTd_35{jibg+s`^75q0xtO}l8Y{e}t0hJ8m)*@|uQ z{%)^Qqf?N)F_TZL+YnrD?k`tjE(oc{>MuO{KV-VR_`lM6#`}_1i#~}j-vCT>44$rjF6*2UngAO8v6TP- literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_group_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_group_light.png new file mode 100644 index 0000000000000000000000000000000000000000..bf91dc7eb534bb745e036b1b4ddc1f3d19a7c124 GIT binary patch literal 1017 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBgK_U`z_|32_B-k%5DQgR!x(wzjs6 zjEt0&6p*c_rw8P!tE*dETbrAk14RrB41gjU8X7>hp`js=t*NOAWa#Vbo0^(J1c7RR z8g+Gbjf{+dY@if`4dg;p0+m775S2jE#KZ(H0+)p-hKK_d0L6hSA+m7AKn8@3Yyw0C zs2y1`oC`4uC=eFE`_FYLCe_!U=Wv;1o;IsFfuW- zu&}ama&d9<@bdEU3kV5|h)PIGNz2N~D<~?dsH$mb>ggLA8Jn1zTUp!MJ2*NyySRCH zdU^W?1O|nKhJ{B&#>B=aBqe8N=j7()7Zes1mz0*3S5(&2H#9Ugx3so*bar+3^!D{n zm^69H)M?Xa%$zk_Bu)_+-xoYx977}|-yRH%zQiEGcAz4fMIys+;z6$yz)11BI`@D0h zvO6ZNc5&{~i)sApqinZvM@)}i$Dujdt97PdO5T>dYeAZ{_w*;9mT@aT%U;68ax$T? zF=T5c&&F`itGoWr;Su^492ENY!rDpCIFuy!xV4(BzL4q>d@S0iqFH{)NeA_b&sb)s zC>WGp^0>emV)5da*}o|~O2X{3;+ab7R5^P$`?|;V=lx2ru3=jBThzWSr@Vsg!_tp^ z8O&CVMkn@dV7&MKw!|@&e<4fPe>L49eT6ge!OWoYWM8{!`%Hv*+$;|po?~oy9bkRZ zsZ_o6S{>7YgGUef^~@0Z9Js%_@BaO{E<0R9y6opf`h=|zJ@n+Ao&ED~?w=otoYOVU zbl^*RruFg`& zi`2JXe$ITuqbz@B>$7X0;>^x4?VGz#ghx(3=z6|q$8pw|ExY*S9|}pQr(AfL*cpDJ zMX0&;rrAuZxve{8B7ZOh^PlM2#9+Ms#3ivaE{~=u?fAI_BoLa~_NU7_SXq zS`0rL?^6qr4y^wwGMkH_i_P(WlKhk-k+XLKX#9rwxK^5K;TnK* zBq)-^$a`0pYE%re1NlVR;i}#p^fmKIp9EH}mDMcD%9rt~jqzyM97VPyp?tVbhLi6( zZUbZ1#Gp0Po%T3BT=$zev0%9ME#Nz3Q@)8uE)6ko@9w>Ts4W}G-2i^*nXlvA*DCLXx}5~^mIPPgarJ41wsm<56=WBZE>&1VOC}-3 ze&Jey@>TkIFKGTmN%^Qn{nNKqd^ENSof6-;q|~5|Ei;g? A-~a#s literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_info_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_info_light.png new file mode 100644 index 0000000000000000000000000000000000000000..c19f7f8297047ddd1f7612d223be3be1ef603570 GIT binary patch literal 563 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sT>(BJu0R?BjE#+DWMrhIq|D9D zfowfJJyTOtBO@byeSH%X6QBr?ZD?p{U|;|tfn10PL<+(NNOUoZnB6DubdAHR&OikgnDt-XVbYfyMZRCG*iTw+pMMrL+i zNo8$qV^j0wsnci9y2veH$H2g-<>}%W;&J@#l(Rw24gxJd1E;J}oS4AE%;9*XwdVc* zDmjx0x@FBT4$2s9pE+yYtC=q|PwzUmv`zcaa+6-ChyPZ@rc8Q2VdjjS@7@clPfu1^ zZ@u8l`S0taS1`TT{@BEI>+8%i^|rLis7NybYc~g;m%UNDd=zv|nQ zoP{b$%eQ=wa`3$T`R0LT>0cdJ-nHlXywAzd=bU4Ce@~W&*zdndC$x-u zHF&j0FlRhRY{J-F^DmGwQPilgpDd2R{?0Hy&pi#LMd0&nz>k&L~~0^}ug? z*w+FrhiZ#ZDJ=(W-q0GZ0}6Jo_a;ucIAzaN_D#9B=hZ0u?Y{L)d~QC|G~vU)5A)2P unVYgV^qTu>8=uIhHOBv1@5Vp2eEL7Xu|GhaLM1_d z!3<|DbvYIC;`{`dcsTgwMOXwyCgeo}WrICk978JN-d?fhJD|YB5?I}+lJIHw|5WAN z*T+&P{P~sXK5Zh~3h$6mC$@RAU)q|Ng&2K!H}_mYz?511Mmx-^4lz!7mE_1KYvRIV h;;MGy&b$8#wOSWg^NL@aoCX@t;OXk;vd$@?2>{7gZ&m;R literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_network_cell_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_network_cell_light.png new file mode 100644 index 0000000000000000000000000000000000000000..c11f7cbe7be3f96e1babb105d82f3f0d519bf486 GIT binary patch literal 250 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-smH|E?u0R?Bw6(QWR8(YSWc2j( zfNXVjbz@^=9UUDYTUS@t(9lp{U*E*U#0Um%?mBD^)G1sNDsXR5#Ob?R?OP+S%vJP_obM#ZLhxJlbSZQk$0Q7@4E$$H4P!V3AdAnWAvOl;u=Fi`R^{MU4qg nLKeMJ0sMVl56)yYvokQ9l#;KWQmgTe~DWM4fDz-NS literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_new_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_new_light.png new file mode 100644 index 0000000000000000000000000000000000000000..52ffc61e91e898869035e40296f14dc3fac9191a GIT binary patch literal 157 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDB3?!H8JlO)IgaUj*T!FN{zP=F{7#kY{>D3RC z%z&b7B|(0{3~C;M`LiCnJpmbD;_2cTV$qwNAo0fGhCq8u)`b-;vZ^gp6b_iOoC;|1 un$fnXF~Ld5qE{+_zt8KznXG1Z28NST^3_x76>EU{89ZJ6T-G@yGywo}Dl4)8 literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_next_item.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_next_item.png new file mode 100644 index 0000000000000000000000000000000000000000..74c1448e56555fe1628101f4b2820cf7afb770d2 GIT binary patch literal 478 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-ss{?#OT!HleAp*{>UojKtT+5Om zzhDMNCT0#!ZXSLCF-d6|1vO0_OKV$KH}}Ah@Tlmt-29@_)}F~zX3t-=WaX+&o44-R zf9S~36DLodIcs2h<}=Wcm7Xq+As(G?rM*ws_r zgjwqUu85Khm6P4n)BWp*$PBl8?3b(?8Y>nRFdf>apcVcgOw{Ew=bY}Q7tC)qH_c#J zGwD6^M%Dv9Jmx#uB)XRsu`9gcT2#U)SL%4>-GQw-9ex}#pPM8YbAskG=Xig+T(+jH z@S4=dohI|Qmix;EIL}+b%P4L9axKrMmR>K}V~u^k_wQRI-uO?6>v{TGIiRB%JYD@< J);T3K0RT#VAG-hm literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_next_item_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_next_item_light.png new file mode 100644 index 0000000000000000000000000000000000000000..ee7acebc928c9b6d79438da8396495731600805a GIT binary patch literal 470 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sO9OmDT!AzMXlrY$sHi9?D9Fgj z=;`SJxdsLX8X6kL#>R$*hCr^VsVR^Rlmc>1OiYZ7jDQTF8VCcT48ny=K@czu|@{(1?|uE{-7{oo}bO3LSRfVR>tD z1_<8$x7UsLkPkYkSR8geYw1OngYovO!osGuJ5QUqqJP-|lN$LGZy4Afbw1+kxZSiO zt})tI;H-Lq9_J$d4d*$Nm^OIr2-!BN_U^g0xpYao}-LxJz=NRLKg2~&OLpwo_otA;T0Zk=k~dDvj<2yU?XA zI_o@J^CRcZnO#w5TX-$~7%&cZdb&7SIN_x~AE zm!^A9dwAgex41vw&zK1I|6tw7ad%yVMV#;_?!q23sl^?MQ}-3V)LL}=hSv1$W&$(A z{_vP|OD*!c?EGNDGQo>pd-><>`^B|rrc(0a1RKwN`K;g*~UKev1EGfT<4CReMb+bYut`txtyeI-6F?4HIhT%g3%VUnm6@UAWA){DgaNwZ}lj-)s>_fPZa;@If>{GqY`cEM$H zN*+E|JI%3pGV2c=0ola1r?o%coIcD^9N^mjiqXm9sH}~Z-Lb`U7crZ4&UrAeSnKq1 zzISs4ICG3cn$x$%Y3$XylK$}GB;$nNSJ*a`99{jM(evs0X$*U6*|&WalX?8+&e?;L zi_f3uVP9KnAp23i{5#ilQ=65sV&BRv|8eNZ{B#T9te+V2&-&qkPt7TpnQB@}rfoTJ o>0jhw?yW)6I@>u)y6f-eoA~KmaLo{y0!%v$p00i_>zopr0BJZ>)Bpeg literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_not_important_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_not_important_light.png new file mode 100644 index 0000000000000000000000000000000000000000..40967e24abbbb8ceca40461aaca0feabb11e45e1 GIT binary patch literal 932 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBgK_VAKil32_B-k%5DQgNllZf`WpK zjEuInwz;{vv9Ym%fq|~BE|3dk8yXtw=;#31nwpwGwyCKpM1h{39#9#OG%_**ikq02 zKp6V^`alL;9H<7U9wG%)2IN8%07ZaWAW{%npcI4w7l)|FR09-27KCsyMS!M341`EQ zlmSH`T%h4_EpREgEJ&x3k*W92r@+8UDGBlmW?*DuW?^CH;N;=s7Z4N@5fzt^l#-QG zP*hdd)Y8$@H#9c4uy=5Da&~cbbNBG__6Z6J4UdS7iiwMlPe@EoNzKU2&dJL!Dk&{1 zuc)l5uBokWYHn%o>gnz4pD=Oql<6~O&dT1ob`~(64tu&dhDb=hJy;z*D}aIhfxM8% zrM)^qx4Oe$1B`?r5TTAwe%+8h~u*x`tu z`w;~@qi>AO7MtH1^CZk#vt~l3%J%yCe)r!i8}1BeJ7p{BDSAT0z?I9xV}rk-#a338 z%?CblJh{msZ}>suqq$RboX@XP`qh&+t^c*| z^NFlB%eOX$OY0s_ZggKBYOj~y_lQ4n_NDHulSW_GXeqgbY~GbPb(Q#(Jno9*3i~#} zw7F(jz+1{@Rzo(?6TNSRQq+yz*)a04PrL>gq#=Hi* zLvq$0jmN)a8#z6hm9KP6=%(uly-24yTjE_jF8V9?oqHx=biCxq&BAs8qbKha&Q;3R zzIxuF_;uTdq!bqYZB;@)Or{+c&b(WCUDf8KA#crU7q^6a%iP_s%yW167Jl&iR^Eg+ zEoP<;*_S38GQ8D)u=^*=$*LXN%LF_`-^=N6PL(d`4OTAqlsa%Fp!GHylThkty Y^PH1#@G_Zw66j3^Pgg&ebxsLQ0Jhz31poj5 literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_person.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_person.png new file mode 100644 index 0000000000000000000000000000000000000000..fb7ad44121042564fe83d83041b1c8c89bc9b95d GIT binary patch literal 642 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-s4+DHcT!HleVGY)-V)_j9q<2Y> zUoZnBGYcyRuYibzq>O^1ik7Z{p^=%rqm#3XtDA>kXm~_abX;OmR!(kyaaDDFb5H-o zNt35coi=mn%2jJNZrZwS_uiw&j-NPr>hzhjQhllY3=E8{o-U3d5|VEZW`;8+O0Yec zt?9#gQf!loQ{svo-EXPy{{L^DRP0rmK5wRe?TW{{3O>w#ak9p4ld&(cnyGiEz6NOKGJJO%DK56RGP)XIwQ`ouu5#J;>QC^R% zkShu&gC@2f+5h15%aeW|av!#@@Qh1-KF#;U7tZODHM@+|tz=ZD&6#dmW3g_{G)@aI z|C7%z{fyl5=hREp7!JD`cZ{qZcL=ZB^80U@YR~-zsXfPcw5?tIWAem{3SGQA4D&+0 zmu6+3=}qKmdeqewD!7eHO?L+C4UV%JnPN>_`Es`;YC1&=My$LXCL4CiH9Aw~PwD&E XwyGw9|Gs9xaAxpy^>bP0l+XkK#sZEg literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_person_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_person_light.png new file mode 100644 index 0000000000000000000000000000000000000000..e02a988e1aeafaf57966d91ac83e98aecb6936e9 GIT binary patch literal 638 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-s_X2!ET!Az)(AL(Ll9B?F#>U1# zQbR+-(9jUb(A3n_*Vi{NFwoP}Gcqy)GJsql11Jk*02M>n5OE+01ZaW~1tumYKq(*_ z!UbxFu;Ge?zmTw~gru~B zqKc}TroN$(v5Bdfm4l;`i>sTvr zsne#*3~LHtV7;(-ir36pD_x#Vkc_;gFeABH`QGRM z_EUC-MaJ#;aLHNs`>}KNi=>}!TBy9F+kY`x zF?GjMmZdLdL>~)WF(+VBtJmB~Rv}SSwk#;}KPelMr@6DyYvLrOkVoA6WaM&G?u!*_ z*iI6^vEv!@l`opH!t>7^4RLR1I(>9%8~^WXmvj{-SSrug@9*FAHT;~PpwlPM0^gEJ z9O}82&5g-RKT4Zie)r6D&D*EDzs+P@dS`<6Y6_xZf}Q~LgFV5Q-Ma+g$4D)Myob6Mw<&;$Sl CKhYWh literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_previous_item.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_previous_item.png new file mode 100644 index 0000000000000000000000000000000000000000..d06bce81a491b29e44afc42005b2d0e33c3fe1cf GIT binary patch literal 547 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-shXZ^m@3O2i zEYJS_53fwv5gy0G_vB}4hrF(m(XTF&rUd~+hlhHq#7q%+hkKU?#a=g*U~H3!+x zi5kzp$$YSVX8m0To;evWxEJoTU8!opW%nUkOlE8Mwy@{79v!zd7g{XXmY>Ey|8rQ> zp0CWi=4ZqftWaHW-6tZ&x_V-3sHC{tk)uY}UjJM9|FZnFEKv1_lNi8X7<;LqkI#*VNP$$OcLQx%&G0CMG6EMn*t35CBy|*gytQ4TKFO zAq+HGpaKX0Y6LRi%HRx$ERYLlps|76x$m1E1D$SH666=mz{teP#?HaX%_ATzA}S#( zr>Lc^qo;3TYHRP{=;Y!P6dW2Bk&>C0Us7IPRb5lx(AM73HDS`^DbuFUm^o{;*3@pG zNhdsA978;gzn$VPbjX2+#ns62c}~%}gA#ZC{}*Hb!|>9nFyWl-*4?)*cKrGJ*=u`F zO-`${;fINm2Hr1tog19J&TeOZFf07?RQ3l`uhu+d+cPW6u9!(;MP)j#!Bzeez70LA zc#|8}E`C->EXjT!d`TsrQUe$~0iNAM0f6;I= zac8m8!oL-_l+E+Lma~UknsjQVp8xs7CaJrxr7ZuWePNN+y8I98pLi?ixF2L;6MypL zkDBVv>%rUG-QKN#x^jmW`}A!Zzf3Ny>AF@vh4=KE5VjL;e{U7HcNt2WMj!azy@^+B z#f+&JMJBwQvUa`0RqmNv{Y^IH4sj$Mxj|nVx`D-6L+v-SHaH+^0_Z{@ZR` z8PZqPxbui!z38L#kmH#%rX5k<8tUli02%uF`g(eLrlzJqS)d?L0g!8CWCRfh zGJt|Wwuy-egaHu&DnnKP(F@TIu>~j#Q3)g=44@VW1ELHp3^E+39>NAHfU|+(KmZg0 z0*Ef46kHaW4RjbX7pM!ug(wCa0~G<91DAp*gS!D)3L*#>fpe8-nLGuCa(PLRUoZnB zGYcylI|nBh7Y`r5fS{15xP-Kftem`pqKcZjrk1vjzM-*+shPQjrH!4vgQKgPyQhz@ zpMOwrNN8AiL{xN4e0)M;QgTXaT1IA8c1~V?L1AHWNoiSmc|~PaO>J#mLt|5OTSsSi zPv3-zlO|7@I&J!lnX`EN-$n!De4?j|V~B+0+k=_WLWvA*7u!`$y>D`9doT9YTH0Hn zJvD5p(BdPfwjABKL4|YX@9)ReN-tWUsQE4hI3whh*$fVi*6u;+EX| z;KK*hU*(a*>cz#V*GMoa`FQ_(~1Hzyu{E5NW&U;xAQBsV=pxxC|bNl?m~*L@BR5FYZm7zYp9$5xc@JwU*>4T@%6d?Hf>J7dQjku=fo?=YqL(t zPf{#3IkCvy^!WKBddJ(UN+t4-sh97uO8Ue;t$RWD%}6Uy?qu+E^>bP0l+XkKVj4OI literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_ring_volume.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_ring_volume.png new file mode 100644 index 0000000000000000000000000000000000000000..47e35fcda6b0159f298a086c9429790ecaaa39c0 GIT binary patch literal 834 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBgK_U=$DV32_B-|BnKU5O}<2>P=wK z#Fhm41v4-*F|)9;v2$>8ar5x<3kr*hiA$)eYv}0e85o+GTiV$>I=lM@hK5H)$Hryn z=H(ZZR94m0HZ(Q2wfFS)O_(@o^3>@wX3bu(c|CSAI6$z{%rvuma{HR|6u6?Uj>-v9sB zHqy?wu0Gtb@8`ka#}>0^d`%MnuUIV*u*XfO-SgRbjlVGm9FDJa(5^puLX+)HTtUcz z3b)xCb9qGG?%UqC(af@BcT2=p=_|_(+`7N7^Jxj&G^4a)PU9_8cc}@_{_T)9(2?_Z zTzPcj`3Yxk=_lH^9<`d1CG&~@xxmT#CnvW&WO*G>`Oa7=D)r9ohwNv{_A-U+GrAIW z>^|R7sa1cKSA?)GtyOulFJ5{>GgpX=m$|V=g>Xo~8_NLAuNrR^5_j<&usiR#)bV7r zOV%>)m6IK_*8iIFZNfZP&m6_A>bYM3qIqn8Uolu1T%h?gx?`{U`e_S-KWTJUu`S%> z|EWycO25wdN@UBGlqV&OQlkBe@8@==9&D7)zM!$Q=T3w#AM5T58a0pY^%hLt`pbta zY~lAysfQTV45e-R=A;@%o)qkfJ*PZ%s=l4`TboN-*Jj;)wye>e|C}t-%?7qd&dtCG PXJGJj^>bP0l+XkK8~+05 literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_ring_volume_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_ring_volume_light.png new file mode 100644 index 0000000000000000000000000000000000000000..08bf6ae4752d5574f1cc5895df2bffb7c87e39a8 GIT binary patch literal 786 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sKLdP1T!Az)aBy%iHa6DQ)>ctb zQBY8jk&%&-lG4-DQ&(3vH#avhFwoW21jMQ%O-+G{fefG^kYQwG1XKVd4Z#4Y z1}F#=fd~RgAQvbDWB{dr${<=G>VYH#K=cCH5S2g%P#LmHpg4qUVqyZ8fyx5Kfr^2G z5WPSW4j}3wis6Err|KyHeI8sALZ?qN=H- zZ)jv{W$WPR?CRzo5Ev8^9vu@Kmynd2nwgcIlbe@UP*_w_Syj`}(Aw77)!jE?^0etQ zX3pxZ{RcFivDDMWF+@W0?ZMpWO92dQ57HO#2}f$_1%6cZJ#)5X(P|cE(bz2wbD#hJ zKjYl731y`gYx3(p?ECmk^wwVcqxBl|xVx-^RL^X#a$lLBxaRfk3tILDh24hv8tb%X zoPA+X+GBWHy0v=7%Ld_Q-zD3sADubCle@3NL~ym}#y6WI8*T|NkMYoMPLOXqyo_o*^v3RIDtvZoa>%K(x?H{*W zS0q=Luuh$|;EB@WFMm=F2%Ck}c>NVJ;%nv2e&L*&?D3LC(mRwPZaa(U^q?JWcg{2f zZEv_!<~Bv<$@2gq_Y=7boi%@Tbe3OV$2r%_LDS0V75C2_oO8cUm}H@?5Z3F#*SB!< z*V!B2Ni7i*-Y#Zh*V5BE-{(eCvi<7|5&Sb=SnK+A1ZRZQeUSftLDNb(tuyw;Tb45x z$8DBbKe-Ys_&N7S)5`YHCqciZ46kV_>#x4}YAYYlp32gH44+RI)oJ=&(*>n$Pgg&e IbxsLQ0R4*!j{pDw literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_settings.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_settings.png new file mode 100644 index 0000000000000000000000000000000000000000..54eecded35495a5d6e6bf2ea5f68003aec682bd0 GIT binary patch literal 807 zcmV+?1K9kDP)(RCwC#S<7+TFc77D4hvukUH5EY;Tl!fNOv$F$$;0UCBz|LUcA)v)R>>tju zM2Qk5O7s9NreJ!z-Ik7}^J1~MerW(Cd`Z)rV|h;i4l&Prnm_?d&)SdJhs_P(=a&XR z=9AO3@@&aH{_(j0NU-lTZ3DJ8*gL-y)4>f*YZ~t~dKyYc6?|`OQ3rErS?lPx9n;(r z+WTj|M+GntT@2|Ec>uTz6I=r+AYhHZGwiuq0B#6`iVfh+ag!f6O5+3#t(cG*6IKH| zV!iS3x)6Xmnh%ih^?>lN5b!Sm6qY>&)>_>92D6O{oEb+0#O&x0$_TIRw;JhxCupO6 zL<>)W(dCbvrX+da zHAFmiQ%0c!1Zaft8&|=GaM=nFMvLpQ!jDR1xY1Ykskda^y|3EDniOmWU-;k~D*Wh7 zOpK50ZzXQ>91^>65!}2AVQ$?RnMMKNPGu)n4Ni}Vxl$aDGpk&`o z-$|#_`F!rq-hiL<35!N;xSu1DtsT=t+36NWyh zR;%H1xm@R7h2Z2aF0Y_x&^a^|RfYF=46j^Ta({w%zbId>!LJv|`(6WJb@`AmOq9s) z3@(B`mgN%~(7_IWmpEo+2=F6<2z{5)Uc&PU^e40n9Vkwg6lXje z3}E%es=c%f8FD3s<4plp6M&(0=ria!^eY3oZyF1nM8L_yR~6b#aK6b^t2o#aW8Ofw z`894cr+WabE*mkA<*wR^0q}%s%I6Mqe-dLma4EUv6aapwt*}U$0|L9EIX(giFAWPZ z&;ToJ92#s3nZm}<3kHyj*T~6V`1wM)eFA+1-O`*t#Ke)o#u_$GIewG3MgHHgO4ZXk zpK2%OimFEE25K<2u}wZ3X}1NCr>b37=TlP&7@jJ>LoFRHU1~QMLQStgOSeg8Tu22K zb6S-!g{d=xU72HB(Qe7nudn(>}YJyET`(&62EQC*nOR z+nLa5Od@vL=h_}}u9eXyO63$K^TyII43sijBKdowl+lJOjYz|V`i9*$V2|5T_>6FH z3l3btfye;Vw}y@En0Pw%WW^|GOFk%{_m>K)I7dI{%361-zyXQbW^ zw&;)xlN|dz;PrYk$FgV3-O%^xbQWi$b6WuanvJ@MZS%SCJz1`QaJZhf6;encg%pyT b{1#vU%aSg@hL7wY00000NkvXXu0mjfhD literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_share.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_share.png new file mode 100644 index 0000000000000000000000000000000000000000..ce9fd905774006bd83df0366d6a778bc4a00ac61 GIT binary patch literal 641 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sPXc^GT!Hle;SPK}qymBd^eGAQ z3ua(sVP#|I;N;@r6A%;@5fu}ckdaeVRWmlVu(YK55N=eVn%P*{{ zZEo-A>7Oud?)(+&)^FOnWA~mzM~)podFu38*&v@#1_nk3PZ!4!kK=DckBS{~5YT=H z0s(78p8fydzUXx0@pE4e_Qu?D{6_)V<3#E4RF#HSdm)!@G(~Wxgqb{>u9WW^0{KoKT)| z{FT|gs+x}~XUvzL*O|XuU|#i%r>44T%L~6X?)f0h_|xOb!k61N9d#}2uI_ac6YceX zXsqIUHx3vIVCg!0KWc@l>h($ literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_share_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_share_light.png new file mode 100644 index 0000000000000000000000000000000000000000..202a5c83a3f67ab6e5669445e4b35dbc1febd1fe GIT binary patch literal 613 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-smjZl3T!AzkI5;>M8yjnDYpbZJ z$jHb**y`%)=H})=wt<0xuC6Xn*3i&UM@L6fQ&Ue*&(zdZUtb?64iq#oF)=bS0y2Oq zf$HIGpfVsEA_5Tvs)Q?mD+6kT0A$5LHiQdQ4+KC3KoTwjmIRp$5rlA)crBL#z2sIB zlYLf8XK3K zmYJPXSXN%w+}6?6J8AONY13!SoYn4Q;|MhIkEe@ch{y4_q3%M53ge2=l?Ip=ll0>48I;8yMMHmJ3EiTj8}8<>>6Fg z1-DnT<=_80^VFtQVlnSCz0Ab-EnB{VQRcVe#SZ1Z)*t_4c1-_%`T;1hc)I$ztaD0e F0svT(#!&zO literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_sign_out.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_sign_out.png new file mode 100644 index 0000000000000000000000000000000000000000..6cd89e10bb309f89aa7300e37c15274e2b649161 GIT binary patch literal 602 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-s=L38~T!HleVFXrm%yS2N$+aZN zFPPzMGVAe^91`LyHcG7#WmzY@YLg7lQl^<+B5U*3`zalplD%c?QEvX_f(pgud^=Rd z9HyUEc1(B5nBlEbuSmohVDDKJO z?QzJnMTJFFC2?_+%9|+@TMFjJudBJgUiyAwl6b36;^%zZ=htp6d$}uTtMxUv#cRH* z{(CHYzOBII9{ViG=W{1KJM*QX`7k5T?aahoM{SmS%D-{texaul;y&F$IgjBwcMfOX z8Qp^Nd_}KKd~=^I{C1Px# literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_sign_out_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_sign_out_light.png new file mode 100644 index 0000000000000000000000000000000000000000..8cf93dc6883e75f834c2fb1aa0045c244fd10b71 GIT binary patch literal 646 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-soCO|{#S9GG!XV7ZFl&wkP>{XE z)7O>#4i7UMBUiKDgl|Bh!vQ`au0R?Nw6(Pr6cl7+WQ>iC_4M@A)z!_-&4FwK0|Q-M zU7)O)nVF%Xp^lCYkPT$$>+74EngV5k44^V2BO@T&#KZ)`1}Xq@fr3B)WCKZ{6p#eU zLKHw$0@*-WhzML3!i9)K*l-1KH9!Us{Qv*oeTqdK&<_qJL4LsujLa--9GqO-ynOru zfEamTas2I+n?Z*h1YE6WDlVARz$P9OaYRf2ugEsw9UvJrz70Rc7i0 zn*~Czx@#g6wVhRue3!4Zx^~N9&DJod?6sO_^6Q>ee!cho>80xW8Rzz%*LM9W7+<({ zuB6RXHi!KW_Lb`t>)Jk8W7QhDYtH>0PpzvjveZm?pmo`pM%jUcMLgvM~ny~lxc21aA{BDa`;k(M}tHk44ofy`glX(f`a29w(7Bet# z3xhBt!>l*3HOYx%Q>Nr{m`dPVWU Tc7_HWpm_|Qu6{1-oD!Mk44ofy`glX(f`a29w(7Bet# z3xhBt!>lFVdQ&MBb@05%CotN;K2 literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_stop.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_stop.png new file mode 100644 index 0000000000000000000000000000000000000000..b4bae41f331adc8d726f6dd8aff765e0379fd5d2 GIT binary patch literal 139 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDB3?!H8JlO)I_yc@GT!Hj|B+&14F9RsVS`y?J z%#c5A`q}2x_A;P=nx~6nh=qT0g2YV+4^B=ECC?Q*6d0ceb_RAfP7*M4V`}43mS$k! X&`mt`bGqOJpbiF4S3j3^P6sJ!w z7tC;0hMi;X&T^KZ0M-K&rY(=s+rMO8p7XrfRdXt*@-5#Lsa)E;TrWE0 zz~j1;E&PtQ?UgV0s^35TU$35`aLq5JAg$tIOJ1w5t}@uJGlA#oq*QOyCI2hL zOW8I1;?8`I&t`6ryiu0Giy)CfN<|r=1Kat6i|k?*D<`wC`k2?fOb&K*`+QTW3{>`{$zFD38>n}QX zht@1AIpBNL)GDQraqoe`1p)PD7sacV9(edqNMPcvCaoJv4gQ^s6-$J2xXt(tA{w}Y zmA5v>9$Ypv)9H|t!U|iP&SMN>+!GSHUoq%j%y2%(X>sUd1FMhr%O@h~&)2BbWj=Z& z6dqfac`xkIGqLjTYu5gG*zt~eiu<>M8k3HD#&K~sGd?_2z896TfAhn~k9|$-?e_nu z_{{H;Vf(M~hq&qw@u%Jn|AMEgTo#&9diH`+_a|{l!S7; literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_time_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_time_light.png new file mode 100644 index 0000000000000000000000000000000000000000..075507bb8d8f0dd8367bf062163c94593be19773 GIT binary patch literal 739 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sHv)V@T!AzM7#kaFYimnMNdXx^ zU|?VXxRH?&P!=c%yO&S>|YQ=x)2VFl(;G z|NriK62IncIlAj&Yow{~r%8A2xIBsfw@Tzy?&VEq%JzPceIIi;RWDC@`>WU{{2{0*3|2rYY$P<=yU%tsUv*h<46V?N5jxl|D zUp`GfueSNtXWJJpzrzpC`*m7yYh|3YlJ)sYmf{EfmK?{09=M8LWk_B(=K_x|n~4%r z%pZaI#!*~hc6luF0ku_IM5DRIB7@qCR@|JUwaw^?IMXebnE|^WI&Dm4(tYUSBjdXJ zsh6qM3~olTTG#5dB~rg5yqV-Au1{l`5u<(U;f(KhpG^9)EcJi$cCVz%R%?{3*YC+u zJ-CYB&qb^M$865#%PSR?g7!SFQ=TVf_0z>ACAVd}oWEV~y~|Vg)@U8Q938zt(&lIj z>!q-e$S*%cr~VOGqaP}|rbT(euQN;RQy%eCqYdM?lZUH?<`CyUHS&ol#`lPf?; N)zj6_Wt~$(6989*|I7dY literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_upcloud.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_upcloud.png new file mode 100644 index 0000000000000000000000000000000000000000..c7e8ac825c1b9a55479e8360c192d6c612b1a179 GIT binary patch literal 1891 zcmbVNeOME99G|>Sion7oH9U{(L0-1Iv9ax*fxFucnK&ev+d$Nf?FN_JZr~)? zKoqnLNOe)exd9r$h$aqxLo+1#)OzW|mg7t?_e{|2?{a)_-`Fy^= z@5^(WGBXy3hRhBT2n3Shm;@>8}KPvg*IZkWlvS|nBu`+}JwbS_oprfn> zL>6JSuUp$gs00FkJ83X;X8lscMpGiI&qm~>Ts&GJP%ZMhthO}-2jmk4q%#>D={yMn zq&*ol$@Gxkr6CH*v=WBMF3B+1O4itvc5qP&pz>D3#0Q@qh$^Au%Ko!;%D8jwDJD2m&TA zkXK{u4kQatoz&u2$zUPJxe&3~^diB^(Hvk=qU!A zU~LTP;z-&F_!zDEw3|x?c~2i6fpY2fkBFV@WT5zviM>{r7#2Zdit?T7fi=rz5&yXH zSZmg>&P9l`2$ps;Ha;JY=qWHCyZ;vQ8S>sB%NUYRinR!*ZElKiaymR2aeEQi4GmG)bw2QK?LdDyKLehs804Hc5_YQf06f=5Hm2DR30SI)sz&7lv<)b04vJe81J{aMa-K|D_?l@ELUO=SP~T z?;5Lf4IAd>Mxb%V?)0$!a__C?W?-iF%&d^=nX%Pj?PV>&tAE?n+|n|L9ya1<$}d-^ zEvz!4tyQ_(jMZ)A#TSR~hHfYg|FEg=oRe||Z>)U1sQ5&~$o=|OM~<;&TV+)2=nSDS zAi&RWTB%^SH74ayX`m%4CfGXq{LxY)1T_X82$ESuk^TpyFHIi}RQY-Cbci))ch*G) z*Ot}2b4lHQ?c(CsPB(VVA1!}x*|cX)&Fh7~_N(q%kQur$Jtf=kGArLv-e-xgy69Zi zp08>r>3J(drGP>eE6~j&{*RWM1&Bo8Kyw(>9i6 zN1f4J&)ZJ~7!*rW&ZJ!TSETK`>8T-))vxUpMr9o^8DqE4fO^nZ(KW+C`%k^t+eCC~ zKP!HEuK!5P61Tap*wAsS$-#QzzS)a&=G{HA%T&`q2Ci?)t(L07;h5;b?fQk{_hqZf zMIVGp4WIbt{V(b=vFd#EuDb6cud^w&V}Gsuu=1{HFz8axrneZd z6_CBaY7t}nfs`35yblMF3AZ9818(0UY%EGD2>4iSvB z+ENR&r3zF<3o1}6c!2SOf|gMn9YG}uBWPhEdfG|e4IcHV-R3eXKD0&V<`C*FCU*3`4hjmQ0xXaTGC&rC$)YiX_<<}w2m+HA z8CTOO)A?~C$)py(3MH#BOv`653&j9jXRiMVF7fMO_4ngc6oeCMjpHcAd}bp!$^G@RAf&_2x)7pFOg&6*s2wO;Vqx zjylXlEIz!EwBV#7_AYA&m7fqcUY3`dRAaN>yn0XX_Ov?_`7Np5tX=e&Y zJjtoHmGujgi#pI6%TU9PKFg6FuHQhRU*k^?Wt3f>)Lj9=#osTR`;7Edzx#?#kV~$}Ns(6HTWENd86o<2SX;XReu%6ic@A zZq|_Qt7GQVW$roKPD^`kH;gyO%)qEYVwxiFhrVUUZ`uA@+3Vx&!WetO(e5a2uR07? za%AM+Kaf#`H3n7F*jClFz?Q)p-|+o^dsd&Zgu|{SM&I%lpSBwn3uv3KjXdbS_o&Ci z32Lvm&cZs+>D1m5O8$To#Gn3Iu0Z-f%|M{m@25Zu{40h3~CErL~?ejv*eMZ?8sj z9Z=w53E2Jq+Pk&a?){&!_ke_eNan{{wr9y5633MGPdcR0*!am%>%Yv6tOOM%rnAvX z3-}z^boV|v;K1^X=S6eb4u6N8F?Xgg$qHWJx}fLn{bkyUOS-eTl@4ep@a}rq%{=|> qvXz&rncv+1b;5>y4ZqiubKIVPyq-MHm~I7h2!p4qpUXO@geCyLIJras literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_view_as_list_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_view_as_list_light.png new file mode 100644 index 0000000000000000000000000000000000000000..6d259be106c7bf3b48b82968b1ae39fb26f7a343 GIT binary patch literal 335 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-r0X`wFKpF_NVL(GeLq|tPUtix4 z42+D7jE#-qBr*di50`>7fC`Y+0NF|@%*{Xx6iR~pf*F|Ec!Y$-rM2vG@(YVf%POm? zYijG8+q))Co;rQT%vpPrHd+GJ)_J-(hIn+oy&BEcpdi3{;mzE=^QT35I+qttrYbIcda z#LbU7__FBn#+Z3)f0?%8lFV6mr3<15UX@F&)`%XLOwLakJ2k&kPOh VzM+5ErOH6z;_2$=vd$@?2>`X|XkGvS literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_volume_on.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_volume_on.png new file mode 100644 index 0000000000000000000000000000000000000000..96b42d1c5e5d04ac96f4c2c5dc3b77da1ec60f31 GIT binary patch literal 1078 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBgK_VC)a@32_B-|Br$}69S#@J_Z1z zq_rf-FPP!%!IPOxJKLq#vS@_u<4%(0*jprXYVnELGn`ikE?6>UL&lM9C1+gatGjxR zPS!jolGZyZ#fDSJbT<#bOQhVoiH!Q&t&3UhC1OPzRh{~03J9mhD;=M1UdDGochywy zX=349ms@yPYWc?*L@hL1xvO?*O!Hy4hQv}fJLXx-1a-Kwz0^FFr+2l+0Mp7vPZ!6K zinzB|p9cp!iX3}*fA)m9&V}C{xMUpzHM=-8Iyjp4e!o|}zJABUq<43$i;dURJo{Nw z_Uz5Oo8>oG#vaeg%6gZWx6m=DfGPN9&yu>Mh9YaHZ!wQC?^uD5=jS=Y9#fhFU=y)KAJYcoBPWv3(c)g?OZxq&C$n-4=Nu`3}J1XYLJmRQO@^J zvaRBp1qYYy5Bk*JsV0&ZAlRJjd&r_Dm`&`;j=x8rGBfmOu;_oy`hD?4V&+BZiq(d9 zBIeDmzOVlLLuqnnZ%spo-J^$>)1Oz=A2gf$ef^_U+vgPy%r_oo9gdEf#V(>x8JWu-{q7fC^=qZq1ksIx3wAB7545yyo|*DIOrqW3>uGh( r<@Y7Bzj?n}^Y^^|YkuqPul4tJnm(Tuem@MD+88`t{an^LB{Ts5bI-r< literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_volume_on_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_volume_on_light.png new file mode 100644 index 0000000000000000000000000000000000000000..1335d49b7e62e7b811f281ca4525e5e950b35571 GIT binary patch literal 1043 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBgK_V2lay32_B-k%5DQgSNJ|ii(PY zf`W{UjIpt?o}M01L|t9o+S=OO+#D!kU|;|g0Wu5?4S}*cIyyjxzP`SxsVPJdr~oJq zWE&Y70U1CNsKCU;1R@I&hiHMw0;PazfVvHyG9*78<8jxlr1wb}L0azGhDVz(@4iSeagG&LqXFYxP0Ry+B zB*-tAfsu)sg@uisgOiJ!hnJU+UqDDiR7_k-T2@Y8K~Y&nT~kX(SKr9k#LV2n+Sb9* z*~Qh(!_&*#$Im}7G%P$KGA1@IAu%a6Eh954J2x*czo4+NsJNuEs;0KKzM-M1xuv7C ztGlPSuYbbC$y26In?7UaEbD;BpMmlG$<%bqZ>zR$y|GX(Je7}w@dE*V^InsJwr%WD(q=#La zd93inUj59&^&5Mgi#PF1{BylQ*}r?zCpj_EL!E6?bfOKG1!~3V1p0@he!j50a$Rdk z*5YjscAj!mSdgj}G;4ucc+9rE57YJq8!ldd<%?H%&4HKtT25BkPo{maJ{^DaQv{#! zjaiG_ynW0yW&Td%kc8V>e zK=7KmkEZ0Z#9&>UStXAxgD1%SJyxP~m~YMMxu&-5^Q9I9tIsGhk~uKTYQ|NGH=0hn zH_g}t=2oobyb;!7_S8W3^akeFS?Phw6GH6kQVo`-%xLqqOBdpRl7OQ0yw#o{Qo>jf?V@Yb{p>yr%-rc|X-@H4!c%G(!B`9lqy85}Sb4q9e0O6-*VgLXD literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_website.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_website.png new file mode 100644 index 0000000000000000000000000000000000000000..ae7581b4fbf2c5feb97bddfd71c9b70f615cbbdd GIT binary patch literal 1442 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBgK_V0;|l6XFWw{vQRyIs`WINqqxG z^TLuKzhH*5r#V?P;zxs^Cq-RS|Tc%z-RE-?qsU{ihI7`U|VT3B8D+?99al^+|-UGzZTRdAl_w|KiNTR&!AJ@`9C ztZl{Ylr@@8^&8EZ&dlqxa{fFyw)wK)KZXYd+Pt|L_NN>sR!zNqQgHKywrd~0M%`n6 zRi*qo@7s)-nM)TGZEaDMm}Ff2{MhspVp}vy&T6P?S~N`VS-s(MB(JltzP$Rn31|EQ zE1C=UGp|_2Cw+Bl-=PPp(GOlOxpJ!ikovl73>UYY{@2nUY%n$aTP({hQ7#{Yb>>SF zEd1m@u}V%m7|F2Gl}qNfOhbb~^NGbfm8E!uPtJDp`g&epbA!=!`o& zKK-4Nw8{qEZJjKj_P6CT<{%(>I>WckyBuNHs) zTg#oQ?cXRccSFTbA2!9PnDdN#Y)_pClQ!^Que(s#;Ztbzs%g`%8}#xpN*QE$7fA6Q zT54A`XTE^4Uh5e#0@=a3TCuMo#yv^Ga#(zy^w;j9q z!Poux_WQ9Givu3?pV*#|Ez=~T6v%L~l!f61F@`A3w=>g8>- zdnTrQ2fy5Y#@Nbq-a+C-o^<{Tle3D?zsGUOw7%qj)w+L$qAl0UfF7pTi5}~wu4wgc zXp{3$*L-XG``X%&1r7~tsS$3`Q!Z)#`6uS3g*@Me+<>!&k(vi z1z3JDJK{2IB(O{c_;AB aSNVljQDui;o!<-0g$$mqelF{r5}E)dh?Nfj literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_website_light.png b/MeditationAssistant/src/main/res/drawable-hdpi/ic_action_website_light.png new file mode 100644 index 0000000000000000000000000000000000000000..01fcdbbf30c51908fd50362067f72f4e90687f13 GIT binary patch literal 1358 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBgK_U|bmB6XFWwA_E5p2V-MnZEbB8 z6%_>q1sNF`DJdzSh@PGvP*7c6-P+pP+}s=}VqjpPtE;P_pV0ap)^1#%(Qp(zF{1epv35GkNC2tYOpC<5U^+ym!Aj78?6iNMvv)c_fA zHrz%a15F&6Yb+qh3XGxdk|4ie21X`k78X`Eb`DN1E^Z!PUOs*SL1AH0aS2H&X<0dW z1!XmLO)YI5T|IpRLt_(DGjj_oYa2Uz2PbD&H+K(DA3y(qz@Xre(6I1`$f)R;*!cK_ zq~w&;^o)$mtn8fJyu5ujwV_;yq=;`7ZA|d(qAb0fTFb1{<`Yxv=!(<;Vxhf20|*W=bq?o-^*yw7Oq@3MO_=MQf$kC-%7XP?_fm7j&C^_^2LfB1S? zS(o*;*NvFDH5Sox_9&g?stL~7Bz&W-X!h2{?9)DlM}M z^mw~}OuUpp=s(s4+uhD{?6SLXNUV0#x~)t%tb#XZeTC|Fx{`l(67y|y!txEGzV zvAOkh=g)VypRlN@%sstnP77PlCZ!EC4@Oo5W&bh%J}Kod-)y&wx!DJFcypBIxJk)P zp40G2-PyG6RsBCJ)+N$?4s*^~f7t4~u7oLe660LaWHrw7v9CI`4Z9D>F`Q)Q;fc*~ zS2!({6taEQp~V^YjMZuXEsr;}HZW~{wW=dyj$?2+SH|u`6Lgs7YCbp?BK?Er zlkQXF>x^=W@ulK77ysTm_36>p#}4yYU3~sEIm{D$&d$(o zx1lPZ#llfoaI!dKMtzS;xTGa_d^Y<6CT0^s%@4u$-_}pKF8OoDfwsGnJR2K4`eH)r z%i@gQg}d-+JwBtjXkty>s?zvg!`Kc%^OcH=c74(5@3oy*{WZ?$Lg$Xua95vB->W7K zUv$m(T9;XDmS31RO<=k4g2R_THT?fA+t__YP+jKN9ljrRdp0OYR`f6Xwo7?Kr{jGa zvoC85Cp5md;muJy^~J=9Lv{j>#0Qy3eeRlt{+EnPx#32;bRa{vGf6951U69E94oEQKA00(qQO+^RX3=ar4Hhd1=_W%F@0%A)?L;(MX zkIcUS00VDHL_t&-8O6a}sMrG>$KmfebLP-&bhc^6g}2!SE+&z&OldCIg_km{D5)(q zFJ;M=mG(j@FImdCQC1QwDcpF;)ktGS7cHmgWFMMudy_hF*Kw#8s?EitWy; zwf5S}mp+k^;@T1sSy5wL>l`A#z9l3FrE24Y(}BScrSVN|(xA)dZ6J*j_^qb9645=p>%_zi`MJY& zGz45^N9d@ztY&E%bh3c8e8e`y0+mg?!-utoIcbm~Bw;QpDz9*SYE(UkwbkyVQllB` zIL325yAiO(ZFZzV4#i|!An!URboiv!4o^=^i)=|!XVy;$i1nQ(=1-~zOTc=s#w6iB zi#^yKN>Vda1nc$cPU6+}BQM%T{$LWWa~C2q;4S$RUc(l$oX#XQ zx;A3tvV@qHNw|sK2v`HoNr+uJfLZh-3cu8)Nl3z-sBCds8pgC(t%y+l%t)N*OWs#A zILoQr?PgR|mLxxA7;mD|=fifV;Uv}|7A5k@Ku5yu$X<4`gC7{QfsMs)CNaZmA{!MD z+`yNJ1(wLpIxmenpD+BCeTt|Ix|MkeIe;Wy$a+LnWIshdt!W7%iJeSmKFfTXr(N#t zOwM27WLCN#BBF!!7^fta78z2Z)6PnZn8TP|Nt|2{vbtX76`plYosb6k4^;job0{)$ ZzXSdO_*pUmDHi|$002ovPDHLkV1f?a#AE;f literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/list_focused_buddhism.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/list_focused_buddhism.9.png new file mode 100644 index 0000000000000000000000000000000000000000..a2951bd4c4329ffe619b09f3f37337120c5c3ba5 GIT binary patch literal 148 zcmeAS@N?(olHy`uVBq!ia0vp^+#t-s1|(OmDOUqh(Vi}jArj%qDF;~oPi&Exxb)zh z;}6dmZ_IEKoD}=hymwpIf9AP{+-cAM*YiZrl$8AU|L^$&Cr%uBz$@Ht$?R%)xxP); xfc3wGWX%UHwUkc^oV*j{CnWQR|1n@<_&&*kIrHbu|3GUPJYD@<);T3K0RaE6HSGWZ literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/list_focused_holo.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/list_focused_holo.9.png new file mode 100644 index 0000000000000000000000000000000000000000..555270842a739eb45d404ab473ad38a4c730240c GIT binary patch literal 191 zcmeAS@N?(olHy`uVBq!ia0vp^+#t-s1|(OmDOUqhEX7WqAsj$Z!;#Vf2?p zbb>IW`N`93fr5#iE{-7*Q>RY2$k|}PUG3I8+hq?M&UySt({#?YOY9F7 zV)|4jusAQAw~U49z^wIm)#n)N-o9e&+IDtd30r~4TeZ_)uKQd*6*KFj^h@OhGw-CF i@bOgmX?1Mk5ox7hDXx8`mUDoXF?hQAxvX2?p zbb>IW`N`93fr2)kE{-7*QBRJJkl{&7FVVepxUS$Rt1LT2VAvn7lLLt0oo!v4%( tpjG6n=4tr&fORvYRP%q%M>EqU82;Q9of*be(FHVz!PC{xWt~$(699PnDoy|Z literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/list_pressed_buddhism.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/list_pressed_buddhism.9.png new file mode 100644 index 0000000000000000000000000000000000000000..74e43594f2d2802d4e28d7e1092f6be4f09b1f75 GIT binary patch literal 113 zcmeAS@N?(olHy`uVBq!ia0vp^+#t-s1|(OmDOUqh7M?DSArj%qDF;~oPi&Exxb)zh z%gg<(6E3zWrDSF8n!l~2?p zbb>IW`N`93fr5^nE{-7*QD_LZ%D`aoRl?HIGCc%n7=x#)pUXO@geCyJM=ZAh literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/list_pressed_holo_light.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/list_pressed_holo_light.9.png new file mode 100644 index 0000000000000000000000000000000000000000..5654cd69429fd0a3502a05b5f827bffab89cc7e0 GIT binary patch literal 159 zcmeAS@N?(olHy`uVBq!ia0vp^+#t-s1|(OmDOUqhEX7WqAsj$Z!;#Vf2?p zbb>IW`N`93fr5^nE{-7*QD_LZ%D`aoRl?HIGCc%n7=x#)pUXO@geCyJM=ZAh literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/list_selector_disabled_holo_dark.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/list_selector_disabled_holo_dark.9.png new file mode 100644 index 0000000000000000000000000000000000000000..f6fd30dcdc9c39c836e509486854f9da03486892 GIT binary patch literal 189 zcmeAS@N?(olHy`uVBq!ia0vp^;y~=k!3HF){@Qy1DVAa<&kznEsNqQI0P;BtJR*x3 z7`Qt@n9=;?>9s(?cuyC{kcif|*A4j^95`Gq9-KV8B6o6ra`I!Z80pW;7d5zZGhRBg zm{FnhT6Xzih3ZMUGkfBc^kAT_eS7{3zPQ8d#DAm9s(?cuyC{kcif|*Eb3_81S$-+V)J@yPBVWyvqG&GeYz~KYxJdw0eeyIoHJnOEfn# R{sUUY;OXk;vd$@?2>|r{LWckV literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/menu_dropdown_panel_buddhism.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/menu_dropdown_panel_buddhism.9.png new file mode 100644 index 0000000000000000000000000000000000000000..2c7f561234ef003a7fa5e13713e17b5a73ab425a GIT binary patch literal 1236 zcmV;_1S|WAP)O)!LjyrfOPC_7r5JDghOQy~=f2K2zowTcI*DFO% z8z&vl=Q-G!JqgSI&X+&pD4uY#WE6{TUh>23-mwN62q!b5foLF{XuydWODtl^y-tR| zH!-Rcm>OkjeQWOD+o&Bq*a9#KW=fIrdanP}vmEJbr=sMPEU%e;OBI{52EK-UjvWdr zl+R_0w6*@D*>7*immk~Ij;BGTL@MI!+IoU@*dRg}0K zp7jX9I+qs0KXm98qWN}9=?I`0MhOU3`f0CKY7qo~FX8MoB077RR5n}0Kd=lsr$79T z`(eB8WPw0;Bb9yLmKxAEaM8rRj?n|5)?q)#9OloZ%IS?Ed z2*}lqTcYz-_~>io&ZLRqUJv3=9~ZdAcri+6B?w%!NsAyb1cX3*a5i*b;>2*j6Nr>g z2M29-O&BM5(YIw08VGhv1R=p_AoAb`5Cnm(fzA;IJ);=JI5rFx@!r=IbS6y<55OAO zDrC^E1~Fty1BiFdhVDz87#=FFNxG=nAX0otuIa6>kvo$nhDQJb;{>{=#URc)5O16f z-Iq8qJnjVgZCJ&uV7={@LTDhSus0A>8oHqC7X+fkh$)_XjuE(^Ygtnc#-6gKwByQ) zxs)}vbwnNnuOsBjdUn>t5O}|-t*ocq5?$ZJ%35xLr**{hZm)?qLrMg@Onqq1znHhz zglfV<0ekoLS-1Oo?J{Y%VyskF@p8TUid!2+yRQ}q`+daI?tR2rzs_!!k@QE)w4dGa zt2Pn9L_1Z1bs+#wf z8EtlQ3nM?rak3nc{NfpN=2sz881@QX{S%}6kuyv{33ZZ0Cm@FK_ ziVe*jT)HWY8(Iv>LdXSDoWa&w!-9280eT8V4v4fO zt?%afIhT=xp{1u&{VOs>_gyUjqf7`!k%dq)b2V$Qv~=ikU@raK21(8;M!#31Jgsld y{c{I;NcYX%1yj@4l7a7Po2=xw4zW-51pN;pA{RON76JYM0000|-DE)DqUVH>W5Cn77v!Dkh#3Z;$ zc6X+`{i>&X9b#s2qxeT=8LGNwrt0ge`l{EUxk8dEOiTZ*ss>gde+)otx8V#-N9|)~ z{+8=M2SYX(^p6qZ4cFVrwvw28BgsBABTAx~GGiwE*I*hzuM}kKI?Tc@%(+EKaR6h7 zFmj1QBq4Z*8EaGe4zgf>~dGXcun2vcGQj`!|fF@WOQMbIQkI|zVtPx0^B&ZZH&bZOgS$wG%ak%yfN1b3o zpF831x0WFn-$OD0-RVGJO9PvOmktHDZR>JAO6NnAVng8qpK5QoS#QfGPIJFl z-K_6S2a^KpPS`K%SbHr3B5>NI0eCW?HkkBn_A!wYKm@}u(=sy~7Bc94?N&h9ThPl}-2f)NE2J7j&#tRymC3<0003$Nkl*oX-X$i=vTvx^sDAnb(Aa~NYBBqX%9MvO6hmC_HB$HD-FU;ghk zuK~0gKFHT)G;*)-W$7>A5dx+!ElB2Xl3~l&gmMvv08B^Uypl2H08C#cAQ?!8ca=iV zK+l-nGkKmnQ4}@r;rxqL*T7|2t}(`5UDxLz2=3YjC4)3gv$t*AqvxaV`xh;k7Ghae zj1YQI%s~t08$y#Kfj*i W(hwfd;(_!40000C3<0003kNklF_L-*X%UYwPkR(Z>zVE}PY3^B;byhGVWEh64>$>l{u5VT_ zQwYI$2%*jjW)7jtVg<7Vv4UYijAPayMlo9uV;CNY5ezRxJ4OVe6(b7KhLM42!N@{( z$EZMd#S}$>f*`oi?n|4V=r(RwOj(u@*#ew>-$ybKdJo39dyt{Lg{Z2^C+%PP)Pg|z z-C3<0005~NklVlOUB*B$8&;zIk(CAiAqFap~09m+G;{{yFh6@;tCx8HoedDx% zAc4~V?V??_uQR{Q%z-GBs_INDcN_;hIRTM2GnQ8FFK(YH;lz7lSVs} z8qFjOOPa1nkw`T%Cw7{0m<2WCL}t31GLWVmCQs9{k7pj4JTiV8YhE*%tr?4;L4jpn z;#AWlBW;n1D#Gz54Y8jZj12;!Eg3T_VD%s)XD1by35e8AO{V;BFyE&FGY3)>piU|< z3qb6Rl|0N6kmO-pK$3-70g@by2asf7Jc7gz;{zmK7@r{V!2|$_2PPm$^e`bnqJ;?w z5*>`_Yb8;(M1XXsCEdT%j literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/spinner_ab_pressed_buddhism.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/spinner_ab_pressed_buddhism.9.png new file mode 100644 index 0000000000000000000000000000000000000000..dda5bd5165ec360c30f771cfce397f0a463ae6b3 GIT binary patch literal 461 zcmV;;0W$uHP)C3<0004$Nkl3GZTjt&51YsE77>04HX_^Du6?3nY9Uz2$VT+rl`SyK3CzvRT z?sQ%E;4AlkKj1`d+y1z&`$bM3$MK`cMEW3{kmER?1d}Am6J@g8n%TDfp)f=7cF7wT)(^ zgb;T-sH$pT6vff9tdmp>hU9r3Kr(^nd9TtiXOIUdy!Y@(@*)M(hhT&h%n(EhW(*=6 zGX)Wfxdai0p@9g&&_cLl=0Lb&=0dn(mO!{*mO@s?us~MDutHYD)OCHxvg{tp0CM-8 zTgi3pSGiH9X&OK>N9gph6oQX~dghI}gec4M8Wtgqen+rUsl#v7tE8rBCd?R?G-!?$ zUXV|rwuVtluY;rYzbL(_<@!y%$k@~?o{1?Z^ySwdA(7P{ocvLC00000NkvXXu0mjf DGIG{R literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/tab_selected_buddhism.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/tab_selected_buddhism.9.png new file mode 100644 index 0000000000000000000000000000000000000000..1e8a2448c1e860a415615009ea95eab9c9b75259 GIT binary patch literal 101 zcmeAS@N?(olHy`uVBq!ia0vp^tU%1i!3HFsuehcLq;x!89780+lT#WR{s&087#caT zI+*bMQTLtjuuy{gj?c}|dWi#RyrPa@7#JDu9oJ!QT4QwssE@(Z)z4*}Q$iB}t2-OZ literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/tab_selected_focused_buddhism.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/tab_selected_focused_buddhism.9.png new file mode 100644 index 0000000000000000000000000000000000000000..8a01a9dc28bf9a040a8d4c631eb2bd29a3a15b15 GIT binary patch literal 107 zcmeAS@N?(olHy`uVBq!ia0vp^tU%1i!3HFsuehcLq>MaW9780+lT#WR{s&087#cOP z$hB>nb%5n*_(7#VzynKJVo+29D&&EVMaW9780+lT#WR{s&087#cOP z+}mG&pF>zgL}ZP+?}Uei65MxuZid!NINWOQQK)KQV3?p}%G^*_775hN;OXk;vd$@? F2>^W89sU3S literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/tab_unselected_buddhism.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/tab_unselected_buddhism.9.png new file mode 100644 index 0000000000000000000000000000000000000000..2d7c0134ae9e9da2952092023155b55a0ba3c63f GIT binary patch literal 103 zcmeAS@N?(olHy`uVBq!ia0vp^tU%1c!3HD^Kbl$tDLqdY#}JO_+ za&4Pt9bkDH{@>1dmI8CYZo^$=ZO0RJ3c6Fm|0Xib?2Hw->&dXaL6-U8!JphfBN#kg L{an^LB{Ts5BH1CY literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-hdpi/tab_unselected_pressed_buddhism.9.png b/MeditationAssistant/src/main/res/drawable-hdpi/tab_unselected_pressed_buddhism.9.png new file mode 100644 index 0000000000000000000000000000000000000000..5df03dee786caa286b86b7cecdf0f5a3b62368c8 GIT binary patch literal 112 zcmeAS@N?(olHy`uVBq!ia0vp^tU%1c!3HD^Kbl$tDRWO3#}JO_+ z_x9J{=MWYV5m}?|JArYgTe~DWM4f`XeCV literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_accounts.png b/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_accounts.png new file mode 100644 index 0000000000000000000000000000000000000000..e83c6efe61e95840d97eb4e501914479e0a8c288 GIT binary patch literal 410 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM3?#3wJbMaAwFLNtxB}__0}T{zKf4HYhfYb5 zUoZm;I|q+|grtUsVN%QA# zC!G?{ttfWeS5dpPgmF!vYxW+UUn`l{1kT;qV7$s$Y=c{A;2!pDkqx(+yhSE3&19Oz hXVj_^dF_I{TxqA+$77rCeFr*{!PC{xWt~$(697$_^gI9n literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_accounts_light.png b/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_accounts_light.png new file mode 100644 index 0000000000000000000000000000000000000000..6d09956688891ce5f83544d7933e193316dbd5fd GIT binary patch literal 382 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM3?#3wJbMaA6$SW&xB_V)Fg7;U*4CDhkpYrG zprN5*W@ZKyG&D3cH8lk?3=9nP^z?vSBO@aq8^{2X`uh4nE|3ib5C%{s1OP>V44@zo zKp1eY-X#AH6csIeet;=k|pN8cGpnO}SQ>zm_~jHV~A zR>}7^?)$Lq?_~yuxB1V`nujwxq&hq6En--9;a7Hml2k(uFDH)|Kf{#l9UEMt?SHZ6 ziHQ{39}}zisuP>i8Sl%WeBqW-V%V$dJC-gkE{neXzvVT@dfxw=f|Yw0a>ocUujD>= hm(OFuGIh%d@=I%l|7UbF=KvkZ;OXk;vd$@?2>^dPcA@|P literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_brightness_low.png b/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_brightness_low.png new file mode 100644 index 0000000000000000000000000000000000000000..feef8d60de9ae2c25cfe2632b8fdea408b2a11f5 GIT binary patch literal 418 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM3?#3wJbMaAwFmfwxB}__g8*br{4WS}if&1e zUoZm`GYbc&u!w}3x|Xhixvi(SUvO+vMtNWV#7R@;EZ($j$Ijh*_w7G$_~?n#XCo{{ zmQCQMS! zk~Z=PPDtcGv3kerM_T{yv2mH)>l1h3)%wuDaW->p!};#j2Tw3ZBrjW^*UkHR#-yr` zc{|q$A6NCd^ZEP+C!JQ~38L?+nr5;{-SF&xrQoru{l_Gs?eFKMU)g;vVYj3(+x&?M lxBH)@cl=MbP0l+XkKMxcC* literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_chat.png b/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_chat.png new file mode 100644 index 0000000000000000000000000000000000000000..3aae6974f32d34c5d01582cf3bb10fdb64652f45 GIT binary patch literal 250 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM3?#3wJbMaA*$4Q9xB}__6aeSlzp{Wvh?WHT z1v98?XaJ|6D z&RoX1!Xm)QLx8E};G;V{1)Odg-I6*7+a^3nX=l(Y;j~j>|ETDFpofXkErpY@jzz#> lngeT#>V@W(*2E7?3`d`ESI7I_4Fg)h;OXk;vd$@?2>{~bc1-{P literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_chat_light.png b/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_chat_light.png new file mode 100644 index 0000000000000000000000000000000000000000..0f1f6ee1a773f207c273ccbe52c4d88d67f76854 GIT binary patch literal 250 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM3?#3wJbMaA*$4Q9xB_WYQ&R&214BbYBO@aS z140@b8v_|Y5-1Ll1v20OBK}mWRUc@CXi1P?FoUdumaVI2Xk=7;d_r<|ean=o(`L!c zeensXAk@>vF+?LcIYDAcL#s5iL8EGg>jg$@<}%I|76DEk0!%FjAI0z#aJp%9bLt%I zn(!c@nZd7w(@u`%f%CKmNmizw6GBXXI20Om8o4;U7qD|0AAZ2f&@`9Z`L^QoGe8R% NJYD@<);T3K0RUoiLlyu4 literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_downcloud.png b/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_downcloud.png new file mode 100644 index 0000000000000000000000000000000000000000..3ae803348f45ef6c37e5fc6a89140262e8dc380e GIT binary patch literal 644 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM3?#3wJbQ|Pfsr-9C&cytDER+>eo9?EFkHe* zg8YIR&RjTu?ee9YH~KFo+}(Kl+?9P*+p@3wJ71j{wfpp;$+1ccCnT~+)Zfa_ykoRe zaxL4Ey&Rlbwd=b!?=amSzsW7;K&pVw*}$##6Sb>NQWhNVv3A)adbmx{%YWSzP|$n2 zIEGZj?LBoh?}&j&%frWyZ+ITwbA~51E$!I%`YCxj<)WH9S8uuh^bd3QW!>$2Op}#` z&0d!Y#_kTe_tsw_H)9e@x6;((D>p=4JSiWydwzRd>>HuA(`G5etl{yPwb*aEt3>Z) zc_k~CP1{{>Jlq_xan0UaQ+aFz5@k8Ray<-N{PEjM%=Bs`V7E7PaT)4P2Pm6PEt3vFrf2N0L-`>4+=C{MjXAWLAw$fjpKjGuL3#&eT q;4(-yg}Fp_1aETWe=kaX_ z1eQ#M8a=q|l+$Vhj4Ve3Dmk3*h1D>iM&yV>snKZi02D@G2u2|U%||r20>xn%Sb0EE zjiah@J853g5?6ZAF9;zVg2LgjJgktjoDV`U42yH1XufEX&o=}GcO*Z^?@Ta|H1Fk@ zkif7(AkOIau=Ro-6g^$OLLg+dt`Z0Nl|YFhgCgz_gveni5QyJv$(k4J^uKPbY0Wzt zLNsKjdA6SOiutJCnE;Eid$v&AQ1k{b;TSO~?pl)d)(7aIU?KIOcp|453OB$?wLz(Y zl_nHcYY_xP4X}|=VS2qJ;C z1bM+7^wJ4kM$}!wYM+V4jU4S3SkA$+wTTL_`B{PG{cH#@mZ^YpCP=YiKAxQAyOK1= zyhc-Ijtu}y(Z!iH)Jd2$m{Eg)(3%V;1VISWKx$!=3dPKr5mS=j3YPjm5raf$pm=Hg zr&JPKV*SOZtA#HvR$GS-iv7Zgjq$YNy>^LY-NzP^a6~4?I$}l1#I_URe$OuRTvGEp zsS`awM%$U@)DG81*Z7^*55J#EcILcNa5R#$ZM`Lhm^F2(=4)WHwPqG)b57)Q9 z`t|wi(R8#w_MnTu|J?_jy$^SsyWCmo+4p8tI{Q}O&Qo7TW|F>JraP*1K3DwiJxA`N z!-Kv$*z}<5Y{und#eL}$2R7FpyE&NJq?R^*bpf5fcB<{b`|Z;Noc`I+@6op(M?cq1 zXE*JkFwJJy5NS)_LuB3DI{eF*DV^*0R>|)E3KljqyJr_Ku}@|;D7uNg@Fo{ATyDv| zB#~Jvp3fXTS2*+MPxGT6p+0mZ*Vc3O`rlc2^hobe+i%DJs=Z&?QF<`tbh7N?*v8X} zMeJnOi+#w+*+JLfjJ|9Birz_oa=56dQi|o3D9DE`qqnl7JNvrN?(41d*QE=)7Mdz> z(*O^Q_`199ZQ4F{YHIiG(#IpVGjAltCbd0>D!1f(y6(Kye#khL7TRKp4bc1_M|3w@ zue8n-6!In0c`+aSO}}jXcz=@miFurBl-IA_^;eHCURaP-Nyhp-lRrGN QRmJ~?7E>|VYp81e2O(qhO8@`> literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_flash_on.png b/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_flash_on.png new file mode 100644 index 0000000000000000000000000000000000000000..e177e1eb35a48faa1b917f33a06ed2be820a47e7 GIT binary patch literal 319 zcmV-F0l@x=P)_s2s_#4?wmT(1M@T zvY;AhP!N(~Yk-Eg6EYkmPpl6X1J!CF8JGyP;1X3V00s{;(4a#=%mFp<2aui*#Q%YK zBhaEZ_$(sm1E2+pKm*obG2}GR@C-t}AjSd}pdtQ1%nhYMW_|(UD4+#TDYgJ+0MIAq zK=w2!zZ+=y3POex9mybtKnqfUR3;Fg2jVoK1^=jR!6cx8#y}hiH2e`Uh7;`rpzE1{ zigyF?QlR1Uh&7xP3qTRw0K^GE3;s~u0#Xb_S4%LNQersKK}3lqqdp)QdH~WHLK$gg RkoW)q002ovPDHLkV1j|9bIkw% literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_flash_on_light.png b/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_flash_on_light.png new file mode 100644 index 0000000000000000000000000000000000000000..ed995c0c5650eea4e3f76b962dc52ae00354c7c0 GIT binary patch literal 356 zcmV-q0h|7bP) za-apjsbYblp9nwgo|=HI`6 z9KeXS28Syn<98s{47A`4#TLK}00xsLkX;DnuK-5!K0<~Q9mybt#>U3p|NsB@2QqI1 z4etTc|EX#LFsbGNgGTMwuV2kqu3ULZjNzpCfDsr(y}&rwbLPyMZNwT*v<0Au1{$7t z{`~oNpr*f6w}2D_F_JSSnu*a%FdqG90000BvzU*XX^1gX*cE$vroADe!sHh+e!y{wN$06k{R3ZdZg3pmWXGw|*?g-q5 zYb48kk}`r0fxlshUDUCA!N zn1wxCYL(V8efLs?X7Ucg;a|pa%G(8o%#e3hQqBq(5W9Rp|&N?G|zEFv(CHMzQ WbZ;54`*?T&0000wbxOCl%wiJf<1~?UOH*@8b8}1cG&MDK^;6+Y3}wtr)r$-@ z6$p6H(7k!p3652q+$$X$nXE(RczR6@kL&a0)MLDSXt|EoqBHu-)~s36l_jDq%wfpL q*!I+7uJ?`R9Zf9h3Y#vNPh)(m!TtTJlKoataCy4=xvX`K>~X!Ixdl6*pJCXl!YlcS>aPbnc_eElLGvN}fC6XjnEeWDED|N4vS#GaX!! z;(EVz!9I)Ck>YO60sWgV`jyNmGfA;cTU5z!ZX@Xzy>)7!1=mdTMU$t0s*SmjpnQ3! vQyY7+Ay>c`XVtHVmd*G#?ML))=bsGG1gTe~DWM4fi?E?a literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_full_screen_light.png b/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_full_screen_light.png new file mode 100644 index 0000000000000000000000000000000000000000..f493a47106b713c22db8205b2f4fc6ecf055066a GIT binary patch literal 311 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM3?#3wJbMaAIR*HHxB_WoV`FV?ZBtWI0|Ns+ zJw07rU7(1Ok&&UHA&>zif#N_ekPQK7Z1=?NNkCJ?N`m}?8Mt_46%>_}Ei4_KT?31X zOZq2FoHVO*&zm1W6@8vAjv*SsdnY*Z9ai9Bna;3~MWf}`|NmKUl@=D9SefM$Zq1t=FX;PnJ5`w=VqhNblHupP6SwHbiAP zgywEMa-H`^)Pe7uzVoYgZOsz23SaQ?<+}OOF9W?-Rqxuen)%y#<;H1@rK*_;Vm-lk f^gfoowLd2<=FPre%7>*7=rRURS3j3^P6~dPsncf}rHgj}C0jjR978nDubp&Ts8xZ(mGSfvlb`?B_ZDmD z`}Ds}bV+|Gw}+udkIQ6<+L5(xAxC#9etTv6Jowz4_gn0DJ8=q}{xy4@>c8o-2Vz|x zI8JBR$$99w>f|A2Tc<}$9}jdx)=jEBQBn&Q j`&g~me@W%n58;?dOZKY%d2g(M4r1_h^>bP0l+XkKluV1{ literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_go_to_today_light.png b/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_go_to_today_light.png new file mode 100644 index 0000000000000000000000000000000000000000..6d28956443b6f049faca93fff61cd990fcc0d552 GIT binary patch literal 280 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaN3?zjj6;1;wg8-ipS0D`m+S=MCCML$l#ztUZ zXlMvw14#%2BEH>Q$pEN9pd`pIn1PX*&CA=z*RQvK+VmMSXZ`5ts0GTkd%8G=NQ5UR zC`cJ-85wYJI^0b1XJvgXbkOG5&FcT}?$!SP<|okqQsA{98{2#aSyqE~MvY@97#=q; z_8k7Wc>iPeIiDA;f6Ur*ctu3u3XZ1?SO5HH3}y@Y{GZ)t=7a@F?#h!k{bOTm*<@$I zzJljP2FLRaLJ~I`EPArfH5}C3Am5^3)WvgziNWHp#h2wwniE0(^K|udS?83{1OUkk BS@!?{ literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_group.png b/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_group.png new file mode 100644 index 0000000000000000000000000000000000000000..1328891de039f33f555b2dacc342e5827a31bd3f GIT binary patch literal 571 zcmV-B0>u4^P)>D29eIxW!F$3nP!1C}n_T=*S>dP#ICQk&t7YsI!4GZ5962fhx{P{uh$zvITKY$&kVzO z38cK*5|KEJM72-_(JJX9b`B;GdizNz5P=>Nl=(^GMxY~L0ZtoEa4E#V8l*z6rW9@X zkD(CmVF^)>x##N*NFK`KFytxcG&TWBGy+TbFQ8h*ZDJb`d6#FafFvHZBtJmq_iSh40Xz8V&(1U ziTgT?^&6DqtXGNUp38=F7=sqb1}Vh@WWhD`gA3we52R1z=8Yrbmcx7saPkz)EJ#zC z*?v~=;-L{>zkUILbyOuS6A1>#01DNG&BUN2g(B3Mn*;u zE`$LW0SW>EL=Z^A89)<&;y~>{01*Ug0Ro^PgaH(U*aGK5q~L-evy6=3vJf^{%;>OC z*H@q?eM*A-f*BZ@m|0j@+1R-RgoK4f#Kfg#@(T)!N-C>r>KYoGI{PL}nmlFt%vpR(`Y!;@z3l1Y7$PCL_u$K* zrUVAo3*H{L9x-X8s7Yx}^Uk=X*2z8VRPF!ooHOz#ZTvs4`E!to@4@<_a__v|;ufZ9 zNj+1176-2huFxoxl2lnDd2@Eqj4vnjISreaybb;kt-^a`mA&JIe@i}G=A1CVH~X3WiT1>$i;%MyPs`K`eTnlV=loNj(2}v_0Jq}lr*~2(7C&`#tNd_Y$ZX<~BmB2_ aA7vDs$y^+>i#r+U3V<3=?4f4 znf`lw`|p&0D<-}XT literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_new.png b/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_new.png new file mode 100644 index 0000000000000000000000000000000000000000..19a507516b53ed05340c1a84df9272d27d167483 GIT binary patch literal 138 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaN3?zjj6;1;w{s5m4S0Mc#3G_SN%K!?omIV0) zGZYj~*&8!UB^4;3>gnPbB5^r6L4nbLOQCQEZ^ofSBQrCzLN+0;7cx>&T@Njr7#O~p Wu{FQHA=eMoz~JfX=d#Wzp$P!S0V@aq literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_new_light.png b/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_new_light.png new file mode 100644 index 0000000000000000000000000000000000000000..ad43b186545e14cbb2837ecb64fea5e1d031aa57 GIT binary patch literal 138 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaN3?zjj6;1;w{s5m4S0HU@XlP(yU~Ft`WMrgS z$aDoL#99*M7t9b6n%~DFwmJYPpz7)37$R{wIYEKZfJ>op25-ipL?bgZvqCl@t`{;= fQC$x$n;00rnXxs$zaiHT)WG2B>gTe~DWM4f`|=;j literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_next_item.png b/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_next_item.png new file mode 100644 index 0000000000000000000000000000000000000000..c0d3d24b0d5bff9b28995385a6ac21a24272a197 GIT binary patch literal 280 zcmV+z0q6dSP)yAW^A=o`yR}RNEq2*-Pl0L0o`Zq9Ws)WD1SlH{waeCSP7L zoBzwanR${Je`1`U{DHtZ*PxAENJYfOwludzgjWd6pa~lU=|=@V3`v`^fHKUHY-1#< zLq^gkbOJXRBiU;uDnZ!EjM{?>jF22Pk{ChBw+K3Lh5?dOkwh&ByQor^(1HUDkzDg6 zQGy_;Q&-^Y4yH)%uO#mXYJ{y#1l%UO77=cH$O!DNsp&&A9Tndic6Q^sXbfo9qaT_k e^!cCP7d!x{Mp_w~$HW!@00000dzc|L&^B6wcUh zXTJzmdKI;Vst02#Yc1poj5 literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_not_important.png b/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_not_important.png new file mode 100644 index 0000000000000000000000000000000000000000..62bdfc91a3c43a250e8e178e54c3da917ae0382e GIT binary patch literal 458 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM3?#3wJbMaA%?$7faRt)<2PL>F%Mt=~oN-Bz zUogW2=IVC-AY~p#Ri`+C(!TyF5~~W06dW8`YNE1=-KtExoaH95CYPB{_m<4Bubjce z$<=y2)dZ-0t*47)h=k* z?z6&{Z7~&lzOXyrYiqWXKl-9c&7Di;++-V^#-U(ZorYWjzZOo0#OI&R5 z^YPwlj;7|_^1o;FsV}SucvNzv_Rq8M4w z#KZ)s5h$`JdC@MQgA7W7{DK)6nV4DFIk|a+gvBMKq-E69H4O}nOf77k-MsxnLc<~= zqhn$dQqwZBbMgubiyJf!vg82uuJLqn43Usrdhn*uK?4Sdi?bJOohr6;t7xz4#=rmX zD_&NVt$ZZ&Pf4{dvupmf3f?JF4}$sHRpoMdcb(l{$@NmkJ%5g_8GG?W1^s6mB2ymA z>CgRb^{zeSP~Dz=swuZcdv;m>YJ~{d-IsZ;*QG1XQ`&s{@vgHh(`MW)*jkbOaWVVJqg)?e SEIFhDiUdzrKbLh*2~7aFbBgf* literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_pause.png b/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_pause.png new file mode 100644 index 0000000000000000000000000000000000000000..3a4afb8c62d81d4b7dbdd96438cd3bde7dc5e609 GIT binary patch literal 176 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`Gj<(@8%As*hzDGLk}mTdgVvsg@k zCvlDAm;e9&OFGOI%GmYY$jHc#t&{O-apM%@S%0_})UfU9-Jx@XAw;8lS%vV02DcTg zUmb4o`~EWwuuHhobWx#c31fnhjIZm5HwLpVPVi=%)Wvm6tc>M!f{;khwG0;K?q`lH Z4DCmIBy~IHivXR#;OXk;vd$@?2>=^JKJfqm literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_person.png b/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_person.png new file mode 100644 index 0000000000000000000000000000000000000000..f14968908d22834fb29cbf4069435060d5430997 GIT binary patch literal 360 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM3?#3wJbMaAl?M2PxB}__bO%qn(;R>ntCs}% z1v4-)v+)W@tE#E%np)d92Ze6J$PHFNkN45!rT$7?NY>qK+xLn@oaLaf5>CN7PlT$SXEhD3!R;Ip{ v?1?)OX=0PLY=2~8>WSnHlTImboXX$$o&T!wuDh>*&S3C#^>bP0l+XkKeFM;y literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_person_light.png b/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_person_light.png new file mode 100644 index 0000000000000000000000000000000000000000..18dc2ea61c80d3c560fc62e4c57e772e6262d5e9 GIT binary patch literal 350 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM3?#3wJbMaA<}H8C*(iU5I;kr9wIG&BSp2vUT+IjZI0*$jHktD5A*#Xm&Y!OPMZ1c_WI3@OXSYWZrE7f>T=V6`sEwbPXt~TFk*l2 y8!Gv}Um)j!Mug6b1NDx{&ngZkx>Yr9n8x4Z&G#w!sq}GBD0#a2xvX0PpP+4>Dzw;ecn>a4A`O$ShEq^FBxh{pN76U>KmcSw1mRLZ1`r(lW+DVMRHh`zFPMRmiG^KI zNJK_UThGxoC@M3nrnb4IqjSRa8MAm_<{tv83-@$!4AD5hcfv`*1_uGA$k_bY_mls8 zHesyLI=`$-lHp&N$5b<+?=c_e`7f_1E)LkU&q6D1-khcfg-?Z8&!@?$_5_~b(mN&p o{XNrK%@^v7Lgto>=Kq!6dus=a%IRrpO(6eyy85}Sb4q9e0329RQUCw| literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_refresh.png b/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_refresh.png new file mode 100644 index 0000000000000000000000000000000000000000..5e8f5d924db05350bd28b58ea5579c8beeadcd41 GIT binary patch literal 558 zcmV+}0@3}6P)<%+o1cfMO8QJZxj|p&L*$!Mx32*vtKWy8)9Fw!$6^A$&3lG52yl zVlo@0ZYyd4;zEj+;10SF$@qO}t83)KJG^ShYdfYkXeVHdBH7d#1QHa}@oSTLLNP6Z zCIYTvaz|_xu*r2d=2cG2d9YII%V7uYp{}(GkPQq`wB|5ikoq3*qg@Rf;KbCl`LmpR zpr3%bA_Xd?wkC#?Yab<{y6NQad}{#;H$UgL^!Q=P1!o8kasY0>h> wlFX0=vf)8<12h}!=eGaR!Wl%n{{I8M03UIv8TtX3P5=M^07*qoM6N<$f)P3ZfKH!ts? zh{)*J_{8M2^o;DB{DP9wvdXIJn%cUi=9c!3uI|462@@wznKpA)E_NL-gu6b6 z|A=nxI=gboyN^p_bn={k<=oxNHYu#r@_d!{(uP?}WHuJxt#0XYQdN>Zm@sidu;qvE zpS)fCQa!#b;_0+gi`dq`?MLFN2)_`ui@jx@k9v>uO>Ejo&ZP;@_iS0h#=lXdQ8CFWmg`TDRrc(|8(nLr&fdoAA-B%A=IU&{(#z9LPCr;V zXX#zfb8PXNSAzTbmz7R2ej2@N@2!5JKc{8yCkvb13bV}ux|PAx)z4*}Q$iB}ntd7Y literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_ring_volume_light.png b/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_ring_volume_light.png new file mode 100644 index 0000000000000000000000000000000000000000..96fd15a12fac7794be6eebe55939d2f011e87b5c GIT binary patch literal 450 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM3?#3wJbMaA%?a=caRt(FprWE8BO{}&t!-{@ zZftC9U|?WqXsD;Br=z2zudfeen3|db#f^-NfNY=?Pyvt&1Q0e*90=gza4t{;s0P9X zD~Gb-;t*Ll30G4h?Y0Q$IFphfzhDMNCT4a{9zK2nQ89688ChLpb4x25M;BLj4^RJq z!0?EqjGTh<%Bt$xrk0M*-o6Qwrq9axve_M|f1#&~V~B+0-hX6OOIWtSc*X&(!{{VMYa`(^9XQJ-}0_xBn1*Y9MmHxy!FHb_4J OiV06wKbLh*2~7a&!i<#w literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_settings.png b/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_settings.png new file mode 100644 index 0000000000000000000000000000000000000000..19080b62a05b43e30704ba68b38e1ec1469d6394 GIT binary patch literal 242 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaN3?zjj6;1;wg8-ipS0MeL6kzSkVgS@5P!i-9 z%#eCE*=)Lm%u!}tqq1^6!(U0(NkF+oPZ!4!iK)p63M|i56$PQMd1zN`7>FVdQ&MBb@08xQuSpWb4 literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_settings_light.png b/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_settings_light.png new file mode 100644 index 0000000000000000000000000000000000000000..9de1f5ed69f66575c309fe6941c111111d6b98c1 GIT binary patch literal 244 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaN3?zjj6;1;wg8-ipS0D`p+S=NNhK9Pjy2i%F z1_lQD`uavjMnE=@1d5x00gw#@mFpFFfEol!g8YIRn1n=?lvULem_-=7gftI|7SwglCfEK6%4OxLDk$3|wctN%WK!aI;ngf718Ho9Tm>tQI z6F|eW$qpi*;f_GfIZ#7q0qJ8*RjD~DE&58<`B{VPWpb4S@NYkdchFSos ua6q|U9f+x4;Sfp?AbGOu17ZxPiv<7?ac&tv(+wd20000g((4>FF678Uh(W02DMbGBPnS0g3<_5H3V9kP8$9O2Nf}3-;-Jx3&WrDQ{7#?h0ctGqba4#PIG>!bKr%sSl1R!CHO1A77c2L=&heJkSa`Hi^Wb7; zraLbVol#mf%b}39q>wRHG|^AeRkLgd$Lbk#ETs2O+NHrgE68#|ohdJ8*&4r#505@{ z%Ms%FWYNbP0l+XkK D*~@5v literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_sign_out.png b/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_sign_out.png new file mode 100644 index 0000000000000000000000000000000000000000..fc371cb785b4c28fa7bb6f0154884e9fdd1e333b GIT binary patch literal 385 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM3?#3wJbMaAwFLNtxB}__0}T{zKf4HYhfYb5 zUogX2<{2lM4j-{JWjSVMVtz*A=;;YFH!?1bshKqk@ z0QEI^x;TbZ#OoEp2FF0^XAK> z+CQ49a;C=W^V3t???3cnYq_%Uz^)$-9#5{!S6{T9|Ew(I3s&ho^=XlKd9_ z+9vi+F0OvD@yS^^Ma9)MwXOXVCQq30QEdSq29F=iJ|G*|MTR;pge<=d#Wzp$PyAJ9b3? literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_sort_by_size.png b/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_sort_by_size.png new file mode 100644 index 0000000000000000000000000000000000000000..ddcee7c318088c67e148ddbc25553f8d401381ac GIT binary patch literal 229 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaN3?zjj6;1;w#^NA%Cx&(BWL^R}oCO|{#S9GG z!XV7ZFl!D-IeUqxuPgf<9yUfn^TnbXj6fl|0G|+7ApIXVP^pduANswPKgN?1XPkLYf#AoRp4M0K0ByV>Y&W|^jz5#NyJY5_^B&H@OEYSP#qM=Dl z;rLz|E-w!wWgT9YNgE3~*dLvkmgO+V*_VM~%3LAk6zT6k7cww-y85}Sb4q9e0Oepi A8vp7>3JzNd-v~s{r~?T+*;zj%cEMCe_Kl{<7UNdm7UjO`iv8k za#pqk+>`q8lD+-FvtYItPVt88GCr7QFDO{{Jb&ZTs*6guwzy9-*%z~wBhIZ+d(qc6 zkB=G|j!(9^I6Xg0QIV06 zk&=>9S64SSHa0LY(AU>DG&BUVAq*oUBcPy(i3v~;$Oei-M1Uj^0L6hKaDXfVmIo0K zSs>$8k#ZlZL{Q`hnD)A z{|W5Wy}fOVXNlP3*FLY;d~|E7em7;qY~@o=lape&V$2*~ojGw|yCI8v!5{16*O)%s zVD?C64@hIM;b%yB$`HldV9m7Pw#1$M)f`{KUT1IRSo^DBnyVr2q2J|+MRu(3zp*mT tWM!SWCzwfL)oE3!jXzBueZN`1N_?9E_cBkJzjHug>*?y}vd$@?2>?S}f4~3$ literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_upcloud.png b/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_upcloud.png new file mode 100644 index 0000000000000000000000000000000000000000..fb2d43c62b9bea9b73ff911c6b4613f73f7c66d9 GIT binary patch literal 1387 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`Gjk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+m{T%CB1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxKsVXI%s|1+P|wiV z#N6CmN5ROz&_Lh7NZ-&%*U;R`*vQJjKmiJrfVLH-q*(>IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8EkR}&8R-I5=oVMzl_XZ^<`pZ$OmImpPA){ffi_eM3D1{oGuTzrd=COM+4n&cLd=IHa;5RX-@T zIKQ+g85kdF$}r8qu)}W=NFmTQR{lkqz(`5Vami0E%}vcK@pQ3O0?O#6WTsd-8JL(k znV1`xxEdLlSr{5x8aWv_JDOR#8akSonmAg*%)qAC#o5fj(aFWq&D7A<5Qr?DoGe@% zot(^#O)Sk^EF58aJ@bl767!N%VfJPM?S<;Kz^m8FxhOTUB)=#mKR*YS0s=DfOY(~| z@(UE4gH08}GxJjN%Zovg1M#a%YEfocYKmJ?ey##IbgeS6*>2$C#&rIU%MGbc{YIX&@yPm=G}iftc`w59GkJPHG-7zZ3y8 zhDyZ?J_ZKHxt=bLAr-gYT-~kT94K-8P;yiJ z$8aQJMThGK1-5P%C6y$>&em8Sz0&pD_No6g&75^P+;x|S|0l_+d)uE|KChfNuS%%1 zW%B932Tv-VF#oZr(L4V~!dbtm;{k{Ej`L;>>dxY!NsO@-&OXa^k6QL!>=J+T;K6pr zWrkhsr#CBkvY9^HFe{f~e_5*E$EB=3TK2J*a{MeiFMs)dsryb#YRFQZe~sQE=^P37 zv=0hhyEsqNL09Zz=Za@%#J8K&FFn6a@bbCYp}XCp8x&1eM4!<(u6J*0vha&@OFs)~ zRq-CnWvrUw-CtIslOcR+0QS{OzY)~W|;igVo${pGc}X{Yp!ffbbkA4$DAYS z+zG#S`#3(k>bh}ClKnzC^&7>SyJqg+$Qp5Ywb&cCxzF|_ecHb=g!OCOFO4f~hqo~- z6J5ULbs~?#g7ba5mbji32%4)E#Pa1_PuWYMi&t1v8c-r0jj|8sY zj1fI~u|4wbnHcHjtmxc-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxKsVXI%s|1+P|wiV z#N6CmN5ROz&_Lh7NZ-&%*U;R`*vQJjKmiJrfVLH-q*(>IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8EkR}&8R-I5=oVMzl_XZ^<`pZ$OmImpPA){ffi_eM3D1{oGuTzrd=COM+4n&cLd=IHa;5RX-@T zIKQ+g85kdF$}r8qu)}W=NFmTQR{lkqz(`5Vami0E%}vcK@pQ3O0?O#6WTsd-8JL(k znV1`xxEdLlSr{5x8aWv_JDOR#8akSonmAg*%)qAC&CS)!$kf8p&D7A<5Qr??Tum&1 z2DmyIm;uAl6sFfRuec;JFF6%vZzj-Qs9p=adaay`QWHz^i$e1Ab6_bTAS1sdzc?em zK*2fKR3SVwFD1Xc7!)}Wzq+IrWtOF;xE1B+Du6@RDie$CE(R`6ZbnW{jux&?K&Klz zx;VL57`U1mS-M#|Tbj5iLG`AP6Jq*6$LNES22xUi2?5g|hzU>lKn^_Xq~-zhOA#<* ztXoyNhk=1{nWu|mNX4x;Q?0$39YtCA0A~k;(Z0NX`3@IdFa)s%$&LR`MH_a(#ItxuSmP1 zx=O~h@y3e(e;@72tI%T=JIIp3X19ao_XAzMjn6CVS)DF2g&pMh!NQoqyf=X(rrGY? zT+e+sWLuJEp8TA(hGn0okwYN6PjhZT#7oH~M-2lW2Eu zYhRm_qr^qs-Uo5t`Q-SqxV>EQf#RuMJ?M7Kb+bn^Mi9l={pJfFt_` zRQh!VoA|AHE5eUXel^XrDt<|=+Nb>I0w!g+PTdBwDZpXhHv=vLG1fn%zYD z!U?Eu1F1gn2Wpy4qy-5;b=yd_faY=F0d!R~kv^CURCi#|`5*x3s%1p_APlH(3#mQ` z1ZrAIqy<6bSP%u&^qoixxPa=GlIjC{pr#}uEdT}OPEswPc{23_x(cIg!QmrN*|mvO zAA|rk9Vaq~EP?9QkZJ+VgNUXU(6+)MGTez$HZXNEQBEUL5dbSzV;O!CY(fA4002ov JPDHLkV1nn|VhA5E zFmcl4DKlqnK5=R8y^7FX#B`y@|7G|2o0`zS=9p1B==*RKK)l1@NuJL*P^@ zf@}zZJ?wtH!UufIu^v$&1iPRBT!TYU3xVW7ubZxkK z)aM$3BoY@u1(1)I3VE*?a#I!PRmhDU1M-I>PsUYT14;(>H+@90hgnm}=;#2&A#9*}poo!?5s<5|uWw>v0u+I8fefG^ zP!~`EkOWFW#36!kWe`EQMhF)|0(Aiy5E3p9WIzDW9H1d^jc@}Y;y^VJ2LMSRfM`Kx z3;hoTg+*XVkY6wZ6EiCtI|nBZFE5{fsF=8fyrQzYrk1vjuAaV;iK)4jwXL1KgQJtP zho_gfkFQ@)NN8AmLSj-{dUj4;eql*jWmQdWZGBT)`=rTJrcIwYYoD(X2hi|~o-U3d z8t1o83>R)P5NP2)8n>alD|TbT`y|F{=e_^`XRDlwXxp>P-}-mzq}{v+03{Nc{m-f03e4^4b+ekQzdkMm|e*ISR9 zn6f_E=GA7rBHCf;HR{n6);uMNr`+th+OVzwcuiZUOn^nKs f+iVhQ-T#8|nz3r=kDr#uK&i#k)z4*}Q$iB}c45DP literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_website.png b/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_website.png new file mode 100644 index 0000000000000000000000000000000000000000..797c647d7e90efadf225fedc93bd24ee25d90203 GIT binary patch literal 729 zcmV;~0w(>5P)b>jNeLeT#`d{~TAD$>L$0f?K|GZHNq*5u3 zn*}p0pwHCZQ52;{3UF8f9M8tVW>^V-;0yFZAxwt*(2CHLqXo zXQ$q5zZY7`y;F;Wxa5{g98NWhStZy55}joA~j#$PfXGTuzR_ zI9Lcp@Le_n)r?t>trgCM7PtUs;6Z#P{|H#l&uKCPd--00y#t=WTKEb|*B1B$1F#zw zK^I(voqkW^0(&(vM1epx-vxX(VjsnpU?^`ewAt?q!*Z4(0& znKp8&MLo})Z+8NZv5ztKLuh0C6zr=|9*(dV(2+by$Dk7v7(;svtai?2Hp5%caaGzX z;1-;OhL9#NP(nu)9s68F)3L8WLCpD2trQkR85F|}=C%;jVeB^S7n&0nXrxW2Llfmd zsgi?uk+XE3Ewx&u%2-fTs zJf`MEX}S*ML6>S3gSDD;A;M`?N@2besbowSeG_TB1hpA2nmN%X>sYEZ`>T%=rRtP( zF0%<*;Sh8V`&76{_1NhYy=Q{n9YsHfO1HTvCh&@HJ=X(_9r>|yB3j8d(4^;Z9`v}y zOZLyT6A3?@<+O#rS?KP=(5d^sAC3<*XTQvZbY$H$s-J$=UfqPh>U{kf<0eP^00000 LNkvXXu0mjf(85#3 literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_website_light.png b/MeditationAssistant/src/main/res/drawable-ldpi/ic_action_website_light.png new file mode 100644 index 0000000000000000000000000000000000000000..d502614c807125598d7e725c2549250a8bfe597a GIT binary patch literal 746 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM3?#3wJbQ|Pfl(pAC&U%Vg#%+_V{L716%`c) z1qB%y87V0#Jv}{jb#-fNYjbmRpsay`fv&Eup`oFUjt)?zrluy44O9aZ2LdA_BOuqr z#01FD*VhNC2a-TpAQvbLBq0o- zN(cii03smjA%Z{?;Nn1)aK#WdP$fhevKoj8M8Qn?3paoPlu#1n7tFxO%)-jX&cVsW z&CAQjFCZu?E+Hu;qoAs(rK4wPWM*z*Wn*jaAM`Rc{j-F3zx?aF&!z4k@lSeY6~A6& z*1gdGM<(e1NHW>5wVQd;_Vu?V*GO&Au;)`rdTDd=6Gy|2^#T*Q89GxYD%x6RKmDc0 zDtMdKAR_riZOOwGyV$O~9jWW`pZmr*i9xhGvf50^seIoNF~=iTqAnqG4<_nGD_Kr` z!IV(RrQ7yLf~_ph^B!Y_$qyyQ_$me-6VJYd-{U^`PL^_LTPXT8Ym4O?hR6IobKhJ3 va5R6`X5+@x8-FB3a+S2By6QGvuKMqsiiVckvVNMDgHo)gtDnm{r-UW|zi#B8 literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-ldpi/ic_notification.png b/MeditationAssistant/src/main/res/drawable-ldpi/ic_notification.png new file mode 100644 index 0000000000000000000000000000000000000000..0f64a23997697aec264d3f3abd19fdbd91cfabbb GIT binary patch literal 470 zcmV;{0V)28P)Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^RX3=ar60>e26%m4rY0%A)?L;(MX zkIcUS00CM_L_t&-83n<;iw|%B2jJ%r?nmB^&ZG>=X7LYLl`^nN9g`#jCWRz}q`Z`( z4x<=kP*%fXQ>1J}$RL9hci+#)^8f$}iU0rr1CTR0*9imwpa$r4nr1ry0D#OVdE5tm zlxO{urMArfYk*?XP@G`=&Dhpp)E7(=-pp;anHz`tE*-A{G7Ce1ZW=R?J#E@qx<4QLqo2kJ0AwoDozBfPi=EAdEaq#zWGU_0 zF@+*K`Z90RF6C0b=WC8GO}Z@i+x+P^*_DN{E*pAu+(?`L9CMuk#+EkiUfr4B*$U)f z+vXMoV{MyepKQ*Lo&vhQi)|JFdNIwvY&Ya`(vy&zX*#ZSci(3|Py08``AlJHbzh`O znkM5FV`HxNLq6wikAQ)HD|)w}oZXPZ{yyVEpj?TAaKVQ&b(!@v%bJ|NuiT@cSG65EA9)9sWH5_OJZKdSn2|_ On8DN4&t;ucLK6T1kvm@i literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-mdpi/ab_stacked_solid_buddhism.9.png b/MeditationAssistant/src/main/res/drawable-mdpi/ab_stacked_solid_buddhism.9.png new file mode 100644 index 0000000000000000000000000000000000000000..26b4a1065fb2bc7422300c36eb6d550989ce0411 GIT binary patch literal 158 zcmeAS@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%sh%#5As*hzDGL05*t3#VT(u)M zrmR%)P(FL$^SkE(;Y$rKTv2L^G$b<$@CWan6Dc%n6I~72^44$rjF6*2UngFJy BA1VL< literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-mdpi/ab_transparent_buddhism.9.png b/MeditationAssistant/src/main/res/drawable-mdpi/ab_transparent_buddhism.9.png new file mode 100644 index 0000000000000000000000000000000000000000..18b456aa2665bf046509187eb3f21de3814053d3 GIT binary patch literal 164 zcmeAS@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%*`6+rAs*hzDGL05*t3#VT(u)U z{{R2K((|Irswg+NWBw{TyF$1pT=_4*wd2kOXFVdQ&MBb@098jfa{vGU literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-mdpi/btn_cab_done_default_buddhism.9.png b/MeditationAssistant/src/main/res/drawable-mdpi/btn_cab_done_default_buddhism.9.png new file mode 100644 index 0000000000000000000000000000000000000000..70f1520f186ddee4adf122cfabfcb4a9f00f6ee0 GIT binary patch literal 106 zcmeAS@N?(olHy`uVBq!ia0vp^EI_Ql!3HEv&)kdyQih%`jv*Ss$tevD{~gY7BsFlV ze5mi>Zm|9K|9^e5o7*wtg8dg<7{sPH+Z;(a$v8)fp>U5eGt-0n?}3^bJYD@<);T3K F0RYn%Aua#_ literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-mdpi/btn_cab_done_focused_buddhism.9.png b/MeditationAssistant/src/main/res/drawable-mdpi/btn_cab_done_focused_buddhism.9.png new file mode 100644 index 0000000000000000000000000000000000000000..b94cdcfd33f13af2de0e9cebf9ed1e2c65e19b90 GIT binary patch literal 114 zcmeAS@N?(olHy`uVBq!ia0vp^EI_Ql!3HEv&)kdyQkI@Bjv*Ss$tevD{~gY7BsFv{ zPdu~l(&~SCY@R%YjsG3?|L|P<=X1}*i643H=$i;is422}^F6r2z_7<+CiDNUC(D6` OFnGH9xvX__@%;4$j=d#Wzp$Pyh#xa8c literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_check_off_disabled_focused_holo_light.png b/MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_check_off_disabled_focused_holo_light.png new file mode 100644 index 0000000000000000000000000000000000000000..b8a462a54d60ccd7f0bd61ba9fef024307baf3c6 GIT binary patch literal 287 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJXPz#OArY-_rx|h`au9Hx-`yw> z^h9bI_s%YHkEzB>KQTS>b<#?HsOsXv)Ohfas0(l2CPwb(;oR27{|$E=Ft4h={wUgk z_1N(RERwtlzR3y)g&V97aPFvSisVx{dO#|oa+ZAw!?puAMHMzaJAQA*x#N}soVja{ za30uppW(}~lG!@hjjvt)ugI8XBEV=MI^%k}#H$0F*OkU@55Du+#()3OA9V)#nhi`E zV6?;M@QKt_yifbsG#s_8H#1M%kTGlJGn=d%i+dtZ`W=vqU{xx9(^4J%+1HstJmL5m j@0ZI@&tLyk>nd;7A*;jl&AB%KeaztL>gTe~DWM4fU~qHj literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_check_off_disabled_holo_light.png b/MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_check_off_disabled_holo_light.png new file mode 100644 index 0000000000000000000000000000000000000000..db190430ce0a5e6daeec894453fcddc6e8fa5adc GIT binary patch literal 329 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE0wix1Z>k4UOiAAEE)4(M`_JqL@;D1TB8!2v z2N=7Z%(eqE(mY)pLp+WrCrGd!W-wS()GH}@a>QWZRN c6Vp?JQWH}u3s0un02MKKy85}Sb4q9e0K-jeO#lD@ literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_check_off_focused_holo_light.png b/MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_check_off_focused_holo_light.png new file mode 100644 index 0000000000000000000000000000000000000000..f6549cf7bce8286e271d0d79b3942b5b77a664ab GIT binary patch literal 309 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJKb|g*ArY-_r|soBWFXSIpXKF} z3ws|Z@$vapii*!a;Q1ktWw~8r_YbwXE;2`4U&LKm>HH`mX35v(f--y3&z!f7_hZ_r z@T+`fICszmMK<9L^2`;N%>;xw4)88u&1sr(G9mm%ngN61wQJ8W;`?p00i_>zopr E0H#xaHvj+t literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_check_off_holo_light.png b/MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_check_off_holo_light.png new file mode 100644 index 0000000000000000000000000000000000000000..f5eaf804b1b148b9d55a120a8d4cdaaabd4943e8 GIT binary patch literal 183 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJI!_nJkcif|(>C%p81S(4cW`DH zw}~%KX0sCeEK$-SsKj;2Nu_zg&urm(zdSpImLD_Uy}NKm$bdm}MtsBFyQi>t}P8Y~1@IE8dw&XhH*vib7+Uw3x#6ux{VXG!78HH3iO|b0nKn2hA#j| z00Dqu9~?jeFg9y=yHoHTTQiS_<>jRahW*O^7gjQSG5C0aX6w-1Ev0mjlqE{iLkL$h z^DKds(qW$GZ<14vfTRwepNI00S$00000NkvXXu0mjf_5pNL literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_check_on_disabled_focused_holo_light.png b/MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_check_on_disabled_focused_holo_light.png new file mode 100644 index 0000000000000000000000000000000000000000..257f48f7f843106248e5b491e29fb1cdaadf83cc GIT binary patch literal 562 zcmV-20?qx2P)1t>bFPSpSX^<)9axESjn%PEEbbTB2v=Oc#r>lF1!pO;g_TWEo9hG%l`E{Q zL>5^@V)lypM&`z3W-^P|>X0#{b4#~Og#ILVuuOvY+5QO}*ux=zy-;Kmr^ z1$mVM+5XSKFRRq~{`U5TtSCk!;1)=M9&iH;eGpCZJ2u8##JFp%lY)5{SOd0z|J3uPmE6ssn*VbI8)F`UBjB$Xjch!4`LPJ0gE z@F=n+a literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_check_on_disabled_holo_light.png b/MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_check_on_disabled_holo_light.png new file mode 100644 index 0000000000000000000000000000000000000000..20e2aab12b39cd77efd3a0ab36420a9e123cd181 GIT binary patch literal 508 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE0wix1Z>k4UOiAAEE)4(M`_JqL@;D1TB8!2v z2N=7Z%(i1-V3hQ9aSZV|{&vbnzrzM1uKuqgF33M%me3TAo@?_@Qqv=c$3H2#d8vuV zU8`lHD@0b#SeU!$(v99DO#$zxSiG09zwP;8M*W18?_olIb$wSOUoMZ(n~@Gelm-xpUX%JwH0>@rF6Ys^4E-U%Yo+wy1a8;YXU4cOK1UO)5-@uu0~c zYwF*`WSI2o^%TWQX*rP&*Aqwb3fi|k{ylrg+`xhgp~?fsIR$$pVr4}p6tyWTE*qvD{bC>mF=5@HkX$ToA6=fZh6cJu79oa)R>tO5CMLQD=2iv<>rHpFqiD#@ zPsvQHMAu+uWo!h|5V1dG8Bl{H$cEtjw370~qErUQl>DSr1<%~X^wgl##FWaylc_d9 OMGT&vSlSs4KY^LL6cBY4!w>#O)Y}SJGk{>+g@#ekX z_xt_*e(w+L*#B&y7v*>mr0TIguwEzu52(cEJ~-f_mC49895n#3pgBG!xpNh_UvS6s z9$?e+C6Is%o(9_S38fEkH31#?87LINY;ZsgPm>05q7X!&5qJmq)1#yo0RbEaqBsg; zz`@*^Gv`*u#(wCSo}TusDW_r!fx*rBD_l+{zXk5#8wne1i4c}7+emV$B+Hhq#B_c9 z^?OrlD4qWF%_~~L+q-w4`*3wtry?>i1zv!lCIrY-LLXaHl$h4l)puxkIHMPf06a`2 z#z%|A?@q6-8t%H_6l?_#d4ar55K&z4XdVHGKRal&tU zLF$Qsm=^|=xrT;V#I~j8^>y!fcv(@xg%c+}Z@YQ3=UJg3l&kW_#zg1B!XBKR@sz4< zxZM^bge?>+K-f;D&aWRo{*~e6dk@h34@C2+)Y-PNv7QYV{6Qiyz8HxNw63k?fcL0u zMH8@U9z;G7P-b`SiiJ*|yztu4P>*GrOsCUQVtDwf1oC1kb?U8a*D@QLRtEpArKP`f zX-TYarg8>6R|?AZWbfW+tE#?Q(scmZZrtd3aO{}5F3Y@|&1Q@WxVjvP40KOSeBreQ0H;)5stgUhI)~(*Rv)Nu_Wd(qlcwD`` zZ{I-2!a@$n8}4PFlcFA?+9#6)g69KQ6hsYwMW={lyXd?p@OpGKntpG{8Y zfWLu)`I2OKl$(CH;kFU5?U2|yI-q?pKc7?g@9&>&Y8n@lW*Zw-wWXzBD0fvCOW30D zHdVgYYSn;qSU4B9;gZz=spsxpOFeMlqGa3W?NZ6gMWdHo%{Pko1JrW+E9D@*CpFF(^FHAsf1d54MOF$|Cs>pN$3rw=xbe*lj5cnO1)dns^`5^ zPZ5gB6?xQgR2Ffr>Vn(X+<#`(nwnP6IdC|cOkTabiENNEyWC4U;D>=9YdQDzGzc#P zU$FgyLjKycpT)Q+Va33)b}LY&Meng-tT7+fg(VP)dxWev{5Pn0N%!8xe;Bzd3m+12_DZxcW*0c!YR$E7Rd{BuFV~tX9STKuJ*ol{059H$8aJ_PtW! zo@>L_ub1Vz5Qz;S~9v&co{4tq4zwhqd z^n9&WCx4nqWSWab0-($U)C2)__&y2WZ`>H#qG>y9!vFv@-M`=V=F};xD$6*S&8AI{ zTq^~GeXaR?;m(m`nQg^lD-*yEAxFFu{2oNkiK(gb^H{8BvavA-0P|nJV*A5~?FX{i zcJs>@0Kh~vsy*JcsqfhAYym*oB*YLrUqb#{0svU&^Z7z45a@jyk81#68wM=q`9w6T zeF}y8E{=^A0DJ~evDOh2UhbEW`w`$!D)Fsj0H__EnJH+SH)kf}@f;sC+0dYAiA08b z4maew4a)C;Wyt|QHQ-)XCKFo&K-ylsaI~#kZxBkmsck!jP^g!At_x<`L|#zwzb&8> za8!4$#YAve&C}Dhq5b=>*_2wT@$q-?a_!|@a+ZCB_!i(o0=(wa!~KSjtx$WJg{**bsqpHR*06?E#Sc68j2$sM+`j+-002ovPDHLkV1iHj!6*O# literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_check_on_pressed_holo_light.png b/MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_check_on_pressed_holo_light.png new file mode 100644 index 0000000000000000000000000000000000000000..09f2df11f7a4fdcd780df18aedcbb458acdbc5c4 GIT binary patch literal 554 zcmV+_0@eMAP)wbG{Nnl*X8;bM8VZ^)5|Q8!fO}txk+F zFBxNbq`;S|sybf2fQ5XDbS9r95F=kp6 z#k?%btA`TS+KILHHWnTw&{XKXzjn@LWm#Sl5v;WnV@yUw&o<%9<#JNjwcLw<_x=$P zJqeHJ&bh28it7Mxt=u{Hys9d_7XhWzy$~V;@I4GotE!p@INyZty6(;bj4^1f-wPpb zA4oJ!OfPtpK!-$cc(g!^#OFVO1KY3SP6=!6S1D!Q7v5W-kr)n#-}-(ZCD3;B?JL^^ zJQ1BP7K@ucixbf))-8BH0V(BzF?JW*kThY8c_GB2w*X_zODTW!f$y55_k{liIJTV9 szZ}o8{!2YpEC-MS_=&^rgb&R87dhGwL2HtLjV8( literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_default_disabled_holo_light.9.png b/MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_default_disabled_holo_light.9.png new file mode 100644 index 0000000000000000000000000000000000000000..d424a0e77e9b92c3cb42d140502be078ae2bae96 GIT binary patch literal 313 zcmeAS@N?(olHy`uVBq!ia0vp^GC-`v!3HFKYIk}9DVAa<&kznEsNqQI0P;BtJR*x3 z7`Qt@n9=;?>9s(?+nz3tAs(G?r~C3XIqG)(R zZOJnT3{v1JG_lZ6G}irlX?~)_0smX}-SJ#ntR|eickL#u*}7_#U*$ackiWNlToTg4 zr#+Qyj`ZaHKV@cr^RZYi}a_TZ3+4UUY*wW~D{^tZbnyZV!Sk=BM1)_V(4@o27Fl5C6)ZyldUg%vnmFLhH}Z>zGj7$9Up`*|d{< z2kH*lsk0Wa7D(%~?LGhJcxv0PMfgTe~ HDWM4fQ|x?C literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_default_focused_holo_light.9.png b/MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_default_focused_holo_light.9.png new file mode 100644 index 0000000000000000000000000000000000000000..0ec0c19ef7625d14590c5f3287c512d350d78144 GIT binary patch literal 273 zcmV+s0q*{ZP)F||Ymb&odDH}s_1MK{viT5x9BhU>DT1dY#LubYKBrvEVFalqd=OgJ2x!yEQ zsSrTDg99+|&3QJH>?fcf^j)if5irDmk2SDWuxT1i=nv3;d}ajPudQgWAZP!ley+GD XLxn7zh~H3r00000NkvXXu0mjfta)>a literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_default_normal_holo_light.9.png b/MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_default_normal_holo_light.9.png new file mode 100644 index 0000000000000000000000000000000000000000..e134087b3dd5f5445b7ce9c1b75804500116d21e GIT binary patch literal 242 zcmVj_c)N0w49NNJoo(n_m9D0-n>XgM#ddPS=hzE z@RXl{;SX81LBU4`29`1g25EHh;U9@#LyXeGxoWHZnO{?oey sG%`9fj0_BzVarIk27#%^s}7sF0BXV|Y0tj)ssI2007*qoM6N<$f?rl<(f|Me literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_default_pressed_holo_light.9.png b/MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_default_pressed_holo_light.9.png new file mode 100644 index 0000000000000000000000000000000000000000..90c8de1fd6aaa4776aca6183d7dde71105a46178 GIT binary patch literal 236 zcmVL9uumUSE z4|Hv$U%6qnfPWI`stT;YcO}K&a5U+gHJq$9PkrE699MIdGMLhTlM0^EvQG%nG_zpbj zmV}rDysDV!L6#*18J12qOq#?))v%kfXXlSG7x#B*x_Rn(zFqbFDGv01*P%rg^=RNp zwDPBI-0X7qKLhA-7-#Sbo|fMC>OQVx16R7~{m}sQcpmR!1wY{$ZeWl>T6hL8;RXDK z&%6BkuK{|zhBt5(7yBWUjp1? z@V!*N(*b(v{MMvWYhydcSj`(fui4H%uHm`d!1f1_Ivo6Qq^erk$)eguGbiBTJ-+t^ zXy#{muPB!6mf9j3N+mk(dtZRZsycu&KbuFYs`Bt3%&YMoEXNJ%07m6@@?KF4>`uHz z)I!mC&rj>oHjR*yHOpSV(IyWcQ6jSq0XAHrp6-rq6bFgk_z@yT4n zXb;3_9AD^%@Ex9#6U+2*{35!zu+TUjgLvpdl7qGEmgq1C9&}<{l8)}|wBR!VWQfz! zm8^{)rQZIhvk4UOiAAEE)4(M`_JqL@;D1TB8!2v z2N=7Z%(eqE{&>1LhIkx*J7sUyVFQs?d-G1#V|{l|E|FtuwP~9d*B|&|!ofDaquVYu zOmVO}BB>Oe@Y*qoSwcY z*?cCCgWA#=2StI-;xQwB6k(#>zi%16Fj}nLA7DmmzpMHscS(4arKwy$0A9J0qc*0$8skax} z7-ud0vP(7P&7p>}AO9~$ZCJv~%p*H>j-Q8%>5{|z0T(6&^a&a*Qdw9i|MUN0mioTW z7e3nrBpq1vm-*?!-51P_MT7Moc8B!>!$GygHKHUXu_V8e=o*+?85q3yvh^a0hTQy=%(P0}8fLEK%>`9>+}ILI2tyE&A||G_lu!yn6%9Eqq!g^W5Pwi~R9wwp;9ud^&8$js3|2v0 zxYAHCrxcq8lpv*+s9~rsY6&3((bn8?aZX5#Gs!ruZp^c}+&k}i-|xNip65O6>Hn@u zKZ_a+;sFfjN2|D5=eK_iph1Br@iZQh?zgJM_n5_8J>B0MfCfkL7Dn(j=J5koGRQE- zaRQHF8E5NUziWU7r|}Z5;G<>;MNyW=D(&|8`oO?}9JZQ)uGV5K@M;G6xX$N&1LWc_ z;)7-gbNlbydH(jked8O&q&J28rLQ!epU>1{d;+iU2GJEDfA)9qelvuHN?F$0MR5Zc zVvH-D)`SqMIEe=_U5oK}hIqHz-?6=sHi{Q`8<(3Q%vH+r&2~|IgHO8^hy2?oSioz| z5aw_>=jy1A0GN~->%;rj*H5>LqJ@hw#$7u*$6UnEcm~rLX`~(0Gr$zCG(*_`$H2fi zW_l^U4Ppip%@79hrL=u_2WW5rhor4Gf$K5G)n1Elfmp?2&M}Wivw`glAUPZ?Rm$>k zPSURyF_s&!*phokfT4U{YZt|k&8^mtmQn4Hdq;r(RGk3U@^z?EmTQvz_N%I7*V}XN z2yioB$J#})h{JaQa0E+@X!79G~v!jgXAGh^#YM&rf?7!8oVs^!Ca^K zfld!Uqy0j%(pQeRTE8rej(&ktI5;{w`ctdb`n^l>DxQ;!Y`PZX!*~Pl)w$JaO|Rql zd^3bg8RDp9FxPB)#E9g0TgUM+)N#JAal8%UF9(ubY|N&~tY8V>=Dsgg-(sDFAWos=5vP=}CG+P<^+>Yg4-JHQM|r=AUO f@B3K3r#<}%$3*erDj!UC00000NkvXXu0mjfPos=v literal 0 HcmV?d00001 diff --git a/MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_radio_off_holo_light.png b/MeditationAssistant/src/main/res/drawable-mdpi/buddhism_btn_radio_off_holo_light.png new file mode 100644 index 0000000000000000000000000000000000000000..0d81a6ad4bff24519a73e14fa4a3437946a1c8ba GIT binary patch literal 428 zcmV;d0aN~oP)2q1;Aw+B@50FAcWD&WBRI)4^NU14i z7O#>x-mAvue#^OM&iT#U^JnPk>3L<|v@s4Lzz7@ofIuY)aFvj@%*#v|ThWLV?IKuS)Df8_tVH@x8HO4qmpeP`pd=KC8Eyj3VuwTFy zHnCs2iN%65_>5mTC-wMe3k828tV{p27<^8)J(QAl_>gT$ zzy{8wEN{yU~b}lAfNPSLY93 WEqXjOx5kD50000;j*D%J*I>s#7WihgL z=R?yo)j7-z$kI$}R#6`4B9;2R>Z+~}fsu&g*aZ-_9~XcPfZCrKKn0)#a1Wr6QkG-R z6(fj!07q-YyU>Zr04$}H#a;s9IJN=IT5@{?aUUuGO8^TgWz}b34Uqc)p0?!FXEPE6 zAOPS+QB)>LvL#|mKpe**fMWpue<0q310aZ^sMr+og@D%cV~mUSLt(WdvLs3BEdg!J zpW?8d_la;@5e$5pTr)J8Zp3P}nkl7TGV?R7^-sq}pApeT5CrG8ZJVB71>j0bS#*TP zr&gBbEYI^FiRd~E!(Sc8x!*9k0q|BSHO=#Uo~G%~K@dpSb(aH2+AU`x+6s4qfyAq- zDooS#C(E+_noK5dgb-}-3|ebS)AUtc*WXPhliv+DQ3ALk?5J>gp3jNsdJH)L2qAbf znYpair22&e=-wEi&YPFg%^O^7ae~uwv7vcNNN@tK*A_C1`LkAx6+y9D(1X#gOitGcdF_Z3i8)hQ8uG?@^Z zg3t@cao#fXnNn(JkJyA#YO1yV#&z9y2D5_Dj847qJa0inmqk&`wbrBaMQcq(QOt?x z!qA);K-LKu3_}nE=gjq8X!m$MplC1n`fPQf&!nMO3W_|9=qC zk+0Uj+#*SmL`6|lpqb^J1CeI{Zu-`=UN765$N=b8#J)|dLKE-Xp=I@<%jx&+q7+nBU1(}*ssNPBWxo(2 zB&7`De3g5BhOq~DZ#9S&0o>3232=T$(|%Be=&&0bOVMcb-r2Kfh1ctSWDl68DUTgH zrl!;Bjh1EkfjfPMvD=0Ce5Kz}6TsbY1HkPeP5V+6qEiV3=1-qKJ=fjctzY< zftxpP`T@3Y-(ER<_;4u_iHM1b3EAJ@-&U zw6#5F1_Fx%0|S3_b#^>SAjzZ;QlDweO!Qdfz*(u{Z#dOH*|D#%$_)Lg2BPT;PCKpx1uP! zs@3X-d_Lb?E|;4d8XDFqiqbwgIq4~v%X2+FJ*Ht8h57mU$c5O{GE#+TPx zew