From 2692564bfe18978ceb2b5fa4e9237113ae300176 Mon Sep 17 00:00:00 2001 From: lado Date: Fri, 3 Nov 2017 00:25:44 +0100 Subject: curretn --- .../de.bjusystems.vdrmanager/app-release.apk | Bin 0 -> 2272288 bytes vdrmanager/de.bjusystems.vdrmanager/build.gradle | 50 + .../de/bjusystems/vdrmanager/BuildConfig.java | 4 +- .../r/debug/android/support/v7/appcompat/R.java | 2 +- .../source/r/debug/de/bjusystems/vdrmanager/R.java | 475 +++---- vdrmanager/de.bjusystems.vdrmanager/lint.xml | 5 + .../release/de.bjusystems.vdrmanager-release.apk | Bin 0 -> 2347012 bytes .../de.bjusystems.vdrmanager/release/output.json | 1 + .../src/main/AndroidManifest.xml | 30 +- .../com/rajasharan/widget/BitmapDecorator.java | 90 ++ .../com/rajasharan/widget/RecyclerDropdown.java | 172 +++ .../com/rajasharan/widget/SearchableSpinner.java | 209 +++ .../com/rajasharan/widget/ShadowDecorator.java | 103 ++ .../bjusystems/vdrmanager/app/VdrManagerApp.java | 11 +- .../vdrmanager/backup/BackupActivity.java | 99 +- .../vdrmanager/backup/BackupSettingsActivity.java | 148 +- .../vdrmanager/gui/PreferencesActivity.java | 1 - .../java/de/bjusystems/vdrmanager/gui/Utils.java | 1457 ++++++++++---------- .../vdrmanager/gui/VdrManagerActivity.java | 617 +++++---- .../vdrmanager/remote/RemoteActivity.java | 188 ++- .../src/main/res/layout/dialog_dropdown.xml | 26 + .../src/main/res/layout/recycler_buffer_item.xml | 7 + .../src/main/res/layout/recycler_itemviews.xml | 7 + .../src/main/res/layout/remote.xml | 2 + .../src/main/res/values/dimens.xml | 7 + .../src/main/res/values/font.xml | 13 + .../src/main/res/values/strings.xml | 1035 +++++++------- 27 files changed, 2844 insertions(+), 1915 deletions(-) create mode 100644 vdrmanager/de.bjusystems.vdrmanager/app-release.apk create mode 100644 vdrmanager/de.bjusystems.vdrmanager/build.gradle create mode 100644 vdrmanager/de.bjusystems.vdrmanager/lint.xml create mode 100644 vdrmanager/de.bjusystems.vdrmanager/release/de.bjusystems.vdrmanager-release.apk create mode 100644 vdrmanager/de.bjusystems.vdrmanager/release/output.json create mode 100644 vdrmanager/de.bjusystems.vdrmanager/src/main/java/com/rajasharan/widget/BitmapDecorator.java create mode 100644 vdrmanager/de.bjusystems.vdrmanager/src/main/java/com/rajasharan/widget/RecyclerDropdown.java create mode 100644 vdrmanager/de.bjusystems.vdrmanager/src/main/java/com/rajasharan/widget/SearchableSpinner.java create mode 100644 vdrmanager/de.bjusystems.vdrmanager/src/main/java/com/rajasharan/widget/ShadowDecorator.java create mode 100644 vdrmanager/de.bjusystems.vdrmanager/src/main/res/layout/dialog_dropdown.xml create mode 100644 vdrmanager/de.bjusystems.vdrmanager/src/main/res/layout/recycler_buffer_item.xml create mode 100644 vdrmanager/de.bjusystems.vdrmanager/src/main/res/layout/recycler_itemviews.xml create mode 100644 vdrmanager/de.bjusystems.vdrmanager/src/main/res/values/dimens.xml create mode 100644 vdrmanager/de.bjusystems.vdrmanager/src/main/res/values/font.xml (limited to 'vdrmanager') diff --git a/vdrmanager/de.bjusystems.vdrmanager/app-release.apk b/vdrmanager/de.bjusystems.vdrmanager/app-release.apk new file mode 100644 index 0000000..0f5cbfc Binary files /dev/null and b/vdrmanager/de.bjusystems.vdrmanager/app-release.apk differ diff --git a/vdrmanager/de.bjusystems.vdrmanager/build.gradle b/vdrmanager/de.bjusystems.vdrmanager/build.gradle new file mode 100644 index 0000000..f759850 --- /dev/null +++ b/vdrmanager/de.bjusystems.vdrmanager/build.gradle @@ -0,0 +1,50 @@ +apply plugin: 'com.android.application' + +android { + lintOptions { + checkReleaseBuilds false + // Or, if you prefer, you can continue to check for errors in release builds, + // but continue the build even when errors are found: + abortOnError false + } + + + signingConfigs { + config { + + } + } + compileSdkVersion 23 + buildToolsVersion '26.0.2' + defaultConfig { + applicationId "de.bjusystems.vdrmanager" + minSdkVersion 8 + targetSdkVersion 23 + //vectorDrawables.useSupportLibrary = true + + } + + + aaptOptions { + additionalParameters "--no-version-vectors" + } + + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' + zipAlignEnabled true + } + } +} + +dependencies { + compile 'com.android.support:support-v4:23.4.0' + compile 'com.android.support:appcompat-v7:23.4.0' + compile 'com.j256.ormlite:ormlite-android:4.48' + compile 'com.j256.ormlite:ormlite-core:4.48' + compile 'org.slf4j:slf4j-android:1.7.19' + compile 'org.hampelratte:svdrp4j:1.1.0-SNAPSHOT' + compile 'com.android.support:recyclerview-v7:23.4.0' +} diff --git a/vdrmanager/de.bjusystems.vdrmanager/build/generated/source/buildConfig/debug/de/bjusystems/vdrmanager/BuildConfig.java b/vdrmanager/de.bjusystems.vdrmanager/build/generated/source/buildConfig/debug/de/bjusystems/vdrmanager/BuildConfig.java index a762496..7ec5efc 100644 --- a/vdrmanager/de.bjusystems.vdrmanager/build/generated/source/buildConfig/debug/de/bjusystems/vdrmanager/BuildConfig.java +++ b/vdrmanager/de.bjusystems.vdrmanager/build/generated/source/buildConfig/debug/de/bjusystems/vdrmanager/BuildConfig.java @@ -8,6 +8,6 @@ public final class BuildConfig { public static final String APPLICATION_ID = "de.bjusystems.vdrmanager"; public static final String BUILD_TYPE = "debug"; public static final String FLAVOR = ""; - public static final int VERSION_CODE = 12700; - public static final String VERSION_NAME = "12.70"; + public static final int VERSION_CODE = 12710; + public static final String VERSION_NAME = "12.71"; } diff --git a/vdrmanager/de.bjusystems.vdrmanager/build/generated/source/r/debug/android/support/v7/appcompat/R.java b/vdrmanager/de.bjusystems.vdrmanager/build/generated/source/r/debug/android/support/v7/appcompat/R.java index 0a5a5e0..7e11890 100644 --- a/vdrmanager/de.bjusystems.vdrmanager/build/generated/source/r/debug/android/support/v7/appcompat/R.java +++ b/vdrmanager/de.bjusystems.vdrmanager/build/generated/source/r/debug/android/support/v7/appcompat/R.java @@ -628,7 +628,7 @@ public final class R { public static final int abc_shareactionprovider_share_with = 0x7f0d0060; public static final int abc_shareactionprovider_share_with_application = 0x7f0d0061; public static final int abc_toolbar_collapse_description = 0x7f0d0062; - public static final int status_bar_notification_info_overflow = 0x7f0d016b; + public static final int status_bar_notification_info_overflow = 0x7f0d016e; } public static final class style { public static final int AlertDialog_AppCompat = 0x7f0e0000; diff --git a/vdrmanager/de.bjusystems.vdrmanager/build/generated/source/r/debug/de/bjusystems/vdrmanager/R.java b/vdrmanager/de.bjusystems.vdrmanager/build/generated/source/r/debug/de/bjusystems/vdrmanager/R.java index bffcde8..046eeec 100644 --- a/vdrmanager/de.bjusystems.vdrmanager/build/generated/source/r/debug/de/bjusystems/vdrmanager/R.java +++ b/vdrmanager/de.bjusystems.vdrmanager/build/generated/source/r/debug/de/bjusystems/vdrmanager/R.java @@ -2763,242 +2763,245 @@ public final class R { public static final int no_results=0x7f0d00f6; public static final int no_vdr=0x7f0d00f7; public static final int not_yet_implemented=0x7f0d00f8; - public static final int prefs_current_value=0x7f0d00f9; - public static final int prefs_current_value_not_set=0x7f0d00fa; - public static final int prefs_current_value_template=0x7f0d00fb; - public static final int probing=0x7f0d00fc; - public static final int processing=0x7f0d00fd; - public static final int progress_cache_hit=0x7f0d00fe; - public static final int progress_channels_loading=0x7f0d00ff; - public static final int progress_connect=0x7f0d0100; - public static final int progress_connect_error=0x7f0d0101; - public static final int progress_connect_finished_abnormal=0x7f0d0102; - public static final int progress_connect_finished_abnormal_arg=0x7f0d0103; - public static final int progress_connect_timeout=0x7f0d0104; - public static final int progress_disconnect=0x7f0d0105; - public static final int progress_loading=0x7f0d0106; - public static final int progress_login=0x7f0d0107; - public static final int progress_login_error=0x7f0d0108; - public static final int progress_recording_delete=0x7f0d0109; - public static final int progress_recordings_loading=0x7f0d010a; - public static final int progress_switching=0x7f0d010b; - public static final int progress_timer_delete=0x7f0d010c; - public static final int progress_timer_disable=0x7f0d010d; - public static final int progress_timer_enable=0x7f0d010e; - public static final int progress_timer_modify=0x7f0d010f; - public static final int progress_timer_save=0x7f0d0110; - public static final int progress_timers_loading=0x7f0d0111; - public static final int progress_wakeup_error=0x7f0d0112; - public static final int progress_wakeup_sending=0x7f0d0113; - public static final int progress_wakeup_sent=0x7f0d0114; - public static final int progress_whatson_loading=0x7f0d0115; - public static final int qui_imdb_url_key=0x7f0d0116; - public static final int qui_imdb_url_summary=0x7f0d0117; - public static final int qui_imdb_url_title=0x7f0d0118; - public static final int qui_quit_on_back_key=0x7f0d0119; - public static final int qui_show_imdb_button_key=0x7f0d011a; - public static final int qui_show_imdb_button_summary_off=0x7f0d011b; - public static final int qui_show_imdb_button_summary_on=0x7f0d011c; - public static final int qui_show_imdb_button_title=0x7f0d011d; - public static final int qui_show_omdb_button_key=0x7f0d011e; - public static final int qui_show_omdb_button_summary_off=0x7f0d011f; - public static final int qui_show_omdb_button_summary_on=0x7f0d0120; - public static final int qui_show_omdb_button_title=0x7f0d0121; - public static final int qui_show_tmdb_button_key=0x7f0d0122; - public static final int qui_show_tmdb_button_summary_off=0x7f0d0123; - public static final int qui_show_tmdb_button_summary_on=0x7f0d0124; - public static final int qui_show_tmdb_button_title=0x7f0d0125; - public static final int recent_channels=0x7f0d0126; - public static final int recent_channels_no_history=0x7f0d0127; - public static final int recording_item_menu_delete=0x7f0d0128; - public static final int recording_item_menu_stream=0x7f0d0129; - public static final int recording_started=0x7f0d012a; - public static final int recstream=0x7f0d012b; - public static final int recstream_enable_summary=0x7f0d012c; - public static final int recstream_enable_title=0x7f0d012d; - public static final int recstream_method_summary=0x7f0d012e; - public static final int recstream_method_title=0x7f0d012f; - public static final int recstream_smarttvweb_method_summary=0x7f0d0130; - public static final int recstream_smarttvweb_method_title=0x7f0d0131; - public static final int refresh=0x7f0d0132; - public static final int remapback_hint=0x7f0d0133; - public static final int remote=0x7f0d0134; - public static final int remote_enable_summary=0x7f0d0135; - public static final int remote_enable_title=0x7f0d0136; - public static final int remux_command_summary=0x7f0d0137; - public static final int remux_command_title=0x7f0d0138; - public static final int remux_enable_summary=0x7f0d0139; - public static final int remux_enable_title=0x7f0d013a; - public static final int remux_parameter_summary=0x7f0d013b; - public static final int remux_parameter_title=0x7f0d013c; - public static final int remux_title=0x7f0d013d; - public static final int sad_img=0x7f0d013e; - public static final int sd_card_canceled=0x7f0d013f; - public static final int sd_card_error_no_storage=0x7f0d0140; - public static final int sd_card_import_error=0x7f0d0141; - public static final int sd_card_import_error_no_file=0x7f0d0142; - public static final int sd_card_import_progress_message=0x7f0d0143; - public static final int sd_card_import_success=0x7f0d0144; - public static final int sd_card_save_error=0x7f0d0145; - public static final int sd_card_save_error_create_dir=0x7f0d0146; - public static final int sd_card_save_progress_message=0x7f0d0147; - public static final int sd_card_save_success=0x7f0d0148; - public static final int search=0x7f0d0149; - public static final int search_epg_hint=0x7f0d014a; - public static final int search_reapt=0x7f0d014b; - public static final int set_time=0x7f0d014c; - public static final int settings_backup=0x7f0d014d; - public static final int settings_backup_key=0x7f0d014e; - public static final int settings_backup_now=0x7f0d014f; - public static final int settings_backup_now_key=0x7f0d0150; - public static final int settings_backup_now_progress_message=0x7f0d0151; - public static final int settings_backup_now_summary=0x7f0d0152; - public static final int settings_backup_restore=0x7f0d0153; - public static final int settings_backup_restore_confirm_message=0x7f0d0154; - public static final int settings_backup_restore_key=0x7f0d0155; - public static final int settings_backup_restore_no_backup=0x7f0d0156; - public static final int settings_backup_restore_progress_message=0x7f0d0157; - public static final int settings_backup_restore_select_title=0x7f0d0158; - public static final int settings_backup_restore_summary=0x7f0d0159; - public static final int settings_backup_summary=0x7f0d015a; - public static final int settings_live_port=0x7f0d015b; - public static final int settings_live_port_summary=0x7f0d015c; - public static final int settings_livetv_port=0x7f0d015d; - public static final int settings_livetv_port_summary=0x7f0d015e; - public static final int settings_livetv_streamformat=0x7f0d015f; - public static final int settings_livetv_summary=0x7f0d0160; - public static final int settings_smarttvweb_port=0x7f0d0161; - public static final int settings_smarttvweb_port_summary=0x7f0d0162; - public static final int share=0x7f0d0163; - public static final int share_chooser=0x7f0d0164; - public static final int sort=0x7f0d0165; - public static final int sortby=0x7f0d0166; - public static final int sortby_alphabet=0x7f0d0167; - public static final int sortby_channel=0x7f0d0168; - public static final int sortby_channellist=0x7f0d0169; - public static final int sortby_time=0x7f0d016a; - public static final int status_bar_notification_info_overflow=0x7f0d016b; - public static final int stream_as=0x7f0d016c; - public static final int stream_choose_audio=0x7f0d016d; - public static final int stream_via=0x7f0d016e; - public static final int stream_via_as=0x7f0d016f; - public static final int streaming_password_key=0x7f0d0170; - public static final int streaming_password_sum=0x7f0d0171; - public static final int streaming_password_title=0x7f0d0172; - public static final int streaming_username_key=0x7f0d0173; - public static final int streaming_username_sum=0x7f0d0174; - public static final int streaming_username_title=0x7f0d0175; - public static final int svdrp_port_summary=0x7f0d0176; - public static final int svdrp_port_title=0x7f0d0177; - public static final int switch_to_channel=0x7f0d0178; - public static final int switching_failed=0x7f0d0179; - public static final int switching_success=0x7f0d017a; - public static final int timer_already_exists=0x7f0d017b; - public static final int timer_created=0x7f0d017c; - public static final int timer_default_lifetime_key=0x7f0d017d; - public static final int timer_default_lifetime_summary=0x7f0d017e; - public static final int timer_default_lifetime_title=0x7f0d017f; - public static final int timer_default_primary_limit_key=0x7f0d0180; - public static final int timer_default_primary_limit_summary=0x7f0d0181; - public static final int timer_default_primary_limit_title=0x7f0d0182; - public static final int timer_default_priority_key=0x7f0d0183; - public static final int timer_default_priority_summary=0x7f0d0184; - public static final int timer_default_priority_title=0x7f0d0185; - public static final int timer_detail_channel_title=0x7f0d0186; - public static final int timer_detail_day_title=0x7f0d0187; - public static final int timer_detail_end_title=0x7f0d0188; - public static final int timer_detail_lifetime=0x7f0d0189; - public static final int timer_detail_lifetime_hint=0x7f0d018a; - public static final int timer_detail_priority=0x7f0d018b; - public static final int timer_detail_priority_hint=0x7f0d018c; - public static final int timer_detail_repeat_title=0x7f0d018d; - public static final int timer_detail_start_title=0x7f0d018e; - public static final int timer_detail_title_title=0x7f0d018f; - public static final int timer_detail_title_vps=0x7f0d0190; - public static final int timer_detail_use_vps=0x7f0d0191; - public static final int timer_details_add_title=0x7f0d0192; - public static final int timer_details_create_title=0x7f0d0193; - public static final int timer_details_delete_title=0x7f0d0194; - public static final int timer_details_modify_title=0x7f0d0195; - public static final int timer_details_save_title=0x7f0d0196; - public static final int timer_error=0x7f0d0197; - public static final int timer_post_end_buffer_key=0x7f0d0198; - public static final int timer_post_end_buffer_summary=0x7f0d0199; - public static final int timer_post_end_buffer_title=0x7f0d019a; - public static final int timer_pre_start_buffer_key=0x7f0d019b; - public static final int timer_pre_start_buffer_summary=0x7f0d019c; - public static final int timer_pre_start_buffer_title=0x7f0d019d; - public static final int timer_preferences=0x7f0d019e; - public static final int timezone_key=0x7f0d019f; - public static final int type_to_filter=0x7f0d01a0; - public static final int update_will_start_in=0x7f0d01a1; - public static final int vdr_advanced_preferences=0x7f0d01a2; - public static final int vdr_advanced_preferences_summary=0x7f0d01a3; - public static final int vdr_conntimeout_key=0x7f0d01a4; - public static final int vdr_conntimeout_sum=0x7f0d01a5; - public static final int vdr_conntimeout_title=0x7f0d01a6; - public static final int vdr_device_delete_qeustion=0x7f0d01a7; - public static final int vdr_devices=0x7f0d01a8; - public static final int vdr_devices_category=0x7f0d01a9; - public static final int vdr_devices_summary=0x7f0d01aa; - public static final int vdr_encoding_key=0x7f0d01ab; - public static final int vdr_encoding_summary=0x7f0d01ac; - public static final int vdr_encoding_title=0x7f0d01ad; - public static final int vdr_error_text=0x7f0d01ae; - public static final int vdr_host_key=0x7f0d01af; - public static final int vdr_host_not_defined=0x7f0d01b0; - public static final int vdr_host_summary=0x7f0d01b1; - public static final int vdr_host_title=0x7f0d01b2; - public static final int vdr_name_key=0x7f0d01b3; - public static final int vdr_name_summary=0x7f0d01b4; - public static final int vdr_name_title=0x7f0d01b5; - public static final int vdr_password_key=0x7f0d01b6; - public static final int vdr_password_summary=0x7f0d01b7; - public static final int vdr_password_title=0x7f0d01b8; - public static final int vdr_port_default=0x7f0d01b9; - public static final int vdr_port_key=0x7f0d01ba; - public static final int vdr_port_summary=0x7f0d01bb; - public static final int vdr_port_title=0x7f0d01bc; - public static final int vdr_preferences=0x7f0d01bd; - public static final int vdr_prefs_category=0x7f0d01be; - public static final int vdr_readtimeout_key=0x7f0d01bf; - public static final int vdr_readtimeout_sum=0x7f0d01c0; - public static final int vdr_readtimeout_title=0x7f0d01c1; - public static final int vdr_ssl_key=0x7f0d01c2; - public static final int vdr_ssl_summary=0x7f0d01c3; - public static final int vdr_ssl_title=0x7f0d01c4; - public static final int vdr_stream_format=0x7f0d01c5; - public static final int vdr_stream_port=0x7f0d01c6; - public static final int vdr_stream_proxy_key=0x7f0d01c7; - public static final int vdr_timeout_key=0x7f0d01c8; - public static final int vdr_timeout_sum=0x7f0d01c9; - public static final int vdr_timeout_title=0x7f0d01ca; - public static final int vdr_timezone_summary=0x7f0d01cb; - public static final int vdr_timezone_title=0x7f0d01cc; - public static final int wakeup_enabled_key=0x7f0d01cd; - public static final int wakeup_enabled_summary=0x7f0d01ce; - public static final int wakeup_enabled_title=0x7f0d01cf; - public static final int wakeup_method_key=0x7f0d01d0; - public static final int wakeup_method_summary=0x7f0d01d1; - public static final int wakeup_method_title=0x7f0d01d2; - public static final int wakeup_password_key=0x7f0d01d3; - public static final int wakeup_password_summary=0x7f0d01d4; - public static final int wakeup_password_title=0x7f0d01d5; - public static final int wakeup_preferences=0x7f0d01d6; - public static final int wakeup_url_key=0x7f0d01d7; - public static final int wakeup_url_summary=0x7f0d01d8; - public static final int wakeup_url_title=0x7f0d01d9; - public static final int wakeup_user_key=0x7f0d01da; - public static final int wakeup_user_summary=0x7f0d01db; - public static final int wakeup_user_title=0x7f0d01dc; - public static final int wakeup_wol_custom_boradcast_summary=0x7f0d01dd; - public static final int wakeup_wol_custom_boradcast_title=0x7f0d01de; - public static final int wakeup_wol_custom_broadcast_key=0x7f0d01df; - public static final int wakeup_wol_mac_key=0x7f0d01e0; - public static final int wakeup_wol_mac_summary=0x7f0d01e1; - public static final int wakeup_wol_mac_title=0x7f0d01e2; - public static final int zone_list_menu_sort_alphabetically=0x7f0d01e3; - public static final int zone_list_menu_sort_by_timezone=0x7f0d01e4; + public static final int permission_rationale=0x7f0d00f9; + public static final int prefs_current_value=0x7f0d00fa; + public static final int prefs_current_value_not_set=0x7f0d00fb; + public static final int prefs_current_value_template=0x7f0d00fc; + public static final int probing=0x7f0d00fd; + public static final int processing=0x7f0d00fe; + public static final int progress_cache_hit=0x7f0d00ff; + public static final int progress_channels_loading=0x7f0d0100; + public static final int progress_connect=0x7f0d0101; + public static final int progress_connect_error=0x7f0d0102; + public static final int progress_connect_finished_abnormal=0x7f0d0103; + public static final int progress_connect_finished_abnormal_arg=0x7f0d0104; + public static final int progress_connect_timeout=0x7f0d0105; + public static final int progress_disconnect=0x7f0d0106; + public static final int progress_loading=0x7f0d0107; + public static final int progress_login=0x7f0d0108; + public static final int progress_login_error=0x7f0d0109; + public static final int progress_recording_delete=0x7f0d010a; + public static final int progress_recordings_loading=0x7f0d010b; + public static final int progress_switching=0x7f0d010c; + public static final int progress_timer_delete=0x7f0d010d; + public static final int progress_timer_disable=0x7f0d010e; + public static final int progress_timer_enable=0x7f0d010f; + public static final int progress_timer_modify=0x7f0d0110; + public static final int progress_timer_save=0x7f0d0111; + public static final int progress_timers_loading=0x7f0d0112; + public static final int progress_wakeup_error=0x7f0d0113; + public static final int progress_wakeup_sending=0x7f0d0114; + public static final int progress_wakeup_sent=0x7f0d0115; + public static final int progress_whatson_loading=0x7f0d0116; + public static final int qui_imdb_url_key=0x7f0d0117; + public static final int qui_imdb_url_summary=0x7f0d0118; + public static final int qui_imdb_url_title=0x7f0d0119; + public static final int qui_quit_on_back_key=0x7f0d011a; + public static final int qui_show_imdb_button_key=0x7f0d011b; + public static final int qui_show_imdb_button_summary_off=0x7f0d011c; + public static final int qui_show_imdb_button_summary_on=0x7f0d011d; + public static final int qui_show_imdb_button_title=0x7f0d011e; + public static final int qui_show_omdb_button_key=0x7f0d011f; + public static final int qui_show_omdb_button_summary_off=0x7f0d0120; + public static final int qui_show_omdb_button_summary_on=0x7f0d0121; + public static final int qui_show_omdb_button_title=0x7f0d0122; + public static final int qui_show_tmdb_button_key=0x7f0d0123; + public static final int qui_show_tmdb_button_summary_off=0x7f0d0124; + public static final int qui_show_tmdb_button_summary_on=0x7f0d0125; + public static final int qui_show_tmdb_button_title=0x7f0d0126; + public static final int recent_channels=0x7f0d0127; + public static final int recent_channels_no_history=0x7f0d0128; + public static final int recording_item_menu_delete=0x7f0d0129; + public static final int recording_item_menu_stream=0x7f0d012a; + public static final int recording_started=0x7f0d012b; + public static final int recstream=0x7f0d012c; + public static final int recstream_enable_summary=0x7f0d012d; + public static final int recstream_enable_title=0x7f0d012e; + public static final int recstream_method_summary=0x7f0d012f; + public static final int recstream_method_title=0x7f0d0130; + public static final int recstream_smarttvweb_method_summary=0x7f0d0131; + public static final int recstream_smarttvweb_method_title=0x7f0d0132; + public static final int refresh=0x7f0d0133; + public static final int remapback_hint=0x7f0d0134; + public static final int remote=0x7f0d0135; + public static final int remote_enable_summary=0x7f0d0136; + public static final int remote_enable_title=0x7f0d0137; + public static final int remote_keys_imported=0x7f0d0138; + public static final int remote_nothing_to_import=0x7f0d0139; + public static final int remux_command_summary=0x7f0d013a; + public static final int remux_command_title=0x7f0d013b; + public static final int remux_enable_summary=0x7f0d013c; + public static final int remux_enable_title=0x7f0d013d; + public static final int remux_parameter_summary=0x7f0d013e; + public static final int remux_parameter_title=0x7f0d013f; + public static final int remux_title=0x7f0d0140; + public static final int sad_img=0x7f0d0141; + public static final int sd_card_canceled=0x7f0d0142; + public static final int sd_card_error_no_storage=0x7f0d0143; + public static final int sd_card_import_error=0x7f0d0144; + public static final int sd_card_import_error_no_file=0x7f0d0145; + public static final int sd_card_import_progress_message=0x7f0d0146; + public static final int sd_card_import_success=0x7f0d0147; + public static final int sd_card_save_error=0x7f0d0148; + public static final int sd_card_save_error_create_dir=0x7f0d0149; + public static final int sd_card_save_progress_message=0x7f0d014a; + public static final int sd_card_save_success=0x7f0d014b; + public static final int search=0x7f0d014c; + public static final int search_epg_hint=0x7f0d014d; + public static final int search_reapt=0x7f0d014e; + public static final int set_time=0x7f0d014f; + public static final int settings_backup=0x7f0d0150; + public static final int settings_backup_key=0x7f0d0151; + public static final int settings_backup_now=0x7f0d0152; + public static final int settings_backup_now_key=0x7f0d0153; + public static final int settings_backup_now_progress_message=0x7f0d0154; + public static final int settings_backup_now_summary=0x7f0d0155; + public static final int settings_backup_restore=0x7f0d0156; + public static final int settings_backup_restore_confirm_message=0x7f0d0157; + public static final int settings_backup_restore_key=0x7f0d0158; + public static final int settings_backup_restore_no_backup=0x7f0d0159; + public static final int settings_backup_restore_progress_message=0x7f0d015a; + public static final int settings_backup_restore_select_title=0x7f0d015b; + public static final int settings_backup_restore_summary=0x7f0d015c; + public static final int settings_backup_summary=0x7f0d015d; + public static final int settings_live_port=0x7f0d015e; + public static final int settings_live_port_summary=0x7f0d015f; + public static final int settings_livetv_port=0x7f0d0160; + public static final int settings_livetv_port_summary=0x7f0d0161; + public static final int settings_livetv_streamformat=0x7f0d0162; + public static final int settings_livetv_summary=0x7f0d0163; + public static final int settings_smarttvweb_port=0x7f0d0164; + public static final int settings_smarttvweb_port_summary=0x7f0d0165; + public static final int share=0x7f0d0166; + public static final int share_chooser=0x7f0d0167; + public static final int sort=0x7f0d0168; + public static final int sortby=0x7f0d0169; + public static final int sortby_alphabet=0x7f0d016a; + public static final int sortby_channel=0x7f0d016b; + public static final int sortby_channellist=0x7f0d016c; + public static final int sortby_time=0x7f0d016d; + public static final int status_bar_notification_info_overflow=0x7f0d016e; + public static final int stream_as=0x7f0d016f; + public static final int stream_choose_audio=0x7f0d0170; + public static final int stream_via=0x7f0d0171; + public static final int stream_via_as=0x7f0d0172; + public static final int streaming_password_key=0x7f0d0173; + public static final int streaming_password_sum=0x7f0d0174; + public static final int streaming_password_title=0x7f0d0175; + public static final int streaming_username_key=0x7f0d0176; + public static final int streaming_username_sum=0x7f0d0177; + public static final int streaming_username_title=0x7f0d0178; + public static final int svdrp_port_summary=0x7f0d0179; + public static final int svdrp_port_title=0x7f0d017a; + public static final int switch_to_channel=0x7f0d017b; + public static final int switching_failed=0x7f0d017c; + public static final int switching_success=0x7f0d017d; + public static final int timer_already_exists=0x7f0d017e; + public static final int timer_created=0x7f0d017f; + public static final int timer_default_lifetime_key=0x7f0d0180; + public static final int timer_default_lifetime_summary=0x7f0d0181; + public static final int timer_default_lifetime_title=0x7f0d0182; + public static final int timer_default_primary_limit_key=0x7f0d0183; + public static final int timer_default_primary_limit_summary=0x7f0d0184; + public static final int timer_default_primary_limit_title=0x7f0d0185; + public static final int timer_default_priority_key=0x7f0d0186; + public static final int timer_default_priority_summary=0x7f0d0187; + public static final int timer_default_priority_title=0x7f0d0188; + public static final int timer_detail_channel_title=0x7f0d0189; + public static final int timer_detail_day_title=0x7f0d018a; + public static final int timer_detail_end_title=0x7f0d018b; + public static final int timer_detail_lifetime=0x7f0d018c; + public static final int timer_detail_lifetime_hint=0x7f0d018d; + public static final int timer_detail_priority=0x7f0d018e; + public static final int timer_detail_priority_hint=0x7f0d018f; + public static final int timer_detail_repeat_title=0x7f0d0190; + public static final int timer_detail_start_title=0x7f0d0191; + public static final int timer_detail_title_title=0x7f0d0192; + public static final int timer_detail_title_vps=0x7f0d0193; + public static final int timer_detail_use_vps=0x7f0d0194; + public static final int timer_details_add_title=0x7f0d0195; + public static final int timer_details_create_title=0x7f0d0196; + public static final int timer_details_delete_title=0x7f0d0197; + public static final int timer_details_modify_title=0x7f0d0198; + public static final int timer_details_save_title=0x7f0d0199; + public static final int timer_error=0x7f0d019a; + public static final int timer_post_end_buffer_key=0x7f0d019b; + public static final int timer_post_end_buffer_summary=0x7f0d019c; + public static final int timer_post_end_buffer_title=0x7f0d019d; + public static final int timer_pre_start_buffer_key=0x7f0d019e; + public static final int timer_pre_start_buffer_summary=0x7f0d019f; + public static final int timer_pre_start_buffer_title=0x7f0d01a0; + public static final int timer_preferences=0x7f0d01a1; + public static final int timezone_key=0x7f0d01a2; + public static final int type_to_filter=0x7f0d01a3; + public static final int update_will_start_in=0x7f0d01a4; + public static final int vdr_advanced_preferences=0x7f0d01a5; + public static final int vdr_advanced_preferences_summary=0x7f0d01a6; + public static final int vdr_conntimeout_key=0x7f0d01a7; + public static final int vdr_conntimeout_sum=0x7f0d01a8; + public static final int vdr_conntimeout_title=0x7f0d01a9; + public static final int vdr_device_delete_qeustion=0x7f0d01aa; + public static final int vdr_devices=0x7f0d01ab; + public static final int vdr_devices_category=0x7f0d01ac; + public static final int vdr_devices_summary=0x7f0d01ad; + public static final int vdr_encoding_key=0x7f0d01ae; + public static final int vdr_encoding_summary=0x7f0d01af; + public static final int vdr_encoding_title=0x7f0d01b0; + public static final int vdr_error_text=0x7f0d01b1; + public static final int vdr_host_key=0x7f0d01b2; + public static final int vdr_host_not_defined=0x7f0d01b3; + public static final int vdr_host_summary=0x7f0d01b4; + public static final int vdr_host_title=0x7f0d01b5; + public static final int vdr_name_key=0x7f0d01b6; + public static final int vdr_name_summary=0x7f0d01b7; + public static final int vdr_name_title=0x7f0d01b8; + public static final int vdr_password_key=0x7f0d01b9; + public static final int vdr_password_summary=0x7f0d01ba; + public static final int vdr_password_title=0x7f0d01bb; + public static final int vdr_port_default=0x7f0d01bc; + public static final int vdr_port_key=0x7f0d01bd; + public static final int vdr_port_summary=0x7f0d01be; + public static final int vdr_port_title=0x7f0d01bf; + public static final int vdr_preferences=0x7f0d01c0; + public static final int vdr_prefs_category=0x7f0d01c1; + public static final int vdr_readtimeout_key=0x7f0d01c2; + public static final int vdr_readtimeout_sum=0x7f0d01c3; + public static final int vdr_readtimeout_title=0x7f0d01c4; + public static final int vdr_ssl_key=0x7f0d01c5; + public static final int vdr_ssl_summary=0x7f0d01c6; + public static final int vdr_ssl_title=0x7f0d01c7; + public static final int vdr_stream_format=0x7f0d01c8; + public static final int vdr_stream_port=0x7f0d01c9; + public static final int vdr_stream_proxy_key=0x7f0d01ca; + public static final int vdr_timeout_key=0x7f0d01cb; + public static final int vdr_timeout_sum=0x7f0d01cc; + public static final int vdr_timeout_title=0x7f0d01cd; + public static final int vdr_timezone_summary=0x7f0d01ce; + public static final int vdr_timezone_title=0x7f0d01cf; + public static final int wakeup_enabled_key=0x7f0d01d0; + public static final int wakeup_enabled_summary=0x7f0d01d1; + public static final int wakeup_enabled_title=0x7f0d01d2; + public static final int wakeup_method_key=0x7f0d01d3; + public static final int wakeup_method_summary=0x7f0d01d4; + public static final int wakeup_method_title=0x7f0d01d5; + public static final int wakeup_password_key=0x7f0d01d6; + public static final int wakeup_password_summary=0x7f0d01d7; + public static final int wakeup_password_title=0x7f0d01d8; + public static final int wakeup_preferences=0x7f0d01d9; + public static final int wakeup_url_key=0x7f0d01da; + public static final int wakeup_url_summary=0x7f0d01db; + public static final int wakeup_url_title=0x7f0d01dc; + public static final int wakeup_user_key=0x7f0d01dd; + public static final int wakeup_user_summary=0x7f0d01de; + public static final int wakeup_user_title=0x7f0d01df; + public static final int wakeup_wol_custom_boradcast_summary=0x7f0d01e0; + public static final int wakeup_wol_custom_boradcast_title=0x7f0d01e1; + public static final int wakeup_wol_custom_broadcast_key=0x7f0d01e2; + public static final int wakeup_wol_mac_key=0x7f0d01e3; + public static final int wakeup_wol_mac_summary=0x7f0d01e4; + public static final int wakeup_wol_mac_title=0x7f0d01e5; + public static final int zone_list_menu_sort_alphabetically=0x7f0d01e6; + public static final int zone_list_menu_sort_by_timezone=0x7f0d01e7; } public static final class style { public static final int AlertDialog_AppCompat=0x7f0e0000; diff --git a/vdrmanager/de.bjusystems.vdrmanager/lint.xml b/vdrmanager/de.bjusystems.vdrmanager/lint.xml new file mode 100644 index 0000000..ae17812 --- /dev/null +++ b/vdrmanager/de.bjusystems.vdrmanager/lint.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/vdrmanager/de.bjusystems.vdrmanager/release/de.bjusystems.vdrmanager-release.apk b/vdrmanager/de.bjusystems.vdrmanager/release/de.bjusystems.vdrmanager-release.apk new file mode 100644 index 0000000..68f48f9 Binary files /dev/null and b/vdrmanager/de.bjusystems.vdrmanager/release/de.bjusystems.vdrmanager-release.apk differ diff --git a/vdrmanager/de.bjusystems.vdrmanager/release/output.json b/vdrmanager/de.bjusystems.vdrmanager/release/output.json new file mode 100644 index 0000000..98f40ef --- /dev/null +++ b/vdrmanager/de.bjusystems.vdrmanager/release/output.json @@ -0,0 +1 @@ +[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":12710},"path":"de.bjusystems.vdrmanager-release.apk","properties":{"packageId":"de.bjusystems.vdrmanager","split":"","minSdkVersion":"8"}}] \ No newline at end of file diff --git a/vdrmanager/de.bjusystems.vdrmanager/src/main/AndroidManifest.xml b/vdrmanager/de.bjusystems.vdrmanager/src/main/AndroidManifest.xml index cfedf7f..ad02637 100644 --- a/vdrmanager/de.bjusystems.vdrmanager/src/main/AndroidManifest.xml +++ b/vdrmanager/de.bjusystems.vdrmanager/src/main/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="12710" + android:versionName="12.71"> @@ -20,11 +20,11 @@ android:hardwareAccelerated="true" android:icon="@drawable/app_logo" android:label="@string/app_name" - android:theme="@style/AppTheme" > + android:theme="@style/AppTheme"> + android:label="@string/app_name"> @@ -43,7 +43,7 @@ android:configChanges="orientation|locale|screenSize" /> + android:configChanges="orientation|locale|screenSize"> @@ -54,7 +54,7 @@ + android:configChanges="orientation|locale|screenSize"> @@ -68,7 +68,7 @@ android:configChanges="orientation|locale|screenSize" /> + android:configChanges="orientation|locale|screenSize"> @@ -79,7 +79,7 @@ + android:configChanges="orientation|locale|screenSize"> @@ -91,7 +91,7 @@ + android:windowSoftInputMode="stateHidden"> @@ -102,7 +102,7 @@ + android:configChanges="orientation|locale|screenSize"> @@ -114,7 +114,7 @@ + android:launchMode="singleTask"> @@ -156,7 +156,13 @@ + android:configChanges="orientation|locale|screenSize"> + + + + + + diff --git a/vdrmanager/de.bjusystems.vdrmanager/src/main/java/com/rajasharan/widget/BitmapDecorator.java b/vdrmanager/de.bjusystems.vdrmanager/src/main/java/com/rajasharan/widget/BitmapDecorator.java new file mode 100644 index 0000000..4dedc32 --- /dev/null +++ b/vdrmanager/de.bjusystems.vdrmanager/src/main/java/com/rajasharan/widget/BitmapDecorator.java @@ -0,0 +1,90 @@ +package com.rajasharan.widget; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.drawable.GradientDrawable; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +/** + * Created by rajasharan on 9/13/15. + */ +class BitmapDecorator extends RecyclerView.ItemDecoration { + private Paint mWhitePaint; + private GradientDrawable mD; + + public BitmapDecorator(Context context) { + mWhitePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mWhitePaint.setStyle(Paint.Style.FILL); + mWhitePaint.setColor(Color.WHITE); + mD = new GradientDrawable(GradientDrawable.Orientation.BOTTOM_TOP, null); + mD.setColor(Color.argb(128, 128, 128, 128)); + mD.setGradientType(GradientDrawable.SWEEP_GRADIENT); + } + + @Override + public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { + transformChildren(c, parent); + } + + private void transformChildren(Canvas canvas, RecyclerView parent) { + int childCount = parent.getChildCount(); + int middlePos = (childCount - 1) / 2; + + canvas.drawARGB(255, 255, 255, 255); + + for (int i = 0; i < childCount; i++) { + if (i == middlePos) { + continue; + } + View child = parent.getChildAt(i); + if (child != null) { + Bitmap b = child.getDrawingCache(); + if (b != null) { + canvas.drawBitmap(b, child.getLeft(), child.getTop(), null); + } + } + } + + View child = parent.getChildAt(middlePos); + if (child != null) { + Rect r = new Rect(); + child.getHitRect(r); + Bitmap b = child.getDrawingCache(); + if (b != null) { + canvas.save(); + mD.setColor(Color.argb(32, 128, 128, 128)); + mD.setBounds(child.getLeft(), child.getTop() - 6, child.getRight(), child.getTop() - 4); + mD.draw(canvas); + + mD.setColor(Color.argb(64, 128, 128, 128)); + mD.setBounds(child.getLeft(), child.getTop() - 4, child.getRight(), child.getTop() - 2); + mD.draw(canvas); + + mD.setColor(Color.argb(128, 128, 128, 128)); + mD.setBounds(child.getLeft(), child.getTop() - 2, child.getRight(), child.getTop()); + mD.draw(canvas); + + canvas.scale(2.0f, 2.0f, r.centerX(), r.centerY()); + canvas.drawBitmap(b, child.getLeft(), child.getTop(), null); + + mD.setColor(Color.argb(128, 128, 128, 128)); + mD.setBounds(child.getLeft(), child.getBottom(), child.getRight(), child.getBottom() + 2); + mD.draw(canvas); + + mD.setColor(Color.argb(64, 128, 128, 128)); + mD.setBounds(child.getLeft(), child.getBottom() + 2, child.getRight(), child.getBottom() + 4); + mD.draw(canvas); + + mD.setColor(Color.argb(32, 128, 128, 128)); + mD.setBounds(child.getLeft(), child.getBottom() + 4, child.getRight(), child.getBottom() + 6); + mD.draw(canvas); + canvas.restore(); + } + } + } +} diff --git a/vdrmanager/de.bjusystems.vdrmanager/src/main/java/com/rajasharan/widget/RecyclerDropdown.java b/vdrmanager/de.bjusystems.vdrmanager/src/main/java/com/rajasharan/widget/RecyclerDropdown.java new file mode 100644 index 0000000..d515809 --- /dev/null +++ b/vdrmanager/de.bjusystems.vdrmanager/src/main/java/com/rajasharan/widget/RecyclerDropdown.java @@ -0,0 +1,172 @@ +package com.rajasharan.widget; + +import android.content.Context; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; +import de.bjusystems.vdrmanager.R; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by rajasharan on 8/28/15. + */ +public class RecyclerDropdown extends RecyclerView { + private static final String TAG = "RecyclerDropdown"; + private static final CharSequence [] EMPTY_LIST = new CharSequence[] {Adapter.EMPTY_TEXT}; + + private CharSequence [] mList; + private CharSequence [] mOriginalList; + private Adapter mAdapter; + private OnClickListener mListener; + + public RecyclerDropdown(Context context) { + this(context, null); + } + + public RecyclerDropdown(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public RecyclerDropdown(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + mAdapter = new Adapter(); + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + setDropdownList(null); + setAdapter(mAdapter); + setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false)); + //addItemDecoration(new BitmapDecorator(getContext())); + addItemDecoration(new ShadowDecorator(getContext())); + } + + public void setDropdownList(CharSequence [] list) { + if (list == null) { + mList = EMPTY_LIST; + } else { + mList = list; + } + mAdapter.init(mList); + mAdapter.notifyDataSetChanged(); + //scrollToPosition(mList.length / 2); + } + + public void filter(String str) { + if (mOriginalList == null) { + mOriginalList = mList.clone(); + } + if (str != null && str.trim().length() != 0) { + List list = new ArrayList<>(); + for (CharSequence cs : mOriginalList) { + if (cs.toString().toUpperCase().contains(str.toUpperCase())) { + list.add(cs); + } + } + if (list.size() == 0) { + mList = EMPTY_LIST; + } else { + mList = list.toArray(new CharSequence[list.size()]); + } + } + else { + mList = mOriginalList; + } + setDropdownList(mList); + } + + private static class Adapter extends RecyclerView.Adapter { + private static final int NORMAL_TYPE = 1; + private static final int EMPTY_TYPE = 2; + private static final int BUFFER_TYPE = 3; + + private static final String EMPTY_TEXT = "NO ITEMS"; + private static final String BUFFER_ITEM = "BUFFER ITEM"; + + private CharSequence [] mList; + + public void init(CharSequence [] list) { + mList = new CharSequence[list.length+4]; + mList[0] = BUFFER_ITEM; + mList[1] = BUFFER_ITEM; + System.arraycopy(list, 0, mList, 2, list.length); + mList[mList.length-1] = BUFFER_ITEM; + mList[mList.length-2] = BUFFER_ITEM; + } + @Override + public Holder onCreateViewHolder(ViewGroup viewGroup, int type) { + LayoutInflater inflater = (LayoutInflater) viewGroup.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + View view; + switch (type) { + case NORMAL_TYPE: { + view = inflater.inflate(R.layout.recycler_itemviews, viewGroup, false); + break; + } + case EMPTY_TYPE: { + view = inflater.inflate(R.layout.recycler_itemviews, viewGroup, false); + Holder holder = new Holder(view); + holder.mTextView.setGravity(Gravity.CENTER); + view.setTag(R.id.text, EMPTY_TEXT); + return holder; + } + default /*BUFFER_TYPE*/ : { + view = inflater.inflate(R.layout.recycler_buffer_item, viewGroup, false); + Holder holder = new Holder(view); + return holder; + } + } + Holder holder = new Holder(view); + holder.mTextView.setGravity(Gravity.CENTER); + return holder; + } + @Override + public void onBindViewHolder(Holder holder, int pos) { + if (mList[pos % mList.length].toString().equals(BUFFER_ITEM)) { + return; + } + holder.mTextView.setText(mList[pos % mList.length]); + } + @Override + public int getItemCount() { + return mList.length; + } + + @Override + public int getItemViewType(int position) { + if (mList[position % mList.length].toString().equals(EMPTY_TEXT)) { + return EMPTY_TYPE; + } + if (mList[position % mList.length].toString().equals(BUFFER_ITEM)) { + return BUFFER_TYPE; + } + return NORMAL_TYPE; + } + } + + private static class Holder extends ViewHolder { + private TextView mTextView; + public Holder(View itemView) { + super(itemView); + if (itemView instanceof TextView) { + mTextView = (TextView) itemView; + } + } + } + + public void setOnClickListener(OnClickListener listener) { + mListener = listener; + } + + public OnClickListener getOnClickListener() { + return mListener; + } + +} diff --git a/vdrmanager/de.bjusystems.vdrmanager/src/main/java/com/rajasharan/widget/SearchableSpinner.java b/vdrmanager/de.bjusystems.vdrmanager/src/main/java/com/rajasharan/widget/SearchableSpinner.java new file mode 100644 index 0000000..6ce336a --- /dev/null +++ b/vdrmanager/de.bjusystems.vdrmanager/src/main/java/com/rajasharan/widget/SearchableSpinner.java @@ -0,0 +1,209 @@ +package com.rajasharan.widget; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Color; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.EditText; +import android.widget.TextView; +import de.bjusystems.vdrmanager.R; + +/** + * Created by rajasharan on 8/28/15. + */ +public class SearchableSpinner extends ViewGroup implements TextWatcher, View.OnClickListener { + private static final String TAG = "Searchable_Spinner"; + + private CharSequence [] mList; + private TextView mText; + private TextView mDropdownArrow; + private AlertDialog mDialog; + private RecyclerDropdown mRecycler; + private OnSelectionChangeListener mListener; + + public SearchableSpinner(Context context) { + this(context, null); + } + + public SearchableSpinner(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SearchableSpinner(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context, attrs); + } + + private void init(Context context, AttributeSet attrs) { + mText = new TextView(context); + mText.setTextColor(Color.BLACK); + mText.setLayoutParams(generateDefaultLayoutParams()); + + mDropdownArrow = new TextView(context); + mDropdownArrow.setText("\u25BC"); + mDropdownArrow.setLayoutParams(generateDefaultLayoutParams()); + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SearchableSpinner); + setList(a.getTextArray(R.styleable.SearchableSpinner_list)); + a.recycle(); + + int [] paddingAttrs = new int[] { + android.R.attr.padding, + android.R.attr.paddingLeft, android.R.attr.paddingTop, + android.R.attr.paddingRight, android.R.attr.paddingBottom}; + + a = context.obtainStyledAttributes(attrs, paddingAttrs); + for (int i=0; i 0) { + mText.setText(mList[0]); + mDialog = createDialog(getContext()); + } + } + + private int setPadding(int p, int sideIndex) { + if (p != -1) { + switch (sideIndex) { + case 0: + mText.setPadding(p, p, p, p); + mDropdownArrow.setPadding(p, p, p, p); + break; + case 1: + mText.setPadding(p, getPaddingTop(), getPaddingRight(), getPaddingBottom()); + mDropdownArrow.setPadding(p, getPaddingTop(), getPaddingRight(), getPaddingBottom()); + break; + case 2: + mText.setPadding(getPaddingLeft(), p, getPaddingRight(), getPaddingBottom()); + mDropdownArrow.setPadding(getPaddingLeft(), p, getPaddingRight(), getPaddingBottom()); + break; + case 3: + mText.setPadding(getPaddingLeft(), getPaddingTop(), p, getPaddingBottom()); + mDropdownArrow.setPadding(getPaddingLeft(), getPaddingTop(), p, getPaddingBottom()); + break; + case 4: + mText.setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), p); + mDropdownArrow.setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), p); + break; + } + } + return -1; + } + + private AlertDialog createDialog(Context context) { + AlertDialog.Builder builder = new AlertDialog.Builder(context); + LayoutInflater inflater = LayoutInflater.from(context); + View view = inflater.inflate(R.layout.dialog_dropdown, null); + + EditText filter = (EditText) view.findViewById(R.id.filter); + filter.setHint("\uD83D\uDD0D search"); + filter.addTextChangedListener(this); + + mRecycler = (RecyclerDropdown) view.findViewById(R.id.list); + mRecycler.setOnClickListener(this); + mRecycler.setDropdownList(mList); + mRecycler.scrollToPosition(mList.length/2); + + builder.setView(view); + return builder.create(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + mText.measure(0, 0); + mDropdownArrow.measure(0, 0); + + int w = MeasureSpec.getSize(widthMeasureSpec); + int h = MeasureSpec.getSize(heightMeasureSpec); + + int desiredWidth = Math.min(mText.getMeasuredWidth() + mDropdownArrow.getMeasuredWidth(), w); + int desiredHeight = Math.min(mText.getMeasuredHeight(), h); + + //Log.d(TAG, String.format("onMeasure: (%s, %s)", desiredWidth, desiredHeight)); + + widthMeasureSpec = MeasureSpec.makeMeasureSpec(desiredWidth, MeasureSpec.EXACTLY); + heightMeasureSpec = MeasureSpec.makeMeasureSpec(desiredHeight, MeasureSpec.EXACTLY); + setMeasuredDimension(widthMeasureSpec, heightMeasureSpec); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + mText.layout(l, t, l + mText.getMeasuredWidth(), b); + mDropdownArrow.layout(l + mText.getMeasuredWidth(), t, r, b); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + mText.draw(canvas); + int save = canvas.save(); + canvas.translate(mText.getWidth(), 0); + mDropdownArrow.draw(canvas); + canvas.restoreToCount(save); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + switch (event.getActionMasked()) { + case MotionEvent.ACTION_UP: + if (mDialog != null && !mDialog.isShowing()) { + mDialog.show(); + } + } + return true; + } + + private void updateSelection(CharSequence str) { + mText.setText(str); + requestLayout(); + invalidate(); + if (mListener != null) { + mListener.onSelectionChanged(str.toString()); + } + } + + public String getSelectedItem() { + if (mText != null) { + return mText.getText().toString(); + } + return null; + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + mRecycler.filter(s.toString()); + } + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + @Override + public void afterTextChanged(Editable s) { + } + + @Override + public void onClick(View v) { + if (mDialog.isShowing()) { + mDialog.dismiss(); + } + updateSelection(((TextView)v).getText()); + } + + public void setOnSelectionChangeListener(OnSelectionChangeListener listener) { + mListener = listener; + } + + public interface OnSelectionChangeListener { + public void onSelectionChanged(String selection); + } +} diff --git a/vdrmanager/de.bjusystems.vdrmanager/src/main/java/com/rajasharan/widget/ShadowDecorator.java b/vdrmanager/de.bjusystems.vdrmanager/src/main/java/com/rajasharan/widget/ShadowDecorator.java new file mode 100644 index 0000000..11abedc --- /dev/null +++ b/vdrmanager/de.bjusystems.vdrmanager/src/main/java/com/rajasharan/widget/ShadowDecorator.java @@ -0,0 +1,103 @@ +package com.rajasharan.widget; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import de.bjusystems.vdrmanager.R; + +/** + * Created by rajasharan on 9/13/15. + */ +public class ShadowDecorator extends RecyclerView.ItemDecoration { + private static final String TAG = "ShadowDecorator"; + private static final int SHADOW_INSET = 2; + + private Context mContext; + private Paint mCoreShadow; + private Paint mOvertone; + private Paint mHighlight; + private int mHeight; + private int mInset; + + public ShadowDecorator(Context context) { + mContext = context; + + mCoreShadow = new Paint(Paint.ANTI_ALIAS_FLAG); + mCoreShadow.setColor(Color.argb(128, 128, 128, 128)); + mCoreShadow.setStyle(Paint.Style.FILL); + + mOvertone = new Paint(Paint.ANTI_ALIAS_FLAG); + mOvertone.setColor(Color.argb(64, 128, 128, 128)); + mOvertone.setStyle(Paint.Style.FILL); + + mHighlight = new Paint(Paint.ANTI_ALIAS_FLAG); + mHighlight.setColor(Color.argb(32, 128, 128, 128)); + mHighlight.setStyle(Paint.Style.FILL); + + mHeight = (int) (mContext.getResources().getDimension(R.dimen.item_height)); + mInset = (int) mContext.getResources().getDimension(R.dimen.item_inset); + } + + @Override + public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { + int count = parent.getChildCount(); + int middlePos = (count - 1)/2; + + int t = 2 * mHeight - mInset; + int b = 3 * mHeight + mInset; + + /* TOP SHADOW */ + c.drawRect(parent.getLeft(), t, parent.getRight(), t + SHADOW_INSET, mHighlight); + c.drawRect(parent.getLeft(), t + SHADOW_INSET, parent.getRight(), t + 2 * SHADOW_INSET, mOvertone); + c.drawRect(parent.getLeft(), t + 2 * SHADOW_INSET, parent.getRight(), t + 3 * SHADOW_INSET, mCoreShadow); + + /* BOTTOM SHADOW */ + c.drawRect(parent.getLeft(), b - 3 * SHADOW_INSET, parent.getRight(), b - 2 * SHADOW_INSET, mCoreShadow); + c.drawRect(parent.getLeft(), b - 2 * SHADOW_INSET, parent.getRight(), b - SHADOW_INSET, mOvertone); + c.drawRect(parent.getLeft(), b - SHADOW_INSET, parent.getRight(), b, mHighlight); + + for (int i=0; i=0; i--,j++) { + View child = parent.getChildAt(i); + if (child != null) { + child.setRotationX(25 * j); + child.setAlpha(1.0f/(count - i)); + } + } + + { + View child = parent.getChildAt(middlePos); + if (child != null) { + child.setAlpha(0.5f); + int childMidPoint = (child.getTop() + child.getBottom())/2; + if (childMidPoint >= t && childMidPoint <= b) { + if (child.getTag(R.id.text) == null) { + child.setScaleX(2.2f); + child.setScaleY(2.2f); + child.setOnClickListener(((RecyclerDropdown) parent).getOnClickListener()); + child.setAlpha(1.0f); + } + } + } + } + + for (int i=middlePos+1, j=1; i highlight2(final String where, - String what) { - if (TextUtils.isEmpty(what)) { - return Pair.create(Boolean.FALSE, (CharSequence) where); - } - - final String str = where.toLowerCase(); - what = what.toLowerCase(); - final int idx = str.indexOf(what); - if (idx == -1) { - return Pair.create(Boolean.FALSE, (CharSequence) where); - } - final SpannableString ss = new SpannableString(where); - ss.setSpan(HIGHLIGHT_TEXT, idx, idx + what.length(), - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - return Pair.create(Boolean.TRUE, (CharSequence) ss); - } - - public static int getProgress(final Date start, final Date stop) { - final long now = System.currentTimeMillis(); - return getProgress(now, start.getTime(), stop.getTime()); - } - - public static int getProgress(final Event e) { - if (e instanceof Recording == false) { - return getProgress(e.getStart(), e.getStop()); - } - final Recording r = ((Recording) e); - if (r.getTimerStopTime() == null) { - return getProgress(e.getStart(), e.getStop()); - } - return getProgress(r.getStart(), r.getTimerStopTime()); - - } - - /** - * @param now - * @param time - * @param time2 - * @return -1, is not not between start stop, - */ - private static int getProgress(final long now, final long start, - final long stop) { - if (now >= start && now <= stop) { - final long dura = stop - start; - final long prog = now - start; - return (int) (prog * 100 / dura); - } - return -1; - } - - public static boolean isLive(final Event event) { - final long now = System.currentTimeMillis(); - return now >= event.getStart().getTime() - && now <= event.getStop().getTime(); - } - - private static String trimToEmpty(final String str) { - if (str == null) { - return ""; - } - if (TextUtils.isEmpty(str)) { - return ""; - } - return str; - } - - private static String getBaseUrl() { - final StringBuilder sb = new StringBuilder(); - final Preferences p = Preferences.get(); - String auth = trimToEmpty(p.getStreamingUsername()) + ":" - + trimToEmpty(p.getStreamingPassword()); - if (auth.length() == 1) { - auth = ""; - } else { - auth += "@"; - } - - sb.append("http://").append(auth).append(p.getHost()).append(":") - .append(p.getStreamPort()); - return sb.toString(); - } - - private static String getStreamUrl(final String chn) { - // "http://192.168.1.119:3000/TS/" - final Preferences p = Preferences.get(); - final StringBuilder sb = new StringBuilder(); - sb.append(getBaseUrl()).append("/").append(p.getStreamFormat()) - .append("/").append(chn); - - return sb.toString(); - } - - private static String getRemuxStreamUrl(final String chn) { - // "http://192.168.1.119:3000/TS/" - final StringBuilder sb = new StringBuilder(); - final Preferences p = Preferences.get(); - sb.append(getBaseUrl()).append("/").append(p.getRemuxCommand()) - .append(";").append(p.getRemuxParameter()).append("/") - .append(chn); - return sb.toString(); - } - - public static void stream(final Activity activity, final Event event) { - stream(activity, event.getStreamId()); - } - - public static void stream(final Activity activity, final Channel channel) { - stream(activity, channel.getId()); - } - - public static void stream(final Activity activity, final String idornr) { - - if (Preferences.get().isEnableRemux() == false) { - final String url = getStreamUrl(idornr); - startStream(activity, url); - return; - } - - final String sf = Preferences.get().getStreamFormat(); - final String ext = activity.getString(R.string.remux_title); - new AlertDialog.Builder(activity) - .setTitle(R.string.stream_via_as) - // - .setItems( - new String[] { - activity.getString(R.string.stream_as, sf), - activity.getString(R.string.stream_via, ext) },// TODO - // add - // here - // what - // will - // be - // used - new DialogInterface.OnClickListener() { - @Override - public void onClick(final DialogInterface dialog, - final int which) { - String url = null; - switch (which) { - case 0: - url = getStreamUrl(idornr); - break; - case 1: - url = getRemuxStreamUrl(idornr); - break; - } - startStream(activity, url); - } - }).create().show(); - } - - public static void startStream(final Activity activity, final String url) { - try { - final Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setDataAndType(Uri.parse(url.toString()), "video/*"); - activity.startActivityForResult(intent, 1); - } catch (final ActivityNotFoundException anfe) { - Log.w(TAG, anfe); - Toast.makeText(activity, anfe.getLocalizedMessage(), - Toast.LENGTH_SHORT).show(); - } - } - - public static final String md5(final String s) { - try { - // Create MD5 Hash - final MessageDigest digest = java.security.MessageDigest - .getInstance("MD5"); - digest.update(s.getBytes()); - final byte messageDigest[] = digest.digest(); - - // Create Hex String - final StringBuffer hexString = new StringBuffer(); - for (int i = 0; i < messageDigest.length; i++) { - String h = Integer.toHexString(0xFF & messageDigest[i]); - while (h.length() < 2) { - h = "0" + h; - } - hexString.append(h); - } - return hexString.toString(); - - } catch (final NoSuchAlgorithmException e) { - Log.w(TAG, e); - } - return ""; - } - - public static int getDuration(final Event event) { - final long millis = event.getDuration(); - final int minuts = (int) (millis / 1000 / 60); - return minuts; - } - - public static void shareEvent(final Activity activity, final Event event) { - final Intent share = new Intent(android.content.Intent.ACTION_SEND); - share.setType("text/plain"); - StringBuilder sb = new StringBuilder(); - sb.append(event.getTitle()); - sb.append("\n"); - final EventFormatter ef = new EventFormatter(event, false); - sb.append(ef.getDate()).append(" ").append(ef.getTime()); - final String title = sb.toString(); - share.putExtra(android.content.Intent.EXTRA_SUBJECT, sb.toString()); - sb = new StringBuilder(); - sb.append(title).append("\n\n"); - sb.append(event.getChannelNumber() + " " + event.getChannelName()); - sb.append("\n\n"); - sb.append(ef.getShortText()); - sb.append("\n\n"); - sb.append(ef.getDescription()); - sb.append("\n"); - share.putExtra(android.content.Intent.EXTRA_TEXT, sb.toString()); - activity.startActivity(Intent.createChooser(share, - activity.getString(R.string.share_chooser))); - } - - public static void addCalendarEvent(final Activity activity, - final Event event) { - final Intent intent = new Intent(Intent.ACTION_EDIT); - intent.setType("vnd.android.cursor.item/event"); - intent.putExtra("title", event.getTitle()); - intent.putExtra("description", event.getShortText()); - intent.putExtra("beginTime", event.getStart().getTime()); - intent.putExtra("endTime", event.getStop().getTime()); - activity.startActivity(intent); - } - - public static String mapSpecialChars(final String src) { - if (src == null) { - return ""; - } - return src.replace("|##", C.DATA_SEPARATOR).replace("||#", "\n"); - } - - public static String unMapSpecialChars(final String src) { - if (src == null) { - return ""; - } - return src.replace(C.DATA_SEPARATOR, "|##").replace("\n", "||#"); - } - - public static PackageInfo getPackageInfo(final Context ctx) { - PackageInfo pi = null; - try { - pi = ctx.getPackageManager().getPackageInfo(ctx.getPackageName(), - PackageManager.GET_ACTIVITIES); - } catch (final PackageManager.NameNotFoundException e) { - e.printStackTrace(); - } - return pi; - } - - public static boolean checkInternetConnection(final Context ctx) { - final ConnectivityManager cm = (ConnectivityManager) ctx - .getSystemService(Context.CONNECTIVITY_SERVICE); - // test for connection - if (cm.getActiveNetworkInfo() != null - && cm.getActiveNetworkInfo().isConnectedOrConnecting()) { - return true; - } - return false; - } - - private static String getRecordingStream(final Activity ctx, - final Recording rec) { - - - Preferences prefs = Preferences.get(); - - final String m = prefs.getRecStreamMethod(); - - final StringBuilder url = new StringBuilder(); - - if (StringUtils.equals(m, "vdr-live")) { - url.append("http://") - .append(prefs.getHost()) - // - .append(":") - .append(Integer.valueOf(prefs.getLivePort())) - // - .append("/recstream.html?recid=recording_") - .append(Utils.md5(rec.getFileName())); - // http://192.168.1.119:8008/b0cdedeed2d36508dfd924f0876a851b - final String urlstring = url.toString(); - return urlstring; - } else if (StringUtils.equals(m, "vdr-streamdev")) { - url.append("http://").append(prefs.getHost()) - // - .append(":") - .append(Integer.valueOf( - prefs.getStreamPort())) - // - .append("/").append(rec.getDevInode()); - } else if (StringUtils.equals(m, "vdr-smarttvweb")) { - - String type = prefs.getSmarttvewebType(); - - url.append("http://") - .append(prefs.getHost()) - // - .append(":") - .append(Integer.valueOf(prefs - .getSmarttvewebPort())) - // - .append(Utils.encodeUrlPath(rec.getFileName())); - if (StringUtils.equals(type, "has") == true) { - url.append("/manifest-seg.mpd"); - } else if (StringUtils.equals(type, "hls")) { - url.append("/manifest-seg.m3u8"); - } - } - return url.toString(); - } - - public static void streamRecording(final Activity ctx, final Recording rec) { - final String urlstring = getRecordingStream(ctx, rec); - Log.d(TAG, "try stream: " + urlstring); - Utils.startStream(ctx, urlstring); - } - - public static void switchTo(final Activity activity, final Channel channel) { - switchTo(activity, channel.getId(), channel.getName()); - } - - /** - * @param ctx - * @param id - * @param name - * Optional für die Anzeige - */ - public static void switchTo(final Activity activity, final String id, - final String name) { - - final SwitchChannelClient scc = new SwitchChannelClient(id, - new CertificateProblemDialog(activity)); - final SvdrpAsyncTask task = new SvdrpAsyncTask( - scc); - task.addSvdrpListener(new SvdrpListener() { - @Override - public void svdrpEvent(final SvdrpEvent event) { - if (event == SvdrpEvent.FINISHED_SUCCESS) { - Utils.say(activity, activity.getString( - R.string.switching_success, (name != null ? name - : id))); - } else if (event == SvdrpEvent.CONNECT_ERROR - || event == SvdrpEvent.FINISHED_ABNORMALY - || event == SvdrpEvent.ABORTED - || event == SvdrpEvent.ERROR - || event == SvdrpEvent.CACHE_HIT) { - Utils.say(activity, activity.getString( - R.string.switching_failed, (name != null ? name - : id), event.name())); - } - } - - public void svdrpException(final SvdrpException e) { - Log.w(TAG, e.getMessage(), e); - Utils.say(activity, e.getMessage()); - } - }); - task.run(); - } - - public static void say(final Context ctx, final String msg) { - final Toast t = Toast.makeText(ctx, msg, Toast.LENGTH_SHORT); - t.setGravity(Gravity.CENTER, 0, 0); - t.show(); - } - public static String encodeUrlPath(String path){ - return path.replaceAll("%", "%25"); - } - - public static void say(final Context ctx, final int msg) { - final Toast t = Toast.makeText(ctx, msg, Toast.LENGTH_SHORT); - t.setGravity(Gravity.CENTER, 0, 0); - t.show(); - } - - /** - * Formats the date and time based on user's phone date/time preferences. - * - * @param context - * the context - * @param time - * the time in milliseconds - */ - - public static String formatDateTime(final Context context, final long time) { - return android.text.format.DateFormat.getDateFormat(context).format( - time) - + " " - + DateUtils.formatDateTime(context, time, - DateUtils.FORMAT_SHOW_TIME).toString(); - } - - public static int getTimerStateDrawable(final TimerMatch match, - final int full, final int begin, final int end, final int conflict) { - - switch (match) { - case Begin: - return begin; - case End: - return end; - case Conflict: - return conflict; - default: - return full; - } - } - - public static String formatAudio(final Context context, - final List tracks) { - - final StringBuilder sb = new StringBuilder(); - - String sep = ""; - for (final AudioTrack a : tracks) { - sb.append(sep).append(a.display); - if (a.type.equals("d")) { - sb.append(" (") - .append(context.getString(R.string.audio_track_dolby)) - .append(")"); - } - sep = ", "; - } - return sb.toString(); - - } - - public static TimerMatch getTimerMatch(Event event, Timer timer) { - if (timer == null) { - return null; - } - TimerMatch timerMatch = null; - Date start = event.getStart(); - Date stop = event.getStop(); - if (start.before(timer.getStart())) { - timerMatch = TimerMatch.End; - } else if (stop.after(timer.getStop())) { - timerMatch = TimerMatch.Begin; - } else { - timerMatch = TimerMatch.Full; - } - return timerMatch; - } - - public static int contentToString(int c) { - ; - switch (c & 0xF0) { - case EventContentGroup.MovieDrama: - switch (c & 0x0F) { - default: - case 0x00: - return R.string.Content_Movie__Drama; - case 0x01: - return R.string.Content_Detective__Thriller; - case 0x02: - return R.string.Content_Adventure__Western__War; - case 0x03: - return R.string.Content_Science_Fiction__Fantasy__Horror; - case 0x04: - return R.string.Content_Comedy; - case 0x05: - return R.string.Content_Soap__Melodrama__Folkloric; - case 0x06: - return R.string.Content_Romance; - case 0x07: - return R.string.Content_Serious__Classical__Religious__Historical_Movie__Drama; - case 0x08: - return R.string.Content_Adult_Movie__Drama; - } - case EventContentGroup.NewsCurrentAffairs: - switch (c & 0x0F) { - default: - case 0x00: - return R.string.Content_News__Current_Affairs; - case 0x01: - return R.string.Content_News__Weather_Report; - case 0x02: - return R.string.Content_News_Magazine; - case 0x03: - return R.string.Content_Documentary; - case 0x04: - return R.string.Content_Discussion__Inverview__Debate; - } - - case EventContentGroup.Show: - switch (c & 0x0F) { - default: - case 0x00: - return R.string.Content_Show__Game_Show; - case 0x01: - return R.string.Content_Game_Show__Quiz__Contest; - case 0x02: - return R.string.Content_Variety_Show; - case 0x03: - return R.string.Content_Talk_Show; - } - - case EventContentGroup.Sports: - switch (c & 0x0F) { - default: - case 0x00: - return R.string.Content_Sports; - case 0x01: - return R.string.Content_Special_Event; - case 0x02: - return R.string.Content_Sport_Magazine; - case 0x03: - return R.string.Content_Football__Soccer; - case 0x04: - return R.string.Content_Tennis__Squash; - case 0x05: - return R.string.Content_Team_Sports; - case 0x06: - return R.string.Content_Athletics; - case 0x07: - return R.string.Content_Motor_Sport; - case 0x08: - return R.string.Content_Water_Sport; - case 0x09: - return R.string.Content_Winter_Sports; - case 0x0A: - return R.string.Content_Equestrian; - case 0x0B: - return R.string.Content_Martial_Sports; - } - - case EventContentGroup.ChildrenYouth: - switch (c & 0x0F) { - default: - case 0x00: - return R.string.Content_Childrens__Youth_Programme; - case 0x01: - return R.string.Content_Preschool_Childrens_Programme; - case 0x02: - return R.string.Content_Entertainment_Programme_for_6_to_14; - case 0x03: - return R.string.Content_Entertainment_Programme_for_10_to_16; - case 0x04: - return R.string.Content_Informational__Educational__School_Programme; - case 0x05: - return R.string.Content_Cartoons__Puppets; - } - - case EventContentGroup.MusicBalletDance: - switch (c & 0x0F) { - default: - case 0x00: - return R.string.Content_Music__Ballet__Dance; - case 0x01: - return R.string.Content_Rock__Pop; - case 0x02: - return R.string.Content_Serious__Classical_Music; - case 0x03: - return R.string.Content_Folk__Tradional_Music; - case 0x04: - return R.string.Content_Jazz; - case 0x05: - return R.string.Content_Musical__Opera; - case 0x06: - return R.string.Content_Ballet; - } - - case EventContentGroup.ArtsCulture: - switch (c & 0x0F) { - default: - case 0x00: - return R.string.Content_Arts__Culture; - case 0x01: - return R.string.Content_Performing_Arts; - case 0x02: - return R.string.Content_Fine_Arts; - case 0x03: - return R.string.Content_Religion; - case 0x04: - return R.string.Content_Popular_Culture__Traditional_Arts; - case 0x05: - return R.string.Content_Literature; - case 0x06: - return R.string.Content_Film__Cinema; - case 0x07: - return R.string.Content_Experimental_Film__Video; - case 0x08: - return R.string.Content_Broadcasting__Press; - case 0x09: - return R.string.Content_New_Media; - case 0x0A: - return R.string.Content_Arts__Culture_Magazine; - case 0x0B: - return R.string.Content_Fashion; - } - - case EventContentGroup.SocialPoliticalEconomics: - switch (c & 0x0F) { - default: - case 0x00: - return R.string.Content_Social__Political__Economics; - case 0x01: - return R.string.Content_Magazine__Report__Documentary; - case 0x02: - return R.string.Content_Economics__Social_Advisory; - case 0x03: - return R.string.Content_Remarkable_People; - } - - case EventContentGroup.EducationalScience: - switch (c & 0x0F) { - default: - case 0x00: - return R.string.Content_Education__Science__Factual; - case 0x01: - return R.string.Content_Nature__Animals__Environment; - case 0x02: - return R.string.Content_Technology__Natural_Sciences; - case 0x03: - return R.string.Content_Medicine__Physiology__Psychology; - case 0x04: - return R.string.Content_Foreign_Countries__Expeditions; - case 0x05: - return R.string.Content_Social__Spiritual_Sciences; - case 0x06: - return R.string.Content_Further_Education; - case 0x07: - return R.string.Content_Languages; - } - - case EventContentGroup.LeisureHobbies: - switch (c & 0x0F) { - default: - case 0x00: - return R.string.Content_Leisure__Hobbies; - case 0x01: - return R.string.Content_Tourism__Travel; - case 0x02: - return R.string.Content_Handicraft; - case 0x03: - return R.string.Content_Motoring; - case 0x04: - return R.string.Content_Fitness_and_Health; - case 0x05: - return R.string.Content_Cooking; - case 0x06: - return R.string.Content_Advertisement__Shopping; - case 0x07: - return R.string.Content_Gardening; - } - case EventContentGroup.Special: - switch (c & 0x0F) { - case 0x00: - return R.string.Content_Original_Language; - case 0x01: - return R.string.Content_Black_and_White; - case 0x02: - return R.string.Content_Unpublished; - case 0x03: - return R.string.Content_Live_Broadcast; - default: - ; - } - break; - default: - ; - } - return R.string.Content_Unknown; - } - - public static String getContenString(Context ctx, int[] contents) { - - if (contents.length == 0) { - return ""; - } - - StringBuilder sb = new StringBuilder(); - - String sep = ""; - - for (int content : contents) { - - sb.append(sep).append(ctx.getString(contentToString(content))); - sep = ", "; - } - - return sb.toString(); - } - - public static boolean isSerie(int[] contents) { - if (contents.length == 0) { - return false; - } - - for (int c : contents) { - if (c == 21) { - return true; - - } - } - - return false; - } + public static final String TAG = Utils.class.getName(); + + public static final List EMPTY_LIST = new ArrayList(0); + public static final String[] EMPTY = new String[]{}; + public static final ForegroundColorSpan HIGHLIGHT_TEXT = new ForegroundColorSpan( + + Color.RED); + + public static CharSequence highlight(final String where, String what) { + if (TextUtils.isEmpty(what)) { + return where; + } + + final String str = where.toLowerCase(); + what = what.toLowerCase(); + final int idx = str.indexOf(what); + if (idx == -1) { + return where; + } + final SpannableString ss = new SpannableString(where); + ss.setSpan(HIGHLIGHT_TEXT, idx, idx + what.length(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + return ss; + } + + public static Pair highlight2(final String where, + String what) { + if (TextUtils.isEmpty(what)) { + return Pair.create(Boolean.FALSE, (CharSequence) where); + } + + final String str = where.toLowerCase(); + what = what.toLowerCase(); + final int idx = str.indexOf(what); + if (idx == -1) { + return Pair.create(Boolean.FALSE, (CharSequence) where); + } + final SpannableString ss = new SpannableString(where); + ss.setSpan(HIGHLIGHT_TEXT, idx, idx + what.length(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + return Pair.create(Boolean.TRUE, (CharSequence) ss); + } + + public static int getProgress(final Date start, final Date stop) { + final long now = System.currentTimeMillis(); + return getProgress(now, start.getTime(), stop.getTime()); + } + + public static int getProgress(final Event e) { + if (e instanceof Recording == false) { + return getProgress(e.getStart(), e.getStop()); + } + final Recording r = ((Recording) e); + if (r.getTimerStopTime() == null) { + return getProgress(e.getStart(), e.getStop()); + } + return getProgress(r.getStart(), r.getTimerStopTime()); + + } + + /** + * @param now + * @param time + * @param time2 + * @return -1, is not not between start stop, + */ + private static int getProgress(final long now, final long start, + final long stop) { + if (now >= start && now <= stop) { + final long dura = stop - start; + final long prog = now - start; + return (int) (prog * 100 / dura); + } + return -1; + } + + public static boolean isLive(final Event event) { + final long now = System.currentTimeMillis(); + return now >= event.getStart().getTime() + && now <= event.getStop().getTime(); + } + + private static String trimToEmpty(final String str) { + if (str == null) { + return ""; + } + if (TextUtils.isEmpty(str)) { + return ""; + } + return str; + } + + private static String getBaseUrl() { + final StringBuilder sb = new StringBuilder(); + final Preferences p = Preferences.get(); + String auth = trimToEmpty(p.getStreamingUsername()) + ":" + + trimToEmpty(p.getStreamingPassword()); + if (auth.length() == 1) { + auth = ""; + } else { + auth += "@"; + } + + sb.append("http://").append(auth).append(p.getHost()).append(":") + .append(p.getStreamPort()); + return sb.toString(); + } + + private static String getStreamUrl(final String chn) { + // "http://192.168.1.119:3000/TS/" + final Preferences p = Preferences.get(); + final StringBuilder sb = new StringBuilder(); + sb.append(getBaseUrl()).append("/").append(p.getStreamFormat()) + .append("/").append(chn); + + return sb.toString(); + } + + private static String getRemuxStreamUrl(final String chn) { + // "http://192.168.1.119:3000/TS/" + final StringBuilder sb = new StringBuilder(); + final Preferences p = Preferences.get(); + sb.append(getBaseUrl()).append("/").append(p.getRemuxCommand()) + .append(";").append(p.getRemuxParameter()).append("/") + .append(chn); + return sb.toString(); + } + + public static void stream(final Activity activity, final Event event) { + stream(activity, event.getStreamId()); + } + + public static void stream(final Activity activity, final Channel channel) { + stream(activity, channel.getId()); + } + + public static void stream(final Activity activity, final String idornr) { + + if (Preferences.get().isEnableRemux() == false) { + final String url = getStreamUrl(idornr); + startStream(activity, url); + return; + } + + final String sf = Preferences.get().getStreamFormat(); + final String ext = activity.getString(R.string.remux_title); + new AlertDialog.Builder(activity) + .setTitle(R.string.stream_via_as) + // + .setItems( + new String[]{ + activity.getString(R.string.stream_as, sf), + activity.getString(R.string.stream_via, ext)},// TODO + // add + // here + // what + // will + // be + // used + new DialogInterface.OnClickListener() { + @Override + public void onClick(final DialogInterface dialog, + final int which) { + String url = null; + switch (which) { + case 0: + url = getStreamUrl(idornr); + break; + case 1: + url = getRemuxStreamUrl(idornr); + break; + } + startStream(activity, url); + } + }).create().show(); + } + + public static void startStream(final Activity activity, final String url) { + try { + final Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setDataAndType(Uri.parse(url.toString()), "video/*"); + activity.startActivityForResult(intent, 1); + } catch (final ActivityNotFoundException anfe) { + Log.w(TAG, anfe); + Toast.makeText(activity, anfe.getLocalizedMessage(), + Toast.LENGTH_SHORT).show(); + } + } + + public static final String md5(final String s) { + try { + // Create MD5 Hash + final MessageDigest digest = java.security.MessageDigest + .getInstance("MD5"); + digest.update(s.getBytes()); + final byte messageDigest[] = digest.digest(); + + // Create Hex String + final StringBuffer hexString = new StringBuffer(); + for (int i = 0; i < messageDigest.length; i++) { + String h = Integer.toHexString(0xFF & messageDigest[i]); + while (h.length() < 2) { + h = "0" + h; + } + hexString.append(h); + } + return hexString.toString(); + + } catch (final NoSuchAlgorithmException e) { + Log.w(TAG, e); + } + return ""; + } + + public static int getDuration(final Event event) { + final long millis = event.getDuration(); + final int minuts = (int) (millis / 1000 / 60); + return minuts; + } + + public static void shareEvent(final Activity activity, final Event event) { + final Intent share = new Intent(android.content.Intent.ACTION_SEND); + share.setType("text/plain"); + StringBuilder sb = new StringBuilder(); + sb.append(event.getTitle()); + sb.append("\n"); + final EventFormatter ef = new EventFormatter(event, false); + sb.append(ef.getDate()).append(" ").append(ef.getTime()); + final String title = sb.toString(); + share.putExtra(android.content.Intent.EXTRA_SUBJECT, sb.toString()); + sb = new StringBuilder(); + sb.append(title).append("\n\n"); + sb.append(event.getChannelNumber() + " " + event.getChannelName()); + sb.append("\n\n"); + sb.append(ef.getShortText()); + sb.append("\n\n"); + sb.append(ef.getDescription()); + sb.append("\n"); + share.putExtra(android.content.Intent.EXTRA_TEXT, sb.toString()); + activity.startActivity(Intent.createChooser(share, + activity.getString(R.string.share_chooser))); + } + + public static void addCalendarEvent(final Activity activity, + final Event event) { + final Intent intent = new Intent(Intent.ACTION_EDIT); + intent.setType("vnd.android.cursor.item/event"); + intent.putExtra("title", event.getTitle()); + intent.putExtra("description", event.getShortText()); + intent.putExtra("beginTime", event.getStart().getTime()); + intent.putExtra("endTime", event.getStop().getTime()); + activity.startActivity(intent); + } + + public static String mapSpecialChars(final String src) { + if (src == null) { + return ""; + } + return src.replace("|##", C.DATA_SEPARATOR).replace("||#", "\n"); + } + + public static String unMapSpecialChars(final String src) { + if (src == null) { + return ""; + } + return src.replace(C.DATA_SEPARATOR, "|##").replace("\n", "||#"); + } + + public static PackageInfo getPackageInfo(final Context ctx) { + PackageInfo pi = null; + try { + pi = ctx.getPackageManager().getPackageInfo(ctx.getPackageName(), + PackageManager.GET_ACTIVITIES); + } catch (final PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + return pi; + } + + public static boolean checkInternetConnection(final Context ctx) { + final ConnectivityManager cm = (ConnectivityManager) ctx + .getSystemService(Context.CONNECTIVITY_SERVICE); + // test for connection + if (cm.getActiveNetworkInfo() != null + && cm.getActiveNetworkInfo().isConnectedOrConnecting()) { + return true; + } + return false; + } + + private static String getRecordingStream(final Activity ctx, + final Recording rec) { + + + Preferences prefs = Preferences.get(); + + final String m = prefs.getRecStreamMethod(); + + final StringBuilder url = new StringBuilder(); + + if (StringUtils.equals(m, "vdr-live")) { + url.append("http://") + .append(prefs.getHost()) + // + .append(":") + .append(Integer.valueOf(prefs.getLivePort())) + // + .append("/recstream.html?recid=recording_") + .append(Utils.md5(rec.getFileName())); + // http://192.168.1.119:8008/b0cdedeed2d36508dfd924f0876a851b + final String urlstring = url.toString(); + return urlstring; + } else if (StringUtils.equals(m, "vdr-streamdev")) { + url.append("http://").append(prefs.getHost()) + // + .append(":") + .append(Integer.valueOf( + prefs.getStreamPort())) + // + .append("/").append(rec.getDevInode()); + } else if (StringUtils.equals(m, "vdr-smarttvweb")) { + + String type = prefs.getSmarttvewebType(); + + url.append("http://") + .append(prefs.getHost()) + // + .append(":") + .append(Integer.valueOf(prefs + .getSmarttvewebPort())) + // + .append(Utils.encodeUrlPath(rec.getFileName())); + if (StringUtils.equals(type, "has") == true) { + url.append("/manifest-seg.mpd"); + } else if (StringUtils.equals(type, "hls")) { + url.append("/manifest-seg.m3u8"); + } + } + return url.toString(); + } + + public static void streamRecording(final Activity ctx, final Recording rec) { + final String urlstring = getRecordingStream(ctx, rec); + Log.d(TAG, "try stream: " + urlstring); + Utils.startStream(ctx, urlstring); + } + + public static void switchTo(final Activity activity, final Channel channel) { + switchTo(activity, channel.getId(), channel.getName()); + } + + /** + * @param ctx + * @param id + * @param name Optional für die Anzeige + */ + public static void switchTo(final Activity activity, final String id, + final String name) { + + final SwitchChannelClient scc = new SwitchChannelClient(id, + new CertificateProblemDialog(activity)); + final SvdrpAsyncTask task = new SvdrpAsyncTask( + scc); + task.addSvdrpListener(new SvdrpListener() { + @Override + public void svdrpEvent(final SvdrpEvent event) { + if (event == SvdrpEvent.FINISHED_SUCCESS) { + Utils.say(activity, activity.getString( + R.string.switching_success, (name != null ? name + : id))); + } else if (event == SvdrpEvent.CONNECT_ERROR + || event == SvdrpEvent.FINISHED_ABNORMALY + || event == SvdrpEvent.ABORTED + || event == SvdrpEvent.ERROR + || event == SvdrpEvent.CACHE_HIT) { + Utils.say(activity, activity.getString( + R.string.switching_failed, (name != null ? name + : id), event.name())); + } + } + + public void svdrpException(final SvdrpException e) { + Log.w(TAG, e.getMessage(), e); + Utils.say(activity, e.getMessage()); + } + }); + task.run(); + } + + public static void say(final Context ctx, final String msg) { + final Toast t = Toast.makeText(ctx, msg, Toast.LENGTH_SHORT); + t.setGravity(Gravity.CENTER, 0, 0); + t.show(); + } + + public static String encodeUrlPath(String path) { + return path.replaceAll("%", "%25"); + } + + public static void say(final Context ctx, final int msg) { + say(ctx, msg, Toast.LENGTH_SHORT); + } + + public static void say(final Context ctx, final int msg, final int duration) { + final Toast t = Toast.makeText(ctx, msg, duration); + t.setGravity(Gravity.CENTER, 0, 0); + t.show(); + } + + /** + * Formats the date and time based on user's phone date/time preferences. + * + * @param context the context + * @param time the time in milliseconds + */ + + public static String formatDateTime(final Context context, final long time) { + return android.text.format.DateFormat.getDateFormat(context).format( + time) + + " " + + DateUtils.formatDateTime(context, time, + DateUtils.FORMAT_SHOW_TIME).toString(); + } + + public static int getTimerStateDrawable(final TimerMatch match, + final int full, final int begin, final int end, final int conflict) { + + switch (match) { + case Begin: + return begin; + case End: + return end; + case Conflict: + return conflict; + default: + return full; + } + } + + public static String formatAudio(final Context context, + final List tracks) { + + final StringBuilder sb = new StringBuilder(); + + String sep = ""; + for (final AudioTrack a : tracks) { + sb.append(sep).append(a.display); + if (a.type.equals("d")) { + sb.append(" (") + .append(context.getString(R.string.audio_track_dolby)) + .append(")"); + } + sep = ", "; + } + return sb.toString(); + + } + + public static TimerMatch getTimerMatch(Event event, Timer timer) { + if (timer == null) { + return null; + } + TimerMatch timerMatch = null; + Date start = event.getStart(); + Date stop = event.getStop(); + if (start.before(timer.getStart())) { + timerMatch = TimerMatch.End; + } else if (stop.after(timer.getStop())) { + timerMatch = TimerMatch.Begin; + } else { + timerMatch = TimerMatch.Full; + } + return timerMatch; + } + + public static int contentToString(int c) { + ; + switch (c & 0xF0) { + case EventContentGroup.MovieDrama: + switch (c & 0x0F) { + default: + case 0x00: + return R.string.Content_Movie__Drama; + case 0x01: + return R.string.Content_Detective__Thriller; + case 0x02: + return R.string.Content_Adventure__Western__War; + case 0x03: + return R.string.Content_Science_Fiction__Fantasy__Horror; + case 0x04: + return R.string.Content_Comedy; + case 0x05: + return R.string.Content_Soap__Melodrama__Folkloric; + case 0x06: + return R.string.Content_Romance; + case 0x07: + return R.string.Content_Serious__Classical__Religious__Historical_Movie__Drama; + case 0x08: + return R.string.Content_Adult_Movie__Drama; + } + case EventContentGroup.NewsCurrentAffairs: + switch (c & 0x0F) { + default: + case 0x00: + return R.string.Content_News__Current_Affairs; + case 0x01: + return R.string.Content_News__Weather_Report; + case 0x02: + return R.string.Content_News_Magazine; + case 0x03: + return R.string.Content_Documentary; + case 0x04: + return R.string.Content_Discussion__Inverview__Debate; + } + + case EventContentGroup.Show: + switch (c & 0x0F) { + default: + case 0x00: + return R.string.Content_Show__Game_Show; + case 0x01: + return R.string.Content_Game_Show__Quiz__Contest; + case 0x02: + return R.string.Content_Variety_Show; + case 0x03: + return R.string.Content_Talk_Show; + } + + case EventContentGroup.Sports: + switch (c & 0x0F) { + default: + case 0x00: + return R.string.Content_Sports; + case 0x01: + return R.string.Content_Special_Event; + case 0x02: + return R.string.Content_Sport_Magazine; + case 0x03: + return R.string.Content_Football__Soccer; + case 0x04: + return R.string.Content_Tennis__Squash; + case 0x05: + return R.string.Content_Team_Sports; + case 0x06: + return R.string.Content_Athletics; + case 0x07: + return R.string.Content_Motor_Sport; + case 0x08: + return R.string.Content_Water_Sport; + case 0x09: + return R.string.Content_Winter_Sports; + case 0x0A: + return R.string.Content_Equestrian; + case 0x0B: + return R.string.Content_Martial_Sports; + } + + case EventContentGroup.ChildrenYouth: + switch (c & 0x0F) { + default: + case 0x00: + return R.string.Content_Childrens__Youth_Programme; + case 0x01: + return R.string.Content_Preschool_Childrens_Programme; + case 0x02: + return R.string.Content_Entertainment_Programme_for_6_to_14; + case 0x03: + return R.string.Content_Entertainment_Programme_for_10_to_16; + case 0x04: + return R.string.Content_Informational__Educational__School_Programme; + case 0x05: + return R.string.Content_Cartoons__Puppets; + } + + case EventContentGroup.MusicBalletDance: + switch (c & 0x0F) { + default: + case 0x00: + return R.string.Content_Music__Ballet__Dance; + case 0x01: + return R.string.Content_Rock__Pop; + case 0x02: + return R.string.Content_Serious__Classical_Music; + case 0x03: + return R.string.Content_Folk__Tradional_Music; + case 0x04: + return R.string.Content_Jazz; + case 0x05: + return R.string.Content_Musical__Opera; + case 0x06: + return R.string.Content_Ballet; + } + + case EventContentGroup.ArtsCulture: + switch (c & 0x0F) { + default: + case 0x00: + return R.string.Content_Arts__Culture; + case 0x01: + return R.string.Content_Performing_Arts; + case 0x02: + return R.string.Content_Fine_Arts; + case 0x03: + return R.string.Content_Religion; + case 0x04: + return R.string.Content_Popular_Culture__Traditional_Arts; + case 0x05: + return R.string.Content_Literature; + case 0x06: + return R.string.Content_Film__Cinema; + case 0x07: + return R.string.Content_Experimental_Film__Video; + case 0x08: + return R.string.Content_Broadcasting__Press; + case 0x09: + return R.string.Content_New_Media; + case 0x0A: + return R.string.Content_Arts__Culture_Magazine; + case 0x0B: + return R.string.Content_Fashion; + } + + case EventContentGroup.SocialPoliticalEconomics: + switch (c & 0x0F) { + default: + case 0x00: + return R.string.Content_Social__Political__Economics; + case 0x01: + return R.string.Content_Magazine__Report__Documentary; + case 0x02: + return R.string.Content_Economics__Social_Advisory; + case 0x03: + return R.string.Content_Remarkable_People; + } + + case EventContentGroup.EducationalScience: + switch (c & 0x0F) { + default: + case 0x00: + return R.string.Content_Education__Science__Factual; + case 0x01: + return R.string.Content_Nature__Animals__Environment; + case 0x02: + return R.string.Content_Technology__Natural_Sciences; + case 0x03: + return R.string.Content_Medicine__Physiology__Psychology; + case 0x04: + return R.string.Content_Foreign_Countries__Expeditions; + case 0x05: + return R.string.Content_Social__Spiritual_Sciences; + case 0x06: + return R.string.Content_Further_Education; + case 0x07: + return R.string.Content_Languages; + } + + case EventContentGroup.LeisureHobbies: + switch (c & 0x0F) { + default: + case 0x00: + return R.string.Content_Leisure__Hobbies; + case 0x01: + return R.string.Content_Tourism__Travel; + case 0x02: + return R.string.Content_Handicraft; + case 0x03: + return R.string.Content_Motoring; + case 0x04: + return R.string.Content_Fitness_and_Health; + case 0x05: + return R.string.Content_Cooking; + case 0x06: + return R.string.Content_Advertisement__Shopping; + case 0x07: + return R.string.Content_Gardening; + } + case EventContentGroup.Special: + switch (c & 0x0F) { + case 0x00: + return R.string.Content_Original_Language; + case 0x01: + return R.string.Content_Black_and_White; + case 0x02: + return R.string.Content_Unpublished; + case 0x03: + return R.string.Content_Live_Broadcast; + default: + ; + } + break; + default: + ; + } + return R.string.Content_Unknown; + } + + public static String getContenString(Context ctx, int[] contents) { + + if (contents.length == 0) { + return ""; + } + + StringBuilder sb = new StringBuilder(); + + String sep = ""; + + for (int content : contents) { + + sb.append(sep).append(ctx.getString(contentToString(content))); + sep = ", "; + } + + return sb.toString(); + } + + public static boolean isSerie(int[] contents) { + if (contents.length == 0) { + return false; + } + + for (int c : contents) { + if (c == 21) { + return true; + + } + } + + return false; + } } diff --git a/vdrmanager/de.bjusystems.vdrmanager/src/main/java/de/bjusystems/vdrmanager/gui/VdrManagerActivity.java b/vdrmanager/de.bjusystems.vdrmanager/src/main/java/de/bjusystems/vdrmanager/gui/VdrManagerActivity.java index 729d75c..8f3c68c 100644 --- a/vdrmanager/de.bjusystems.vdrmanager/src/main/java/de/bjusystems/vdrmanager/gui/VdrManagerActivity.java +++ b/vdrmanager/de.bjusystems.vdrmanager/src/main/java/de/bjusystems/vdrmanager/gui/VdrManagerActivity.java @@ -1,16 +1,22 @@ package de.bjusystems.vdrmanager.gui; +import android.Manifest; +import android.annotation.TargetApi; import android.app.AlertDialog; import android.app.SearchManager; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.content.pm.PackageManager; import android.database.Cursor; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.provider.SearchRecentSuggestions; +import android.support.v4.app.ActivityCompat; +import android.support.v4.content.ContextCompat; import android.support.v4.view.MenuItemCompat; -import android.support.v7.app.ActionBarActivity; +import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.SearchView; import android.support.v7.widget.SearchView.OnQueryTextListener; import android.util.Log; @@ -33,309 +39,350 @@ import de.bjusystems.vdrmanager.data.db.EPGSearchSuggestionsProvider; import de.bjusystems.vdrmanager.remote.RemoteActivity; import de.bjusystems.vdrmanager.utils.wakeup.AsyncWakeupTask; -public class VdrManagerActivity extends ActionBarActivity implements - OnClickListener, OnQueryTextListener { +public class VdrManagerActivity extends AppCompatActivity implements + OnClickListener, OnQueryTextListener { - public static final String TAG = "VdrManagerActivity"; + public static final String TAG = "VdrManagerActivity"; - public static final String VDR_PORTAL = "http://www.vdr-portal.de"; + public static final String VDR_PORTAL = "http://www.vdr-portal.de"; - private SearchView search; + private SearchView search; - private View actionMenuWakup; - private View actionMenuRemote; + private View actionMenuWakup; + private View actionMenuRemote; - @Override - protected void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + private static final int MY_PERMISSIONS_REQUEST_EXTERNAL_STORAGE = 13; - // Preferences.initVDR(this); - // if(Preferences.get().getCurrentVdr() == null){ - // finish(); - // return; - // } android.support.v7.appcompat.R + @TargetApi(Build.VERSION_CODES.M) + private void checkAndRequestPermission() { + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + Utils.say(getApplication(), R.string.permission_rationale, Toast.LENGTH_LONG); + } else { + ActivityCompat.requestPermissions(this, + new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, + MY_PERMISSIONS_REQUEST_EXTERNAL_STORAGE); + } + } + } + + + @Override + public void onRequestPermissionsResult(int requestCode, + String permissions[], int[] grantResults) { + switch (requestCode) { + case MY_PERMISSIONS_REQUEST_EXTERNAL_STORAGE: { + // If request is cancelled, the result arrays are empty. + if (grantResults.length > 0 + && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + // permission was granted, yay! Do the + } else { + // permission denied, boo! Disable the + // functionality that depends on this permission. + } + return; + } + + // other 'case' lines to check for other + // permissions this app might request + } + } + + @Override + protected void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); - if (Preferences.initVDR(this) == false) { - final Intent intent = new Intent(); - intent.setClass(this, VdrListActivity.class); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.putExtra(Intents.EMPTY_CONFIG, Boolean.TRUE); - startActivity(intent); - Toast.makeText(this, R.string.no_vdr, Toast.LENGTH_SHORT).show(); - finish(); - return; - } + // Preferences.initVDR(this); - Preferences.setLocale(this); + // if(Preferences.get().getCurrentVdr() == null){ + // finish(); + // return; + // } android.support.v7.appcompat.R - // this.getActionBar().setDisplayShowCustomEnabled(true); - // this.getActionBar().setDisplayShowTitleEnabled(false); - // setTitle(getString(R.string.app_name)); - // attach view - setContentView(R.layout.vdrmanager); - // Preferences.loadPreferences(this); + if (Preferences.initVDR(this) == false) { + final Intent intent = new Intent(); + intent.setClass(this, VdrListActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra(Intents.EMPTY_CONFIG, Boolean.TRUE); + startActivity(intent); + Toast.makeText(this, R.string.no_vdr, Toast.LENGTH_SHORT).show(); + finish(); + return; + } - findViewById(R.id.action_menu_channels).setOnClickListener(this); - findViewById(R.id.action_menu_recordings).setOnClickListener(this); - findViewById(R.id.action_menu_timers).setOnClickListener(this); - findViewById(R.id.action_menu_epg).setOnClickListener(this); - findViewById(R.id.action_menu_remote).setOnClickListener(this); + Preferences.setLocale(this); + + // this.getActionBar().setDisplayShowCustomEnabled(true); + // this.getActionBar().setDisplayShowTitleEnabled(false); + // setTitle(getString(R.string.app_name)); + // attach view + setContentView(R.layout.vdrmanager); + + // Preferences.loadPreferences(this); + + findViewById(R.id.action_menu_channels).setOnClickListener(this); + findViewById(R.id.action_menu_recordings).setOnClickListener(this); + findViewById(R.id.action_menu_timers).setOnClickListener(this); + findViewById(R.id.action_menu_epg).setOnClickListener(this); + findViewById(R.id.action_menu_remote).setOnClickListener(this); // View v = findViewById(R.id.action_menu_search); // if (v != null) { // v.setOnClickListener(this); // } - //findViewById(R.id.main_logo).setOnClickListener(this); - actionMenuWakup = findViewById(R.id.action_menu_wakeup); - actionMenuRemote = findViewById(R.id.action_menu_remote); - // add and register buttons - // createButtons(); - } - - public boolean onCreateOptionsMenu(Menu menu) { - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.main_menu, menu); - - // search = new SearchView(getSupportActionBar().getThemedContext()); - search = (SearchView) MenuItemCompat.getActionView( menu.findItem(R.id.menu_search)); - - // search = (SearchView) - // .getActionView(); - // - // Object o = menu.findItem(R.id.menu_search); - - SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE); - search.setSearchableInfo(searchManager - .getSearchableInfo(getComponentName())); - - //search.setOnQueryTextListener(this); - return true; - } - - @Override - protected void onResume() { - Preferences.setLocale(this); - if (Preferences.get().isWakeupEnabled() == false) { - actionMenuWakup.setVisibility(View.GONE); - actionMenuWakup.setOnClickListener(null); - } else { - actionMenuWakup.setVisibility(View.VISIBLE); - actionMenuWakup.setOnClickListener(this); - } - - if(Preferences.get().isRemoteEnabled() == false){ - actionMenuRemote.setVisibility(View.GONE); - actionMenuRemote.setOnClickListener(null); - } else { - actionMenuRemote.setVisibility(View.VISIBLE); - actionMenuRemote.setOnClickListener(this); - } - - - super.onResume(); - } - - @Override - public boolean onOptionsItemSelected( - final MenuItem item) { - - switch (item.getItemId()) { - case R.id.main_menu_preferences: { - Intent intent = new Intent(this, PreferencesActivity.class); - int flags = Intent.FLAG_ACTIVITY_NEW_TASK - | Intent.FLAG_ACTIVITY_SINGLE_TOP - | Intent.FLAG_ACTIVITY_CLEAR_TOP; - intent.setFlags(flags); - startActivity(intent); - finish(); - break; - } - case R.id.main_menu_info: { - if(isFinishing()){ - break; - } - About.show(this); - break; - } - case R.id.main_menu_exit: { - finish(); - break; - } - - case R.id.main_menu_clear_search: { - SearchRecentSuggestions suggestions = new SearchRecentSuggestions( - this, EPGSearchSuggestionsProvider.AUTHORITY, - EPGSearchSuggestionsProvider.MODE); - suggestions.clearHistory(); - break; - } - - // case R.id.menu_search: { - // if(Build.VERSION.SDK_INT <11){ - // onSearchRequested(); - // } - // break; - // } - case R.id.main_menu_goto: { - try { - final Cursor cursor = ((AndroidDatabaseResults) DBAccess - .get(this).getVdrDAO().iterator().getRawResults()) - .getRawCursor(); - startManagingCursor(cursor); - final AlertDialog ad = new AlertDialog.Builder(this) - .setSingleChoiceItems(cursor, findVdrCursor(cursor), - "name", new DialogInterface.OnClickListener() { - - public void onClick(DialogInterface dialog, - int which) { - cursor.moveToPosition(which); - int id = cursor.getInt(cursor - .getColumnIndex("_id")); - Vdr vdr = DBAccess - .get(VdrManagerActivity.this) - .getVdrDAO().queryForId(id); - if (vdr == null) { - Toast.makeText( - VdrManagerActivity.this, - R.string.main_menu_goto_no_vdr, - Toast.LENGTH_SHORT).show(); - } else { - Preferences.setCurrentVdr( - VdrManagerActivity.this, - vdr); - Toast.makeText( - VdrManagerActivity.this, - getString( - R.string.main_menu_switched_to, - vdr.getName()), - Toast.LENGTH_SHORT).show(); - Intent intent = getIntent(); - overridePendingTransition(0, 0); - intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); - finish(); - - overridePendingTransition(0, 0); - startActivity(intent); - } - dialog.dismiss(); - } - })// - .setTitle(R.string.main_menu_goto_title)// - .create(); - ad.show(); - - } catch (Exception ex) { - Log.w(TAG, ex); - } - - break; - } - } - return true; - } - - private int findVdrCursor(Cursor c) { - if (Preferences.get().getCurrentVdr() == null) { - return -1; - } - - int cid = Preferences.get().getCurrentVdr().getId(); - - int position = 0; - c.moveToPosition(-1); - while (c.moveToNext()) { - if (c.getInt(c.getColumnIndex("_id")) == cid) { - break; - } - position++; - } - return position; - } - - @Override - public void onBackPressed() { - if (Preferences.get().isQuiteOnBackButton()) { - finish(); - } else { - super.onBackPressed(); - } - - try { - // reassign a new and empty key store - ((VdrManagerApp)getApplication()).initSessionKeyStore(); - } catch (final Exception e) { - Log.e(getClass().getName(), "Can't clear session key store"); + //findViewById(R.id.main_logo).setOnClickListener(this); + actionMenuWakup = findViewById(R.id.action_menu_wakeup); + actionMenuRemote = findViewById(R.id.action_menu_remote); + // add and register buttons + // createButtons(); + checkAndRequestPermission(); + + } + + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.main_menu, menu); + + // search = new SearchView(getSupportActionBar().getThemedContext()); + search = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.menu_search)); + + // search = (SearchView) + // .getActionView(); + // + // Object o = menu.findItem(R.id.menu_search); + + SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE); + search.setSearchableInfo(searchManager + .getSearchableInfo(getComponentName())); + + //search.setOnQueryTextListener(this); + return true; + } + + @Override + protected void onResume() { + Preferences.setLocale(this); + if (Preferences.get().isWakeupEnabled() == false) { + actionMenuWakup.setVisibility(View.GONE); + actionMenuWakup.setOnClickListener(null); + } else { + actionMenuWakup.setVisibility(View.VISIBLE); + actionMenuWakup.setOnClickListener(this); + } + + if (Preferences.get().isRemoteEnabled() == false) { + actionMenuRemote.setVisibility(View.GONE); + actionMenuRemote.setOnClickListener(null); + } else { + actionMenuRemote.setVisibility(View.VISIBLE); + actionMenuRemote.setOnClickListener(this); + } + + + super.onResume(); + } + + @Override + public boolean onOptionsItemSelected( + final MenuItem item) { + + switch (item.getItemId()) { + case R.id.main_menu_preferences: { + Intent intent = new Intent(this, PreferencesActivity.class); + int flags = Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_SINGLE_TOP + | Intent.FLAG_ACTIVITY_CLEAR_TOP; + intent.setFlags(flags); + startActivity(intent); + finish(); + break; + } + case R.id.main_menu_info: { + if (isFinishing()) { + break; + } + About.show(this); + break; + } + case R.id.main_menu_exit: { + finish(); + break; + } + + case R.id.main_menu_clear_search: { + SearchRecentSuggestions suggestions = new SearchRecentSuggestions( + this, EPGSearchSuggestionsProvider.AUTHORITY, + EPGSearchSuggestionsProvider.MODE); + suggestions.clearHistory(); + break; + } + + // case R.id.menu_search: { + // if(Build.VERSION.SDK_INT <11){ + // onSearchRequested(); + // } + // break; + // } + case R.id.main_menu_goto: { + try { + final Cursor cursor = ((AndroidDatabaseResults) DBAccess + .get(this).getVdrDAO().iterator().getRawResults()) + .getRawCursor(); + startManagingCursor(cursor); + final AlertDialog ad = new AlertDialog.Builder(this) + .setSingleChoiceItems(cursor, findVdrCursor(cursor), + "name", new DialogInterface.OnClickListener() { + + public void onClick(DialogInterface dialog, + int which) { + cursor.moveToPosition(which); + int id = cursor.getInt(cursor + .getColumnIndex("_id")); + Vdr vdr = DBAccess + .get(VdrManagerActivity.this) + .getVdrDAO().queryForId(id); + if (vdr == null) { + Toast.makeText( + VdrManagerActivity.this, + R.string.main_menu_goto_no_vdr, + Toast.LENGTH_SHORT).show(); + } else { + Preferences.setCurrentVdr( + VdrManagerActivity.this, + vdr); + Toast.makeText( + VdrManagerActivity.this, + getString( + R.string.main_menu_switched_to, + vdr.getName()), + Toast.LENGTH_SHORT).show(); + Intent intent = getIntent(); + overridePendingTransition(0, 0); + intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); + finish(); + + overridePendingTransition(0, 0); + startActivity(intent); + } + dialog.dismiss(); + } + })// + .setTitle(R.string.main_menu_goto_title)// + .create(); + ad.show(); + + } catch (Exception ex) { + Log.w(TAG, ex); + } + + break; + } + } + return true; + } + + private int findVdrCursor(Cursor c) { + if (Preferences.get().getCurrentVdr() == null) { + return -1; + } + + int cid = Preferences.get().getCurrentVdr().getId(); + + int position = 0; + c.moveToPosition(-1); + while (c.moveToNext()) { + if (c.getInt(c.getColumnIndex("_id")) == cid) { + break; + } + position++; + } + return position; } - } - - public void startActivity(Class clazz) { - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setClass(this, clazz); - startActivity(intent); - } - - public void onClick(View v) { - int id = v.getId(); - - switch (id) { - case R.id.action_menu_channels: - startActivity(ChannelListActivity.class); - break; - case R.id.action_menu_recordings: - startActivity(RecordingListActivity.class); - break; - case R.id.action_menu_timers: - startActivity(TimerListActivity.class); - break; - case R.id.action_menu_epg: - startActivity(TimeEpgListActivity.class); - break; + @Override + public void onBackPressed() { + if (Preferences.get().isQuiteOnBackButton()) { + finish(); + } else { + super.onBackPressed(); + } + + try { + // reassign a new and empty key store + ((VdrManagerApp) getApplication()).initSessionKeyStore(); + } catch (final Exception e) { + Log.e(getClass().getName(), "Can't clear session key store"); + } + + } + + public void startActivity(Class clazz) { + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setClass(this, clazz); + startActivity(intent); + } + + public void onClick(View v) { + int id = v.getId(); + + switch (id) { + case R.id.action_menu_channels: + startActivity(ChannelListActivity.class); + break; + case R.id.action_menu_recordings: + startActivity(RecordingListActivity.class); + break; + case R.id.action_menu_timers: + startActivity(TimerListActivity.class); + break; + case R.id.action_menu_epg: + startActivity(TimeEpgListActivity.class); + break; // case R.id.action_menu_search: // onSearchRequested(); // break; - case R.id.action_menu_wakeup: - final AsyncWakeupTask wakeupTask = new AsyncWakeupTask(this); - wakeupTask.execute(); - break; - case R.id.main_logo: - Intent i = new Intent(Intent.ACTION_VIEW); - i.setData(Uri.parse(VDR_PORTAL)); - startActivity(i); - break; - - case R.id.action_menu_remote: - startActivity(RemoteActivity.class); - break; - - } - - } - - protected void startSearchManager() { - Bundle appData = new Bundle(); - startSearch(null, false, appData, false); - } - - @Override - public boolean onSearchRequested() { - search.setVisibility(View.VISIBLE); - // Bundle appData = new Bundle(); - // appData.putBoolean(SearchableActivity.JARGON, true); - // startSearch(null, false, appData, false); - return true; - } - - @Override - public boolean onQueryTextSubmit(String query) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean onQueryTextChange(String newText) { - // TODO Auto-generated method stub - return false; - } + case R.id.action_menu_wakeup: + final AsyncWakeupTask wakeupTask = new AsyncWakeupTask(this); + wakeupTask.execute(); + break; + case R.id.main_logo: + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse(VDR_PORTAL)); + startActivity(i); + break; + + case R.id.action_menu_remote: + startActivity(RemoteActivity.class); + break; + + } + + } + + protected void startSearchManager() { + Bundle appData = new Bundle(); + startSearch(null, false, appData, false); + } + + @Override + public boolean onSearchRequested() { + search.setVisibility(View.VISIBLE); + // Bundle appData = new Bundle(); + // appData.putBoolean(SearchableActivity.JARGON, true); + // startSearch(null, false, appData, false); + return true; + } + + @Override + public boolean onQueryTextSubmit(String query) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean onQueryTextChange(String newText) { + // TODO Auto-generated method stub + return false; + } } diff --git a/vdrmanager/de.bjusystems.vdrmanager/src/main/java/de/bjusystems/vdrmanager/remote/RemoteActivity.java b/vdrmanager/de.bjusystems.vdrmanager/src/main/java/de/bjusystems/vdrmanager/remote/RemoteActivity.java index efd3cec..254150e 100644 --- a/vdrmanager/de.bjusystems.vdrmanager/src/main/java/de/bjusystems/vdrmanager/remote/RemoteActivity.java +++ b/vdrmanager/de.bjusystems.vdrmanager/src/main/java/de/bjusystems/vdrmanager/remote/RemoteActivity.java @@ -7,9 +7,12 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; +import android.net.Uri; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; +import android.os.Environment; +import android.util.Log; import android.util.Pair; import android.view.ContextMenu; import android.view.KeyEvent; @@ -35,11 +38,21 @@ import org.hampelratte.svdrp.commands.HITK; import org.json.JSONException; import org.json.JSONObject; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; import de.androvdr.widget.AnimatedTextView; import de.androvdr.widget.FontAwesome; import de.bjusystems.vdrmanager.R; +import de.bjusystems.vdrmanager.backup.IOUtils; import de.bjusystems.vdrmanager.data.Preferences; import de.bjusystems.vdrmanager.gui.ColoredButton; import de.bjusystems.vdrmanager.gui.Utils; @@ -52,6 +65,10 @@ public class RemoteActivity extends Activity implements OnClickListener, View.On private static final int TAG_KEY = -100; + private static final String TAG = RemoteActivity.class.getSimpleName(); + + private static final int READ_REQUEST_CODE = 19; + private Connection connection; private AnimatedTextView result; @@ -60,12 +77,15 @@ public class RemoteActivity extends Activity implements OnClickListener, View.On private View dummyContextMenuView; + private ViewGroup remoteroot; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.requestWindowFeature(Window.FEATURE_NO_TITLE); + //Remove notification bar this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); View view = getLayoutInflater().inflate(R.layout.remote, null); @@ -77,12 +97,12 @@ public class RemoteActivity extends Activity implements OnClickListener, View.On view.setOnLongClickListener(this); - ViewGroup viewGroup = (ViewGroup) view.findViewById(R.id.remoteroot); + remoteroot = (ViewGroup) view.findViewById(R.id.remoteroot); //Button button = (Button) viewGroup.findViewById(R.id.red); //button.getBackground().setColorFilter(0xFF00FF00, PorterDuff.Mode.MULTIPLY); - setAllButtonListener(viewGroup); + setAllButtonListener(remoteroot); result = (AnimatedTextView) findViewById(R.id.result); //Animation in = AnimationUtils.loadAnimation(this,android.R.anim.fade_in); @@ -95,9 +115,14 @@ public class RemoteActivity extends Activity implements OnClickListener, View.On in = new AlphaAnimation(0.0f, 1.0f); in.setDuration(100); - - //SearchableSpinner spinner2 = (SearchableSpinner) findViewById(R.id.search2); - //spinner2.setList(getResources().getStringArray(R.array.font)); + Bundle bundle = getIntent().getExtras(); + if (bundle != null) { + Uri uri = (Uri) bundle.get(Intent.EXTRA_STREAM); + if (uri != null) { + importFromUri(uri); + return; + } + } } @@ -162,46 +187,83 @@ public class RemoteActivity extends Activity implements OnClickListener, View.On public void export() { SharedPreferences sharedPref = getSharedPreferences("remote_" + Preferences.get().getCurrentVdr().getId(), Context.MODE_PRIVATE); ViewGroup viewGroup = (ViewGroup) findViewById(R.id.remoteroot); - ArrayList> list = new ArrayList<>(); - gather(viewGroup, list, sharedPref); + HashMap> map = new HashMap<>(); + collect(viewGroup, map, sharedPref); + + if(map.isEmpty()){ + Utils.say(this, R.string.remote_nothing_to_import); + return; + } JSONObject root = new JSONObject(); try { - for (Pair stringStringPair : list) { - root.put(stringStringPair.first, stringStringPair.second); + for (Map.Entry> e : map.entrySet()) { + JSONObject pair = new JSONObject(); + Pair stringStringPair = e.getValue(); + pair.put("key", stringStringPair.first); + pair.put("label", stringStringPair.second); + root.put(e.getKey(), pair); } } catch (JSONException jse) { Utils.say(this, jse.getLocalizedMessage()); } - Intent i = new Intent(android.content.Intent.ACTION_SEND); - i.setType("application/json"); - i.putExtra(android.content.Intent.EXTRA_TEXT, root.toString()); - startActivity(Intent.createChooser(i, getResources().getString(R.string.export_custom_key_mapping))); + Intent intentShareFile = new Intent(Intent.ACTION_SEND); + String content = root.toString(); + File outputFile = null; + try { + outputFile = File.createTempFile("vdr_remote_keys_", ".json", Environment.getExternalStorageDirectory()); + final FileOutputStream fileOutputStream = new FileOutputStream(outputFile); + fileOutputStream.write(content.getBytes("utf-8")); + IOUtils.closeQuietly(fileOutputStream); + } catch (IOException iox) { + Log.d(TAG, iox.getMessage(), iox); + Utils.say(this, iox.getLocalizedMessage()); + return; + } + intentShareFile.setType("text/plain"); + intentShareFile.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + outputFile.getAbsolutePath())); + + intentShareFile.putExtra(Intent.EXTRA_SUBJECT, + getString(R.string.export_custom_key_mapping)); + + intentShareFile.putExtra(Intent.EXTRA_TEXT, content); + + startActivity(Intent.createChooser(intentShareFile, getString(R.string.export_custom_key_mapping))); } + //Intent i = new Intent(android.content.Intent.ACTION_SEND); + // i.setType("application/json"); +// i.putExtra(android.content.Intent.EXTRA_TEXT,root.toString()); + + // startActivity(Intent.createChooser(i, getResources(). + + //getString())); +//} + /** * Gather. * * @param viewGroup the view group - * @param pair the pair + * @param map the map * @param sharedPref the shared pref */ - public void gather(ViewGroup viewGroup, ArrayList> pair, SharedPreferences sharedPref) { + public void collect(ViewGroup viewGroup, HashMap> map, SharedPreferences sharedPref) { for (int i = 0; i < viewGroup.getChildCount(); i++) { View v = viewGroup.getChildAt(i); if (v instanceof ViewGroup) { - gather((ViewGroup) v, pair, sharedPref); + collect((ViewGroup) v, map, sharedPref); } else if (v instanceof Button) { if (v.getTag() == null) { continue; } - String hitk = sharedPref.getString("key_" + String.valueOf(v.getTag()), null); - String label = sharedPref.getString("label_" + String.valueOf(v.getTag()), null); + String tagKey = String.valueOf(v.getTag()); + String hitk = sharedPref.getString("key_" + tagKey, null); + String label = sharedPref.getString("label_" + tagKey, null); if (hitk == null && label == null) { continue; } - pair.add(Pair.create(hitk, label)); + map.put(tagKey, Pair.create(hitk, label)); } } } @@ -272,7 +334,9 @@ public class RemoteActivity extends Activity implements OnClickListener, View.On private void restart() { - + if(getIntent() != null) { + getIntent().removeExtra(Intent.EXTRA_STREAM); + } if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { recreate(); } else { @@ -299,7 +363,18 @@ public class RemoteActivity extends Activity implements OnClickListener, View.On return true; } case R.id.imprt: { - Utils.say(this, R.string.not_yet_implemented); + Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); + + // Filter to only show results that can be "opened", such as a + // file (as opposed to a list of contacts or timezones) + intent.addCategory(Intent.CATEGORY_OPENABLE); + + // Filter to show only images, using the image MIME data type. + // If one wanted to search for ogg vorbis files, the type would be "audio/ogg". + // To search for all documents available via installed storage providers, + // it would be "*/*". + intent.setType("*/*"); + startActivityForResult(intent, READ_REQUEST_CODE); return true; } case R.id.remapback: { @@ -322,6 +397,13 @@ public class RemoteActivity extends Activity implements OnClickListener, View.On ; + /** + * On create context menu. + * + * @param menu the menu + * @param v the v + * @param menuInfo the menu info + */ @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { @@ -417,6 +499,70 @@ public class RemoteActivity extends Activity implements OnClickListener, View.On return false; } + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + // The ACTION_OPEN_DOCUMENT intent was sent with the request code + // READ_REQUEST_CODE. If the request code seen here doesn't match, it's the + // response to some other intent, and the code below shouldn't run at all. + + if (requestCode == READ_REQUEST_CODE && resultCode == Activity.RESULT_OK) { + // The document selected by the user won't be returned in the intent. + // Instead, a URI to that document will be contained in the return intent + // provided to this method as a parameter. + // Pull that URI using resultData.getData(). + Uri uri = null; + if (data != null) { + uri = data.getData(); + importFromUri(uri); + } + } + } + + private void importFromUri(Uri uri) { + try { + Log.i(TAG, "Uri: " + uri.toString()); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + IOUtils.copy(getContentResolver().openInputStream(uri), bos); + JSONObject object = new JSONObject(new String(bos.toByteArray(), "utf-8" + )); + IOUtils.closeQuietly(bos); + final Iterator keys = object.keys(); + Set all = new HashSet(); + for (de.bjusystems.vdrmanager.remote.HITK hitk : de.bjusystems.vdrmanager.remote.HITK.values()) { + all.add(hitk.getValue()); + } + SharedPreferences sharedPref = getSharedPreferences("remote_" + Preferences.get().getCurrentVdr().getId(), Context.MODE_PRIVATE); + SharedPreferences.Editor edit = sharedPref.edit(); + int counter = 0; + while (keys.hasNext()) { + final String next = keys.next(); + if (all.contains(next) == false) { + continue; + } + JSONObject pair = object.getJSONObject(next); + String key = pair.getString("key"); + if (all.contains(key) == false) { + continue; + } + String value = pair.getString("label"); + edit.putString("key_" + next, key); + edit.putString("label_" + next, value); + counter++; + } + edit.commit(); + Utils.say(this, getString(R.string.remote_keys_imported, String.valueOf(counter))); + if (counter > 0) { + setAllButtonListener(remoteroot); + } + } catch (Exception iox) + + { + Log.w(TAG, iox.getMessage(), iox); + Utils.say(this, iox.getMessage()); + } + } + + private void putVdrKey(String key, CharSequence value) { SharedPreferences sharedPref = getSharedPreferences("remote_" + Preferences.get().getCurrentVdr().getId(), Context.MODE_PRIVATE); SharedPreferences.Editor edit = sharedPref.edit(); diff --git a/vdrmanager/de.bjusystems.vdrmanager/src/main/res/layout/dialog_dropdown.xml b/vdrmanager/de.bjusystems.vdrmanager/src/main/res/layout/dialog_dropdown.xml new file mode 100644 index 0000000..4f90097 --- /dev/null +++ b/vdrmanager/de.bjusystems.vdrmanager/src/main/res/layout/dialog_dropdown.xml @@ -0,0 +1,26 @@ + + + + + + + + diff --git a/vdrmanager/de.bjusystems.vdrmanager/src/main/res/layout/recycler_buffer_item.xml b/vdrmanager/de.bjusystems.vdrmanager/src/main/res/layout/recycler_buffer_item.xml new file mode 100644 index 0000000..25ce8b8 --- /dev/null +++ b/vdrmanager/de.bjusystems.vdrmanager/src/main/res/layout/recycler_buffer_item.xml @@ -0,0 +1,7 @@ + + + diff --git a/vdrmanager/de.bjusystems.vdrmanager/src/main/res/layout/recycler_itemviews.xml b/vdrmanager/de.bjusystems.vdrmanager/src/main/res/layout/recycler_itemviews.xml new file mode 100644 index 0000000..6aeb1b0 --- /dev/null +++ b/vdrmanager/de.bjusystems.vdrmanager/src/main/res/layout/recycler_itemviews.xml @@ -0,0 +1,7 @@ + + + diff --git a/vdrmanager/de.bjusystems.vdrmanager/src/main/res/layout/remote.xml b/vdrmanager/de.bjusystems.vdrmanager/src/main/res/layout/remote.xml index b251ca1..c75d83e 100644 --- a/vdrmanager/de.bjusystems.vdrmanager/src/main/res/layout/remote.xml +++ b/vdrmanager/de.bjusystems.vdrmanager/src/main/res/layout/remote.xml @@ -7,6 +7,8 @@ android:orientation="vertical" android:padding="5dp"> + + + + 40dp + 0dp + 2dp + 200dp + diff --git a/vdrmanager/de.bjusystems.vdrmanager/src/main/res/values/font.xml b/vdrmanager/de.bjusystems.vdrmanager/src/main/res/values/font.xml new file mode 100644 index 0000000..554cc96 --- /dev/null +++ b/vdrmanager/de.bjusystems.vdrmanager/src/main/res/values/font.xml @@ -0,0 +1,13 @@ + + + + +  500px +  address-book +  address-book-o +  address-card +  address-card-o +  adjust +  adn + + diff --git a/vdrmanager/de.bjusystems.vdrmanager/src/main/res/values/strings.xml b/vdrmanager/de.bjusystems.vdrmanager/src/main/res/values/strings.xml index ec417e0..4f62261 100644 --- a/vdrmanager/de.bjusystems.vdrmanager/src/main/res/values/strings.xml +++ b/vdrmanager/de.bjusystems.vdrmanager/src/main/res/values/strings.xml @@ -1,43 +1,43 @@ - Channels - Timers - Recordings - EPG list - EPG search - Wakeup - Remote - VDR-Manager - Show EPG - Live stream - Hide - Hide permanent - Hide - Hide permanent - Group by - Group - Provider - Name - Source - By Channel - By Date - All Channels - Group by %1$s - Delete - Current: - \nCurrent: %1$s - <not set> - No connection - Connection aborted. - Retry - Refresh - Done - Share - Add to calendar - Reruns - Share EPG Entry - About "VDR-Manager" Software for Android\n + Channels + Timers + Recordings + EPG list + EPG search + Wakeup + Remote + VDR-Manager + Show EPG + Live stream + Hide + Hide permanent + Hide + Hide permanent + Group by + Group + Provider + Name + Source + By Channel + By Date + All Channels + Group by %1$s + Delete + Current: + \nCurrent: %1$s + <not set> + No connection + Connection aborted. + Retry + Refresh + Done + Share + Add to calendar + Reruns + Share EPG Entry + About "VDR-Manager" Software for Android\n This is Version %1$s\n If you have a VDR at home reachable over the internet and own a mobile phone running Android then you possibly find this program useful. @@ -46,389 +46,389 @@ bju<herrlado@gmail.com> herrlado<herrlado@gmail.com> - About - No data connection - Update will start in one second - Search EPG - Search times - Create timer - Record - Delete timer - Modify timer - Enable timer - Disable timer - Nothing found… - An error occurred, check logs… - End - Beginning - Add time - Custom times - - - What\'s on at - Now - Next - Ad Hoc - Channel - Search results - - - Share - IMDb Search - OMDB Search - TMDb Search - Stream - Add timer - Modify timer - - - Search - %1$s min - %1$s/%2$s min - %1$s, %2$s/%3$s - EPG by channel - EPG Search - EPG Search: \'%1$s\' - EPG by time - EPG by time: \'%1$s\' - Search EPG - Search VDR EPG - %1$s, %2$s items - %1$s, %2$s/%3$s - New timer - The communication with VDR has caused an error: %1$s - Live TV - Needs streamdev-server on VDR and an external + About + No data connection + Update will start in one second + Search EPG + Search times + Create timer + Record + Delete timer + Modify timer + Enable timer + Disable timer + Nothing found… + An error occurred, check logs… + End + Beginning + Add time + Custom times + + + What\'s on at + Now + Next + Ad Hoc + Channel + Search results + + + Share + IMDb Search + OMDB Search + TMDb Search + Stream + Add timer + Modify timer + + + Search + %1$s min + %1$s/%2$s min + %1$s, %2$s/%3$s + EPG by channel + EPG Search + EPG Search: \'%1$s\' + EPG by time + EPG by time: \'%1$s\' + Search EPG + Search VDR EPG + %1$s, %2$s items + %1$s, %2$s/%3$s + New timer + The communication with VDR has caused an error: %1$s + Live TV + Needs streamdev-server on VDR and an external player such as VPlayer - Streamformat - Streaming Port - Default 3000. The access must be enabled in + Streamformat + Streaming Port + Default 3000. The access must be enabled in streamdevhosts.conf. - - TS - PES - ES - PS - - - remux_enable - remux_command - remux_parameter - Stream - Choose Audio Track - via %s - as %s - Remux - Enable Remux - Enable streaming via remux (e.g. externremux.sh) - Command - Typically EXT or Extern e.g. http://vdr:3000/EXT/1 - Parameter - Control Streaming quality. E.g. http://vdr:3000/EXT;DSL1000/1 - Preferences - Info - Exit - Switch Device - Switch to… - Can not load selected device :( - Switched to %1$s - Define one or more VDR Devices. - VDR Devices - - - Network settings - VDR host - Host running VDR - VDR plugin port - Port for connections to VDR plugin - VDR plugin password - Password for the VDR plugin - Secure connect - Use SSL for connections - - - Channel settings - Limit channels - Use only given channels - Channel filter - Comma separated channelnumbers or ranges (separator \'-\'). A.e. 1,2,4-10 + + TS + PES + ES + PS + + + remux_enable + remux_command + remux_parameter + Stream + Choose Audio Track + via %s + as %s + Remux + Enable Remux + Enable streaming via remux (e.g. externremux.sh) + Command + Typically EXT or Extern e.g. http://vdr:3000/EXT/1 + Parameter + Control Streaming quality. E.g. http://vdr:3000/EXT;DSL1000/1 + Preferences + Info + Exit + Switch Device + Switch to… + Can not load selected device :( + Switched to %1$s + Define one or more VDR Devices. + VDR Devices + + + Network settings + VDR host + Host running VDR + VDR plugin port + Port for connections to VDR plugin + VDR plugin password + Password for the VDR plugin + Secure connect + Use SSL for connections + + + Channel settings + Limit channels + Use only given channels + Channel filter + Comma separated channelnumbers or ranges (separator \'-\'). A.e. 1,2,4-10 - - Remote VDR host wakeup - Can remote wakeup VDR - Enables to remote wakeup the VDR host - URL for remote wakeup - URL for a request doing the wakeup - Wakeup user - User for remote wakeup - Wakeup password - Password for remote wakeup - Wakeup method - Choose a method to wakeup the vdr host - - - Call a URL - WOL - - - Destination IP address - Unless you have static ARP tables you should use some kind of + + Remote VDR host wakeup + Can remote wakeup VDR + Enables to remote wakeup the VDR host + URL for remote wakeup + URL for a request doing the wakeup + Wakeup user + User for remote wakeup + Wakeup password + Password for remote wakeup + Wakeup method + Choose a method to wakeup the vdr host + + + Call a URL + WOL + + + Destination IP address + Unless you have static ARP tables you should use some kind of broadcast address. - MAC-Address - MAC-Address of the VDR host. Use \':\' or \'-\' or a space as separator. + MAC-Address + MAC-Address of the VDR host. Use \':\' or \'-\' or a space as separator. - - Timer defaults - Margin at start - Minutes recording starts before the beginning of + + Timer defaults + Margin at start + Minutes recording starts before the beginning of the broadcast - Margin at stop - Minutes recording stops after the end of the + Margin at stop + Minutes recording stops after the end of the broadcast - Default priority - Default priority - Default primary limit - Default primary limit - Default lifetime - Default lifetime - Timer already defined. - Timer created - - - - GUI Settings - Use 24-hour format - 13:00 - 1:00 PM - Show channel numbers - Show channel numbers in the channel list. - Quit on back button - Back button quits the VDR-Manager - Back button does not quit VDR-Manager - Show IMDb Button - IMDb Button is shown - IMDb Button is not shown - IMDb Site - Which IMDb site to search. - Show OMDB Button - OMDB Button is shown - OMDB Button is not shown - Show TMDb Button - TMDb Button is shown - TMDb Button is not shown - Custom language - Set a custom language. - - - International - imdb.com - uk.imdb.com - imdb.de - imdb.es - imdb.fr - imdb.it - imdb.pt - - - - - English - German - French - Italian - Polish - Ukrainian - - - EXT - EXTERN (deprecated) - - - Advanced - Advanced settings - Connection Timeout - How long (in seconds) to wait before the connection is established? - Read Timeout - How long (in seconds) to wait for every read line operation? - Total timeout - How long (in seconds) to wait for a whole I/O operation, before it gets aborted? + Default priority + Default priority + Default primary limit + Default primary limit + Default lifetime + Default lifetime + Timer already defined. + Timer created + + + + GUI Settings + Use 24-hour format + 13:00 + 1:00 PM + Show channel numbers + Show channel numbers in the channel list. + Quit on back button + Back button quits the VDR-Manager + Back button does not quit VDR-Manager + Show IMDb Button + IMDb Button is shown + IMDb Button is not shown + IMDb Site + Which IMDb site to search. + Show OMDB Button + OMDB Button is shown + OMDB Button is not shown + Show TMDb Button + TMDb Button is shown + TMDb Button is not shown + Custom language + Set a custom language. + + + International + imdb.com + uk.imdb.com + imdb.de + imdb.es + imdb.fr + imdb.it + imdb.pt + + + + + English + German + French + Italian + Polish + Ukrainian + + + EXT + EXTERN (deprecated) + + + Advanced + Advanced settings + Connection Timeout + How long (in seconds) to wait before the connection is established? + Read Timeout + How long (in seconds) to wait for every read line operation? + Total timeout + How long (in seconds) to wait for a whole I/O operation, before it gets aborted? - Streamdev password - Set your streamdev server password. (a.e. -a \'username:password\') - Streamdev username - Set your streamdev server username. (a.e. -a \'username:password\') - Character encoding - Character encoding of your VDR device. Default is utf-8. - New VDR - No VDR Devices - VDR devices - Device - Name - A name for this device - Delete this device? - Streaming of recordings - Streaming of recordings - Enable Streaming of recordings - - - live plugin - streamdev plugin - smarttvweb plugin - - - - - Progressive - MPEG-DASH - Apple HLS - - - Streaming method - Currently Streaming over VDR live and or streamdev plugin is supported - VDR live plugin port - VDR live plugin has default port 8008. - - - Connecting… - Connection failed! - Connection timeout! - Login. - Login failed. - Loading EPG… - Loading timers… - Loading recordings… - Switching… - Loading channels… - Loading… - Disconnecting… - Initiating wakeup request… - Wakeup request sent - Error sending wakeup request: %1$s - Saving timer… - Deleting timer… - Deleting recording… - Enabling timer… - Updating timer… - Disabling timer… - Connection finished abnormal - Connection finished abnormal: %1$s - Loaded from cache. - Delete - Stream - Recent channels - No history… - Max. recent channels - How many channels should be kept in the recent channels? - Day - - - Every day - - - Never - - - ", " - Repeat - Use VPS: - Priority: - Lifetime: - e.g. 99 - e.g. 50 - %1$s (VPS) - Switch to - Switched to %s - Switching to %1$s failed: %2$s - Switch to - Sort - Sort by - Time - Channel - Alphabet - Chanellist - Clear Search History - VDR host not defined - Processing… - - - Mostly used - Last used - - - Time - Alphabet - - - Time - Alphabet - Channel - - - Channels - Alphabet - - - By Time - By Alphabet - - - Sort by last used or mostly used - Recent Channels Sorting - - - Group - Provider - Source - Name - - - Channels - EPG by Time - EPG by Channel - Recordings - Timers - Remote - - - Filter - Audio Tracks: %1$s - D - The time zone used on the server. It is important if you travel and modify timers + Streamdev password + Set your streamdev server password. (a.e. -a \'username:password\') + Streamdev username + Set your streamdev server username. (a.e. -a \'username:password\') + Character encoding + Character encoding of your VDR device. Default is utf-8. + New VDR + No VDR Devices + VDR devices + Device + Name + A name for this device + Delete this device? + Streaming of recordings + Streaming of recordings + Enable Streaming of recordings + + + live plugin + streamdev plugin + smarttvweb plugin + + + + + Progressive + MPEG-DASH + Apple HLS + + + Streaming method + Currently Streaming over VDR live and or streamdev plugin is supported + VDR live plugin port + VDR live plugin has default port 8008. + + + Connecting… + Connection failed! + Connection timeout! + Login. + Login failed. + Loading EPG… + Loading timers… + Loading recordings… + Switching… + Loading channels… + Loading… + Disconnecting… + Initiating wakeup request… + Wakeup request sent + Error sending wakeup request: %1$s + Saving timer… + Deleting timer… + Deleting recording… + Enabling timer… + Updating timer… + Disabling timer… + Connection finished abnormal + Connection finished abnormal: %1$s + Loaded from cache. + Delete + Stream + Recent channels + No history… + Max. recent channels + How many channels should be kept in the recent channels? + Day + + + Every day + + + Never + + + ", " + Repeat + Use VPS: + Priority: + Lifetime: + e.g. 99 + e.g. 50 + %1$s (VPS) + Switch to + Switched to %s + Switching to %1$s failed: %2$s + Switch to + Sort + Sort by + Time + Channel + Alphabet + Chanellist + Clear Search History + VDR host not defined + Processing… + + + Mostly used + Last used + + + Time + Alphabet + + + Time + Alphabet + Channel + + + Channels + Alphabet + + + By Time + By Alphabet + + + Sort by last used or mostly used + Recent Channels Sorting + + + Group + Provider + Source + Name + + + Channels + EPG by Time + EPG by Channel + Recordings + Timers + Remote + + + Filter + Audio Tracks: %1$s + D + The time zone used on the server. It is important if you travel and modify timers from another time zone. - Select server time zone - Sort alphabetically - Sort by time zone - Probing %1$s … - No results… - Recording started - Set time - + Select server time zone + Sort alphabetically + Sort by time zone + Probing %1$s … + No results… + Recording started + Set time + - + - Certificate warning - The server certificate was not accepted:\n\n + Certificate warning + The server certificate was not accepted:\n\n Hostname:\n %1$s\n Valid from:\n @@ -437,124 +437,127 @@ %3$s\n\n What do you want to do? - Accept once - Accept forever - Abort - - - Movie/Drama - Detective/Thriller - Adventure/Western/War - Science Fiction/Fantasy/Horror - Comedy - Soap/Melodrama/Folkloric - Romance - Serious/Classical/Religious/Historical + Accept once + Accept forever + Abort + + + Movie/Drama + Detective/Thriller + Adventure/Western/War + Science Fiction/Fantasy/Horror + Comedy + Soap/Melodrama/Folkloric + Romance + Serious/Classical/Religious/Historical Movie/Drama - Adult Movie/Drama - News/Current Affairs - News/Weather Report - News Magazine - Documentary - Discussion/Inverview/Debate - Show/Game Show - Game Show/Quiz/Contest - Variety Show - Talk Show - Sports - Special Event - Sport Magazine - Football/Soccer - Tennis/Squash - Team Sports - Athletics - Motor Sport - Water Sport - Winter Sports - Equestrian - Martial Sports - Children\'s/Youth Programme - Pre-school Children\'s Programme - Entertainment Programme for 6 to 14 - Entertainment Programme for 10 to 16 - Informational/Educational/School Programme - Cartoons/Puppets - Music/Ballet/Dance - Rock/Pop - Serious/Classical Music - Folk/Tradional Music - Jazz - Musical/Opera - Ballet - Arts/Culture - Performing Arts - Fine Arts - Religion - Popular Culture/Traditional Arts - Literature - Film/Cinema - Experimental Film/Video - Broadcasting/Press - New Media - Arts/Culture Magazine - Fashion - Social/Political/Economics - Magazine/Report/Documentary - Economics/Social Advisory - Remarkable People - Education/Science/Factual - Nature/Animals/Environment - Technology/Natural Sciences - Medicine/Physiology/Psychology - Foreign Countries/Expeditions - Social/Spiritual Sciences - Further Education - Languages - Leisure/Hobbies - Tourism/Travel - Handicraft - Motoring - Fitness & Health - Cooking - Advertisement/Shopping - Gardening - Original Language - Black & White - Unpublished - Live Broadcast - - - type to filter - Free %1$s GB of %2$s GB (%3$s%%) - Drive - Sad - Search - Clear Term after Search - Search term remains after peforming search - Term gets cleared after performing search - Open navigation drawer - Close navigation drawer - Web search - VDR smarttvweb plugin has default port 8000 - Smarttvweb port - Smarttvweb Stream Type - Supported methods: \'Progressive\', \'MPEG-DASH \/ OIPF HAS\', + Adult Movie/Drama + News/Current Affairs + News/Weather Report + News Magazine + Documentary + Discussion/Inverview/Debate + Show/Game Show + Game Show/Quiz/Contest + Variety Show + Talk Show + Sports + Special Event + Sport Magazine + Football/Soccer + Tennis/Squash + Team Sports + Athletics + Motor Sport + Water Sport + Winter Sports + Equestrian + Martial Sports + Children\'s/Youth Programme + Pre-school Children\'s Programme + Entertainment Programme for 6 to 14 + Entertainment Programme for 10 to 16 + Informational/Educational/School Programme + Cartoons/Puppets + Music/Ballet/Dance + Rock/Pop + Serious/Classical Music + Folk/Tradional Music + Jazz + Musical/Opera + Ballet + Arts/Culture + Performing Arts + Fine Arts + Religion + Popular Culture/Traditional Arts + Literature + Film/Cinema + Experimental Film/Video + Broadcasting/Press + New Media + Arts/Culture Magazine + Fashion + Social/Political/Economics + Magazine/Report/Documentary + Economics/Social Advisory + Remarkable People + Education/Science/Factual + Nature/Animals/Environment + Technology/Natural Sciences + Medicine/Physiology/Psychology + Foreign Countries/Expeditions + Social/Spiritual Sciences + Further Education + Languages + Leisure/Hobbies + Tourism/Travel + Handicraft + Motoring + Fitness & Health + Cooking + Advertisement/Shopping + Gardening + Original Language + Black & White + Unpublished + Live Broadcast + + + type to filter + Free %1$s GB of %2$s GB (%3$s%%) + Drive + Sad + Search + Clear Term after Search + Search term remains after peforming search + Term gets cleared after performing search + Open navigation drawer + Close navigation drawer + Web search + VDR smarttvweb plugin has default port 8000 + Smarttvweb port + Smarttvweb Stream Type + Supported methods: \'Progressive\', \'MPEG-DASH \/ OIPF HAS\', \'Apple HLS\' - Remote Control - Shows the remote control view if enabled - Enable VDR remote control - SVDRP Port - Default is 6419 - Label - HITK Command - Reset - Export - Export Custom Key Mapping - Import - \'Back\' is \'Back\' HITK - Longpress on Back Button to leave the remote. - Not Yet Implemented - Can not create timer: %1$s + Remote Control + Shows the remote control view if enabled + Enable VDR remote control + SVDRP Port + Default is 6419 + Label + HITK Command + Reset + Export + Export Custom Key Mapping + Import + \'Back\' is \'Back\' HITK + Longpress on Back Button to leave the remote. + Not Yet Implemented + Can not create timer: %1$s + The app needs Storage permissions to import/export. + Remote Keys imported: %1$s + No custom mapping… -- cgit v1.2.3