├── app ├── .gitignore ├── src │ ├── main │ │ ├── res │ │ │ ├── drawable │ │ │ │ ├── bg0.png │ │ │ │ ├── bg1.png │ │ │ │ ├── bg2.png │ │ │ │ ├── bg3.png │ │ │ │ ├── fav.png │ │ │ │ ├── fill.png │ │ │ │ ├── ico_port.png │ │ │ │ ├── profile.png │ │ │ │ ├── console_bg.jpg │ │ │ │ ├── ico_sound.png │ │ │ │ ├── ico_switch.png │ │ │ │ ├── ico_voice.png │ │ │ │ ├── switch_bg.png │ │ │ │ ├── bg0_resized.jpg │ │ │ │ ├── bg1_resized.jpg │ │ │ │ ├── bg2_resized.jpg │ │ │ │ ├── bg3_resized.jpg │ │ │ │ ├── ico_display.png │ │ │ │ └── fab_label_background.xml │ │ │ ├── drawable-hdpi │ │ │ │ ├── fav.png │ │ │ │ ├── dropdown.png │ │ │ │ ├── ic_add_black_24dp.png │ │ │ │ ├── ic_add_white_24dp.png │ │ │ │ ├── ic_delete_black_24dp.png │ │ │ │ ├── ic_search_black_24dp.png │ │ │ │ ├── ic_favorite_black_24dp.png │ │ │ │ ├── ic_forward_black_24dp.png │ │ │ │ ├── ic_reorder_black_24dp.png │ │ │ │ ├── ic_settings_black_24dp.png │ │ │ │ ├── ic_arrow_back_black_24dp.png │ │ │ │ ├── ic_arrow_drop_up_black_24dp.png │ │ │ │ ├── ic_github_circle_black_24dp.png │ │ │ │ ├── ic_import_export_black_24dp.png │ │ │ │ └── ic_arrow_drop_down_black_24dp.png │ │ │ ├── drawable-mdpi │ │ │ │ ├── fav.png │ │ │ │ ├── dropdown.png │ │ │ │ ├── ic_add_black_24dp.png │ │ │ │ ├── ic_add_white_24dp.png │ │ │ │ ├── ic_send_black_24dp.png │ │ │ │ ├── ic_delete_black_24dp.png │ │ │ │ ├── ic_search_black_24dp.png │ │ │ │ ├── ic_favorite_black_24dp.png │ │ │ │ ├── ic_forward_black_24dp.png │ │ │ │ ├── ic_reorder_black_24dp.png │ │ │ │ ├── ic_settings_black_24dp.png │ │ │ │ ├── ic_arrow_back_black_24dp.png │ │ │ │ ├── ic_arrow_drop_up_black_24dp.png │ │ │ │ ├── ic_github_circle_black_24dp.png │ │ │ │ ├── ic_import_export_black_24dp.png │ │ │ │ └── ic_arrow_drop_down_black_24dp.png │ │ │ ├── drawable-xhdpi │ │ │ │ ├── fav.png │ │ │ │ ├── dropdown.png │ │ │ │ ├── ic_add_black_24dp.png │ │ │ │ ├── ic_add_white_24dp.png │ │ │ │ ├── ic_send_black_24dp.png │ │ │ │ ├── ic_delete_black_24dp.png │ │ │ │ ├── ic_favorite_black_24dp.png │ │ │ │ ├── ic_forward_black_24dp.png │ │ │ │ ├── ic_reorder_black_24dp.png │ │ │ │ ├── ic_search_black_24dp.png │ │ │ │ ├── ic_settings_black_24dp.png │ │ │ │ ├── ic_arrow_back_black_24dp.png │ │ │ │ ├── ic_arrow_drop_up_black_24dp.png │ │ │ │ ├── ic_github_circle_black_24dp.png │ │ │ │ ├── ic_import_export_black_24dp.png │ │ │ │ └── ic_arrow_drop_down_black_24dp.png │ │ │ ├── drawable-xxhdpi │ │ │ │ ├── fav.png │ │ │ │ ├── dropdown.png │ │ │ │ ├── ic_add_black_24dp.png │ │ │ │ ├── ic_add_white_24dp.png │ │ │ │ ├── ic_send_black_24dp.png │ │ │ │ ├── ic_delete_black_24dp.png │ │ │ │ ├── ic_forward_black_24dp.png │ │ │ │ ├── ic_reorder_black_24dp.png │ │ │ │ ├── ic_search_black_24dp.png │ │ │ │ ├── ic_favorite_black_24dp.png │ │ │ │ ├── ic_settings_black_24dp.png │ │ │ │ ├── ic_arrow_back_black_24dp.png │ │ │ │ ├── ic_arrow_drop_up_black_24dp.png │ │ │ │ ├── ic_github_circle_black_24dp.png │ │ │ │ ├── ic_import_export_black_24dp.png │ │ │ │ └── ic_arrow_drop_down_black_24dp.png │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── drawable-xxxhdpi │ │ │ │ ├── ic_add_black_24dp.png │ │ │ │ ├── ic_add_white_24dp.png │ │ │ │ ├── ic_search_black_24dp.png │ │ │ │ ├── ic_send_black_24dp.png │ │ │ │ ├── ic_favorite_black_24dp.png │ │ │ │ ├── ic_forward_black_24dp.png │ │ │ │ ├── ic_reorder_black_24dp.png │ │ │ │ ├── ic_settings_black_24dp.png │ │ │ │ ├── ic_arrow_back_black_24dp.png │ │ │ │ ├── ic_arrow_drop_up_black_24dp.png │ │ │ │ ├── ic_github_circle_black_24dp.png │ │ │ │ ├── ic_import_export_black_24dp.png │ │ │ │ └── ic_arrow_drop_down_black_24dp.png │ │ │ ├── values │ │ │ │ ├── dimens.xml │ │ │ │ ├── colors.xml │ │ │ │ ├── styles.xml │ │ │ │ ├── style-test.xml │ │ │ │ ├── strings.xml │ │ │ │ └── strings_settings.xml │ │ │ ├── anim │ │ │ │ ├── fade_in.xml │ │ │ │ └── fade_out.xml │ │ │ ├── values-w820dp │ │ │ │ └── dimens.xml │ │ │ ├── layout │ │ │ │ ├── activity_main.xml │ │ │ │ ├── app_toolbar.xml │ │ │ │ ├── profile_password.xml │ │ │ │ ├── fragment_web_view.xml │ │ │ │ ├── activity_login.xml │ │ │ │ ├── drawer_back_view.xml │ │ │ │ ├── backround_list_item.xml │ │ │ │ ├── fragment_profile_keys.xml │ │ │ │ ├── drawer_content.xml │ │ │ │ ├── fragment_profile_manager.xml │ │ │ │ ├── drawer.xml │ │ │ │ ├── fragment_profile_general.xml │ │ │ │ ├── profile_key_list_item.xml │ │ │ │ ├── dapp_form.xml │ │ │ │ ├── dapp_drawer_continue_search_item.xml │ │ │ │ ├── profile_drawer_list_add.xml │ │ │ │ ├── profile_create_dialog.xml │ │ │ │ ├── profile_edit_dialog.xml │ │ │ │ ├── dapp_drawer_add_item.xml │ │ │ │ ├── drawer_header.xml │ │ │ │ ├── wallet_import.xml │ │ │ │ ├── profile_drawer_list_item.xml │ │ │ │ ├── drawer_front_view.xml │ │ │ │ ├── dapp_drawer_list_item.xml │ │ │ │ ├── drawer_bottom_part.xml │ │ │ │ └── fragment_console.xml │ │ │ ├── values-v14 │ │ │ │ └── styles.xml │ │ │ ├── menu │ │ │ │ ├── webview_menu.xml │ │ │ │ └── profile_menu.xml │ │ │ ├── values-v21 │ │ │ │ └── styles.xml │ │ │ └── xml │ │ │ │ ├── pref_general.xml │ │ │ │ └── config.xml │ │ ├── java │ │ │ ├── io │ │ │ │ └── syng │ │ │ │ │ ├── entity │ │ │ │ │ ├── RunningMode.java │ │ │ │ │ ├── LogEntry.java │ │ │ │ │ ├── JsonRpcServer.java │ │ │ │ │ ├── Dapp.java │ │ │ │ │ ├── ObjectSerializer.java │ │ │ │ │ └── Settings.java │ │ │ │ │ ├── service │ │ │ │ │ └── EthereumService.java │ │ │ │ │ ├── cordova │ │ │ │ │ └── plugin │ │ │ │ │ │ └── DappURL.java │ │ │ │ │ ├── adapter │ │ │ │ │ ├── ProfileKeyAdapter.java │ │ │ │ │ ├── helper │ │ │ │ │ │ ├── ItemTouchHelperAdapter.java │ │ │ │ │ │ └── SimpleItemTouchHelperCallback.java │ │ │ │ │ ├── BackgroundArrayAdapter.java │ │ │ │ │ └── ProfileViewPagerAdapter.java │ │ │ │ │ ├── fragment │ │ │ │ │ ├── profile │ │ │ │ │ │ ├── ProfileKeysFragment.java │ │ │ │ │ │ ├── ProfileGeneralFragment.java │ │ │ │ │ │ └── ProfileDialogFragment.java │ │ │ │ │ └── ConsoleFragment.java │ │ │ │ │ ├── activity │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ └── LoginActivity.java │ │ │ │ │ └── util │ │ │ │ │ ├── PrefsUtil.java │ │ │ │ │ ├── Encryption.java │ │ │ │ │ └── ProfileManager.java │ │ │ └── org │ │ │ │ └── apache │ │ │ │ └── cordova │ │ │ │ ├── contacts │ │ │ │ ├── ContactInfoDTO.java │ │ │ │ └── ContactAccessor.java │ │ │ │ ├── device │ │ │ │ └── Device.java │ │ │ │ ├── vibration │ │ │ │ └── Vibration.java │ │ │ │ ├── batterystatus │ │ │ │ └── BatteryListener.java │ │ │ │ ├── statusbar │ │ │ │ └── StatusBar.java │ │ │ │ ├── whitelist │ │ │ │ └── WhitelistPlugin.java │ │ │ │ └── camera │ │ │ │ └── ExifHelper.java │ │ └── AndroidManifest.xml │ └── androidTest │ │ └── java │ │ └── io │ │ └── syng │ │ └── ApplicationTest.java ├── proguard-rules.pro └── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitmodules ├── .gitignore ├── settings.gradle ├── gradle.properties ├── gradlew.bat └── gradlew /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable/bg0.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable/bg1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable/bg2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable/bg3.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/fav.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable/fav.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/res/drawable/fill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable/fill.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/fav.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-hdpi/fav.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/fav.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-mdpi/fav.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ico_port.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable/ico_port.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable/profile.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/fav.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xhdpi/fav.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/fav.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xxhdpi/fav.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/console_bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable/console_bg.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/ico_sound.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable/ico_sound.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ico_switch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable/ico_switch.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ico_voice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable/ico_voice.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/switch_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable/switch_bg.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/dropdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-hdpi/dropdown.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/dropdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-mdpi/dropdown.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg0_resized.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable/bg0_resized.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg1_resized.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable/bg1_resized.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg2_resized.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable/bg2_resized.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg3_resized.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable/bg3_resized.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/ico_display.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable/ico_display.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/dropdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xhdpi/dropdown.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/dropdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xxhdpi/dropdown.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_add_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-hdpi/ic_add_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_add_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-hdpi/ic_add_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_add_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-mdpi/ic_add_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_add_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-mdpi/ic_add_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_send_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-mdpi/ic_send_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_add_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xhdpi/ic_add_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_add_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xhdpi/ic_add_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_delete_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-hdpi/ic_delete_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_search_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-hdpi/ic_search_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_delete_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-mdpi/ic_delete_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_search_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-mdpi/ic_search_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_send_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xhdpi/ic_send_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_add_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xxhdpi/ic_add_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_add_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xxhdpi/ic_add_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_send_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xxhdpi/ic_send_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_add_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xxxhdpi/ic_add_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_add_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xxxhdpi/ic_add_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_favorite_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-hdpi/ic_favorite_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_forward_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-hdpi/ic_forward_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_reorder_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-hdpi/ic_reorder_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_settings_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-hdpi/ic_settings_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_favorite_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-mdpi/ic_favorite_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_forward_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-mdpi/ic_forward_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_reorder_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-mdpi/ic_reorder_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_settings_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-mdpi/ic_settings_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_delete_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xhdpi/ic_delete_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_favorite_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xhdpi/ic_favorite_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_forward_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xhdpi/ic_forward_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_reorder_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xhdpi/ic_reorder_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_search_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xhdpi/ic_search_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_settings_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xhdpi/ic_settings_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_delete_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xxhdpi/ic_delete_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_forward_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xxhdpi/ic_forward_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_reorder_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xxhdpi/ic_reorder_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_search_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xxhdpi/ic_search_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_search_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xxxhdpi/ic_search_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_send_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xxxhdpi/ic_send_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_arrow_back_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-hdpi/ic_arrow_back_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_arrow_back_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-mdpi/ic_arrow_back_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_arrow_back_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xhdpi/ic_arrow_back_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_favorite_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xxhdpi/ic_favorite_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_settings_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xxhdpi/ic_settings_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_favorite_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xxxhdpi/ic_favorite_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_forward_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xxxhdpi/ic_forward_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_reorder_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xxxhdpi/ic_reorder_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_settings_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xxxhdpi/ic_settings_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_arrow_drop_up_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-hdpi/ic_arrow_drop_up_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_github_circle_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-hdpi/ic_github_circle_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_import_export_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-hdpi/ic_import_export_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_arrow_drop_up_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-mdpi/ic_arrow_drop_up_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_github_circle_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-mdpi/ic_github_circle_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_import_export_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-mdpi/ic_import_export_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_arrow_drop_up_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xhdpi/ic_arrow_drop_up_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_github_circle_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xhdpi/ic_github_circle_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_import_export_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xhdpi/ic_import_export_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_arrow_back_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xxhdpi/ic_arrow_back_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_arrow_back_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xxxhdpi/ic_arrow_back_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_arrow_drop_down_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-hdpi/ic_arrow_drop_down_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_arrow_drop_down_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-mdpi/ic_arrow_drop_down_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_arrow_drop_down_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xhdpi/ic_arrow_drop_down_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_arrow_drop_up_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xxhdpi/ic_arrow_drop_up_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_github_circle_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xxhdpi/ic_github_circle_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_import_export_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xxhdpi/ic_import_export_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_arrow_drop_up_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xxxhdpi/ic_arrow_drop_up_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_github_circle_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xxxhdpi/ic_github_circle_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_import_export_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xxxhdpi/ic_import_export_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_arrow_drop_down_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xxhdpi/ic_arrow_drop_down_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_arrow_drop_down_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/status-im/syng-client/HEAD/app/src/main/res/drawable-xxxhdpi/ic_arrow_drop_down_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/anim/fade_in.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/anim/fade_out.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Apr 10 15:27:10 PDT 2013 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip 7 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "cordova-android"] 2 | path = cordova-android 3 | url = https://github.com/apache/cordova-android.git 4 | branch = master 5 | [submodule "ethereumj"] 6 | path = ethereumj 7 | url = https://github.com/syng-io/ethereumj-android.git 8 | branch = android-test-poc9-rlpx 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.gradle/ 2 | /local.properties 3 | /.idea 4 | .DS_Store 5 | /build 6 | 7 | #built application files 8 | *.apk 9 | *.ap_ 10 | 11 | # files for the dex VM 12 | *.dex 13 | 14 | # Java class files 15 | *.class 16 | 17 | # generated files 18 | bin/ 19 | gen/ 20 | 21 | # Eclipse project files 22 | .classpath 23 | .project 24 | 25 | # Android Studio 26 | *.iml 27 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':ethereumj-core' 2 | project(':ethereumj-core').projectDir = new File('ethereumj/ethereumj-core') 3 | include ':ethereumj-core-android' 4 | project(':ethereumj-core-android').projectDir = new File('ethereumj/ethereumj-core-android') 5 | include ':cordova-android' 6 | project(':cordova-android').projectDir = new File('cordova-android/framework') 7 | include ':app' -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/fab_label_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 11 | -------------------------------------------------------------------------------- /app/src/androidTest/java/io/syng/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package io.syng; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/layout/app_toolbar.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/values-v14/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/menu/webview_menu.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/java/io/syng/entity/RunningMode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Jarrad Hope 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | package io.syng.entity; 10 | 11 | 12 | public final class RunningMode { 13 | 14 | public final static int FULL_CLIENT = 1; 15 | public final static int LIGHT_CLIENT = 2; 16 | public final static int JSON_RPC_CLIENT = 3; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ffffff 4 | #fa0000 5 | #fafafa 6 | 7 | #e7333333 8 | #303030 9 | #536DFE 10 | 11 | #cfcfcf 12 | #737373 13 | 14 | 15 | #161b2f 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/layout/profile_password.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_web_view.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_login.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/layout/drawer_back_view.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/java/io/syng/service/EthereumService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Jarrad Hope 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | package io.syng.service; 10 | 11 | import android.content.Intent; 12 | 13 | import org.ethereum.android.service.EthereumRemoteService; 14 | 15 | public class EthereumService extends EthereumRemoteService { 16 | 17 | @Override 18 | public int onStartCommand(Intent intent, int flags, int startId) { 19 | return START_STICKY; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/res/values-v21/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 11 | 14 | 15 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/opt/android-sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/main/java/io/syng/cordova/plugin/DappURL.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Jarrad Hope 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | package io.syng.cordova.plugin; 10 | 11 | import org.apache.cordova.CordovaPlugin; 12 | 13 | public class DappURL extends CordovaPlugin { 14 | 15 | @Override 16 | public boolean onOverrideUrlLoading(String url) { 17 | if (url.indexOf("dapp://") == 0) { 18 | webView.loadUrl(url.replace("dapp://", "http://")); 19 | return true; 20 | } 21 | return false; 22 | } 23 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/backround_list_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/java/io/syng/entity/LogEntry.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Jarrad Hope 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | package io.syng.entity; 10 | 11 | public class LogEntry { 12 | 13 | private long timeStamp; 14 | private String message; 15 | 16 | public LogEntry(long timeStamp, String message) { 17 | this.timeStamp = timeStamp; 18 | this.message = message; 19 | } 20 | 21 | public long getTimeStamp() { 22 | return timeStamp; 23 | } 24 | 25 | public String getMessage() { 26 | return message; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_profile_keys.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 14 | 15 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/layout/drawer_content.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_profile_manager.xml: -------------------------------------------------------------------------------- 1 | 10 | 11 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/layout/drawer.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | 15 | 16 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_profile_general.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 13 | 14 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/java/io/syng/entity/JsonRpcServer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Jarrad Hope 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | package io.syng.entity; 10 | 11 | import java.io.Serializable; 12 | 13 | public class JsonRpcServer implements Serializable { 14 | 15 | protected String host; 16 | protected int port; 17 | 18 | private static final long serialVersionUID = 1L; 19 | 20 | public JsonRpcServer() { 21 | } 22 | 23 | public String getHost() { 24 | return host; 25 | } 26 | 27 | public void setHost(String host) { 28 | this.host = host; 29 | } 30 | 31 | public int getPort() { 32 | return port; 33 | } 34 | 35 | public void setPort(int port) { 36 | this.port = port; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/res/menu/profile_menu.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 10 | 11 | 17 | 18 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/layout/profile_key_list_item.xml: -------------------------------------------------------------------------------- 1 | 10 | 11 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/layout/dapp_form.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 14 | 15 | 21 | 22 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/layout/dapp_drawer_continue_search_item.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 17 | 18 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/layout/profile_drawer_list_add.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 17 | 18 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/layout/profile_create_dialog.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 14 | 15 | 22 | 23 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/res/layout/profile_edit_dialog.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 13 | 14 | 20 | 21 | 28 | 29 | 30 | 31 | 32 | 36 | 37 | -------------------------------------------------------------------------------- /app/src/main/res/xml/pref_general.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | 19 | 20 | 25 | 26 | 31 | 32 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /app/src/main/res/layout/dapp_drawer_add_item.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 14 | 15 | 23 | 24 | 31 | 32 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /app/src/main/res/layout/drawer_header.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | 16 | 19 | 20 | 33 | 34 | 38 | 39 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /app/src/main/res/values/style-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 17 | 18 | 29 | 30 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/java/org/apache/cordova/contacts/ContactInfoDTO.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | package org.apache.cordova.contacts; 21 | 22 | import java.util.HashMap; 23 | 24 | import org.json.JSONArray; 25 | import org.json.JSONObject; 26 | 27 | public class ContactInfoDTO { 28 | 29 | String displayName; 30 | JSONObject name; 31 | JSONArray organizations; 32 | JSONArray addresses; 33 | JSONArray phones; 34 | JSONArray emails; 35 | JSONArray ims; 36 | JSONArray websites; 37 | JSONArray photos; 38 | String note; 39 | String nickname; 40 | String birthday; 41 | HashMap desiredFieldsWithVals; 42 | 43 | public ContactInfoDTO() { 44 | 45 | displayName = ""; 46 | name = new JSONObject(); 47 | organizations = new JSONArray(); 48 | addresses = new JSONArray(); 49 | phones = new JSONArray(); 50 | emails = new JSONArray(); 51 | ims = new JSONArray(); 52 | websites = new JSONArray(); 53 | photos = new JSONArray(); 54 | note = ""; 55 | nickname = ""; 56 | desiredFieldsWithVals = new HashMap(); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/io/syng/adapter/ProfileKeyAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Jarrad Hope 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | package io.syng.adapter; 10 | 11 | 12 | import android.support.v7.widget.RecyclerView; 13 | import android.view.LayoutInflater; 14 | import android.view.View; 15 | import android.view.ViewGroup; 16 | import android.widget.TextView; 17 | 18 | import java.util.List; 19 | 20 | import io.syng.R; 21 | 22 | public class ProfileKeyAdapter extends RecyclerView.Adapter { 23 | 24 | private List mDataSet; 25 | 26 | public ProfileKeyAdapter(List data) { 27 | this.mDataSet = data; 28 | } 29 | 30 | @Override 31 | public SimpleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 32 | View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.profile_key_list_item, parent, false); 33 | return new SimpleViewHolder(v); 34 | } 35 | 36 | @Override 37 | public void onBindViewHolder(SimpleViewHolder holder, int position) { 38 | holder.keyTextView.setText(mDataSet.get(position)); 39 | holder.profileKeyItem.setOnClickListener(new View.OnClickListener() { 40 | @Override 41 | public void onClick(View v) { 42 | } 43 | }); 44 | } 45 | 46 | @Override 47 | public int getItemCount() { 48 | return mDataSet.size(); 49 | } 50 | 51 | static class SimpleViewHolder extends RecyclerView.ViewHolder { 52 | 53 | private TextView keyTextView; 54 | private View profileKeyItem; 55 | 56 | public SimpleViewHolder(View v) { 57 | super(v); 58 | keyTextView = (TextView) v.findViewById(R.id.text); 59 | profileKeyItem = v.findViewById(R.id.ll_profile_key_item); 60 | } 61 | } 62 | 63 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/wallet_import.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 19 | 20 | 26 | 27 | 28 | 29 | 36 | 37 | 44 | 45 | 52 | -------------------------------------------------------------------------------- /app/src/main/java/io/syng/adapter/helper/ItemTouchHelperAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Paul Burke 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Copyright (c) 2015 Jarrad Hope 19 | * 20 | * This Source Code Form is subject to the terms of the Mozilla Public 21 | * License, v. 2.0. If a copy of the MPL was not distributed with this 22 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 23 | */ 24 | 25 | package io.syng.adapter.helper; 26 | 27 | import android.support.v7.widget.RecyclerView; 28 | import android.support.v7.widget.helper.ItemTouchHelper; 29 | 30 | /** 31 | * Interface to listen for a move or dismissal event from a {@link ItemTouchHelper.Callback}. 32 | */ 33 | public interface ItemTouchHelperAdapter { 34 | 35 | /** 36 | * Called when an item has been dragged far enough to trigger a move. This is called every time 37 | * an item is shifted, and not at the end of a "drop" event.
38 | *
39 | * Implementations should call {@link RecyclerView.Adapter#notifyItemMoved(int, int)} after 40 | * adjusting the underlying data to reflect this move. 41 | * 42 | * @param fromPosition The start position of the moved item. 43 | * @param toPosition Then resolved position of the moved item. 44 | * @return True if the item was moved to the new adapter position. 45 | * @see RecyclerView#getAdapterPositionFor(RecyclerView.ViewHolder) 46 | * @see RecyclerView.ViewHolder#getAdapterPosition() 47 | */ 48 | boolean onItemMove(int fromPosition, int toPosition); 49 | 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/io/syng/entity/Dapp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Jarrad Hope 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | package io.syng.entity; 10 | 11 | import org.ethereum.crypto.HashUtil; 12 | import org.spongycastle.util.encoders.Hex; 13 | 14 | import java.io.Serializable; 15 | 16 | public class Dapp implements Serializable { 17 | 18 | protected String name = ""; 19 | protected String version = ""; 20 | protected String url = ""; 21 | protected String id = ""; 22 | 23 | private static final long serialVersionUID = 1L; 24 | 25 | public Dapp(String id, String name) { 26 | 27 | this.id = id; 28 | this.name = name; 29 | } 30 | 31 | public Dapp(String name) { 32 | 33 | this.name = name; 34 | this.id = generateID(); 35 | } 36 | 37 | public Dapp() { 38 | 39 | this.id = generateID(); 40 | } 41 | 42 | protected String generateID() { 43 | 44 | byte[] privateKey = HashUtil.sha3(HashUtil.randomPeerId()); 45 | return Hex.toHexString(privateKey); 46 | } 47 | 48 | public String getName() { 49 | return name; 50 | } 51 | 52 | public void setName(String name) { 53 | this.name = name; 54 | } 55 | 56 | public String getVersion() { 57 | return version; 58 | } 59 | 60 | public void setVersion(String version) { 61 | this.version = version; 62 | } 63 | 64 | public String getUrl() { 65 | return url; 66 | } 67 | 68 | public void setUrl(String url) { 69 | this.url = url; 70 | } 71 | 72 | public String getId() { 73 | return id; 74 | } 75 | 76 | public void setId(String id) { 77 | this.id = id; 78 | } 79 | 80 | 81 | @Override 82 | public boolean equals(Object o) { 83 | if (this == o) return true; 84 | if (!(o instanceof Dapp)) return false; 85 | Dapp object = (Dapp) o; 86 | return object.getId().equalsIgnoreCase(id); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /app/src/main/res/layout/profile_drawer_list_item.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 17 | 18 | 27 | 28 | 36 | 37 | 45 | 46 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23" 6 | 7 | defaultConfig { 8 | applicationId "io.syng" 9 | minSdkVersion 15 10 | targetSdkVersion 23 11 | versionCode 3 12 | versionName "1.0" 13 | multiDexEnabled true 14 | } 15 | packagingOptions { 16 | exclude 'META-INF/INDEX.LIST' 17 | exclude 'META-INF/LICENSE.txt' 18 | exclude 'META-INF/NOTICE.txt' 19 | exclude 'LICENSE' 20 | exclude 'NOTICE' 21 | exclude 'META-INF/ASL2.0' 22 | exclude 'META-INF/LICENSE' 23 | exclude 'META-INF/NOTICE' 24 | exclude 'META-INF/services/javax.annotation.processing.Processor' 25 | } 26 | dexOptions { 27 | javaMaxHeapSize "4g" 28 | } 29 | lintOptions { 30 | abortOnError false 31 | } 32 | buildTypes { 33 | release { 34 | minifyEnabled false 35 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 36 | zipAlignEnabled true 37 | } 38 | } 39 | } 40 | repositories { 41 | maven { url "https://jitpack.io" } 42 | } 43 | dependencies { 44 | compile fileTree(include: ['*.jar'], dir: 'libs') 45 | compile(project(':ethereumj-core-android')) { 46 | exclude group: "org.hibernate", module: "hibernate-core" 47 | exclude group: "com.h2database", module: "h2" 48 | exclude group: "org.codehaus.jackson", module: "jackson-mapper-asl" 49 | exclude group: "org.mapdb", module: "mapdb" 50 | } 51 | compile 'com.android.support:multidex:1.0.1' 52 | compile 'com.android.support:appcompat-v7:23.0.0' 53 | compile 'com.android.support:recyclerview-v7:23.0.0' 54 | compile 'com.android.support:design:23.0.0' 55 | compile 'com.android.support:cardview-v7:23.0.0' 56 | compile 'com.getbase:floatingactionbutton:1.9.0' 57 | compile 'com.afollestad:material-dialogs:0.7.7.0' 58 | compile 'com.github.bumptech.glide:glide:3.6.1' 59 | compile(project(':cordova-android')) { 60 | } 61 | debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1' 62 | releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1' 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/java/io/syng/adapter/BackgroundArrayAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Jarrad Hope 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | package io.syng.adapter; 10 | 11 | import android.content.Context; 12 | import android.view.LayoutInflater; 13 | import android.view.View; 14 | import android.view.ViewGroup; 15 | import android.widget.ArrayAdapter; 16 | import android.widget.ImageView; 17 | 18 | import com.bumptech.glide.Glide; 19 | 20 | import java.util.ArrayList; 21 | import java.util.Arrays; 22 | import java.util.List; 23 | 24 | import io.syng.R; 25 | 26 | 27 | public class BackgroundArrayAdapter extends ArrayAdapter { 28 | 29 | private static final List sItems = new ArrayList<>( 30 | Arrays.asList(R.drawable.bg0_resized, R.drawable.bg1_resized, R.drawable.bg2_resized, R.drawable.bg3_resized)); 31 | 32 | public BackgroundArrayAdapter(Context context) { 33 | super(context, 0, sItems); 34 | } 35 | 36 | @Override 37 | public View getView(int position, View convertView, ViewGroup parent) { 38 | ViewHolder viewHolder; 39 | 40 | if (convertView == null) { 41 | convertView = LayoutInflater.from(parent.getContext()) 42 | .inflate(R.layout.backround_list_item, parent, false); 43 | viewHolder = new ViewHolder(convertView); 44 | convertView.setTag(viewHolder); 45 | } else { 46 | viewHolder = (ViewHolder) convertView.getTag(); 47 | } 48 | Glide.with(getContext()).load(getItem(position)).into(viewHolder.backgroundImage); 49 | return convertView; 50 | } 51 | 52 | 53 | static class ViewHolder { 54 | 55 | View backgroundView; 56 | ImageView backgroundImage; 57 | 58 | public ViewHolder(View view) { 59 | backgroundView = view.findViewById(R.id.ll_background); 60 | backgroundImage = (ImageView) view.findViewById(R.id.iv_background); 61 | } 62 | } 63 | 64 | public int getImageResourceIdByPosition(int position) { 65 | return sItems.get(position); 66 | } 67 | 68 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/drawer_front_view.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | 15 | 29 | 30 | 44 | 45 | 46 | 47 | 54 | 55 | -------------------------------------------------------------------------------- /app/src/main/java/io/syng/entity/ObjectSerializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Jarrad Hope 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | package io.syng.entity; 10 | 11 | import java.io.ByteArrayInputStream; 12 | import java.io.ByteArrayOutputStream; 13 | import java.io.ObjectInputStream; 14 | import java.io.ObjectOutputStream; 15 | import java.io.Serializable; 16 | 17 | public class ObjectSerializer { 18 | 19 | 20 | public static String serialize(Serializable obj) throws Exception { 21 | if (obj == null) return ""; 22 | try { 23 | ByteArrayOutputStream serialObj = new ByteArrayOutputStream(); 24 | ObjectOutputStream objStream = new ObjectOutputStream(serialObj); 25 | objStream.writeObject(obj); 26 | objStream.close(); 27 | return encodeBytes(serialObj.toByteArray()); 28 | } catch (Exception e) { 29 | throw e; 30 | } 31 | } 32 | 33 | public static Object deserialize(String str) throws Exception { 34 | if (str == null || str.length() == 0) return null; 35 | try { 36 | ByteArrayInputStream serialObj = new ByteArrayInputStream(decodeBytes(str)); 37 | ObjectInputStream objStream = new ObjectInputStream(serialObj); 38 | return objStream.readObject(); 39 | } catch (Exception e) { 40 | throw e; 41 | } 42 | } 43 | 44 | public static String encodeBytes(byte[] bytes) { 45 | StringBuffer strBuf = new StringBuffer(); 46 | for (int i = 0; i < bytes.length; i++) { 47 | strBuf.append((char) (((bytes[i] >> 4) & 0xF) + ((int) 'a'))); 48 | strBuf.append((char) (((bytes[i]) & 0xF) + ((int) 'a'))); 49 | } 50 | return strBuf.toString(); 51 | } 52 | 53 | public static byte[] decodeBytes(String str) { 54 | byte[] bytes = new byte[str.length() / 2]; 55 | for (int i = 0; i < str.length(); i += 2) { 56 | char c = str.charAt(i); 57 | bytes[i / 2] = (byte) ((c - 'a') << 4); 58 | c = str.charAt(i + 1); 59 | bytes[i / 2] += (c - 'a'); 60 | } 61 | return bytes; 62 | } 63 | 64 | } 65 | 66 | -------------------------------------------------------------------------------- /app/src/main/res/layout/dapp_drawer_list_item.xml: -------------------------------------------------------------------------------- 1 | 11 | 12 | 19 | 20 | 30 | 31 | 39 | 40 | 48 | 49 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /app/src/main/java/io/syng/adapter/ProfileViewPagerAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Jarrad Hope 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | package io.syng.adapter; 10 | 11 | import android.content.Context; 12 | import android.support.v4.app.Fragment; 13 | import android.support.v4.app.FragmentManager; 14 | import android.support.v4.app.FragmentPagerAdapter; 15 | import android.support.v4.app.FragmentTransaction; 16 | import android.view.ViewGroup; 17 | 18 | import io.syng.fragment.profile.ProfileGeneralFragment; 19 | import io.syng.fragment.profile.ProfileKeysFragment; 20 | 21 | public final class ProfileViewPagerAdapter extends FragmentPagerAdapter { 22 | 23 | public static final int GENERAL_POSITION = 0; 24 | public static final int KEYS_POSITION = 1; 25 | 26 | public static final String[] LABELS = new String[]{"General", "Keys"}; 27 | private final Context mContext; 28 | private final String mProfileId; 29 | 30 | public ProfileViewPagerAdapter(FragmentManager fragmentManager, Context context, String profileId) { 31 | super(fragmentManager); 32 | this.mContext = context; 33 | mProfileId = profileId; 34 | } 35 | 36 | @Override 37 | public Fragment getItem(int position) { 38 | switch (position) { 39 | case GENERAL_POSITION: 40 | return ProfileGeneralFragment.newInstance(mProfileId); 41 | case KEYS_POSITION: 42 | return ProfileKeysFragment.newInstance(mProfileId); 43 | default: 44 | throw new UnsupportedOperationException(); 45 | } 46 | } 47 | 48 | @Override 49 | public void destroyItem(ViewGroup container, int position, Object object) { 50 | FragmentManager manager = ((Fragment) object).getFragmentManager(); 51 | FragmentTransaction trans = manager.beginTransaction(); 52 | trans.remove((Fragment) object); 53 | trans.commit(); 54 | super.destroyItem(container, position, object); 55 | } 56 | 57 | @Override 58 | public int getCount() { 59 | return LABELS.length; 60 | } 61 | 62 | @Override 63 | public CharSequence getPageTitle(int position) { 64 | return LABELS[position]; 65 | } 66 | } -------------------------------------------------------------------------------- /app/src/main/java/io/syng/fragment/profile/ProfileKeysFragment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Jarrad Hope 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | package io.syng.fragment.profile; 10 | 11 | 12 | import android.os.Bundle; 13 | import android.support.annotation.Nullable; 14 | import android.support.v4.app.Fragment; 15 | import android.support.v7.widget.LinearLayoutManager; 16 | import android.support.v7.widget.RecyclerView; 17 | import android.view.LayoutInflater; 18 | import android.view.View; 19 | import android.view.ViewGroup; 20 | 21 | import io.syng.R; 22 | import io.syng.adapter.ProfileKeyAdapter; 23 | import io.syng.entity.Profile; 24 | import io.syng.util.ProfileManager; 25 | 26 | public class ProfileKeysFragment extends Fragment { 27 | 28 | private static final String ARG_PROFILE_ID = "profile_id"; 29 | private String mProfileId; 30 | 31 | private RecyclerView mRecyclerView; 32 | private ProfileKeyAdapter mProfileDrawerAdapter; 33 | 34 | public static ProfileKeysFragment newInstance(String profileId) { 35 | Bundle bundle = new Bundle(); 36 | bundle.putString(ARG_PROFILE_ID, profileId); 37 | ProfileKeysFragment dialogFragment = new ProfileKeysFragment(); 38 | dialogFragment.setArguments(bundle); 39 | return dialogFragment; 40 | } 41 | 42 | @Override 43 | public void onCreate(@Nullable Bundle savedInstanceState) { 44 | super.onCreate(savedInstanceState); 45 | mProfileId = getArguments().getString(ARG_PROFILE_ID); 46 | } 47 | 48 | @Override 49 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 50 | Bundle savedInstanceState) { 51 | View view = inflater.inflate(R.layout.fragment_profile_keys, container, false); 52 | 53 | Profile profile = ProfileManager.getProfileById(mProfileId); 54 | mRecyclerView = (RecyclerView) view.findViewById(R.id.rv_profile_keys); 55 | RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getActivity()); 56 | mRecyclerView.setLayoutManager(layoutManager); 57 | mProfileDrawerAdapter = new ProfileKeyAdapter(profile.getAddresses()); 58 | mRecyclerView.setAdapter(mProfileDrawerAdapter); 59 | 60 | return view; 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/java/io/syng/entity/Settings.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Jarrad Hope 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | package io.syng.entity; 10 | 11 | 12 | import java.io.Serializable; 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | 16 | public class Settings implements Serializable { 17 | 18 | protected int runningMode = RunningMode.JSON_RPC_CLIENT; 19 | 20 | /* "sync in background" option */ 21 | protected boolean syncInBackground = false; 22 | 23 | /* "sync only when connected to wifi" */ 24 | protected boolean syncOnlyWhenWifi = true; 25 | 26 | /* "setting json-rpc servers (address and port)" */ 27 | protected List jsonRpcServers = new ArrayList<>(); 28 | 29 | private static final long serialVersionUID = 1L; 30 | 31 | public Settings() { 32 | 33 | } 34 | 35 | public int getRunningMode() { 36 | return runningMode; 37 | } 38 | 39 | public void setRunningMode(int runningMode) { 40 | this.runningMode = runningMode; 41 | } 42 | 43 | public boolean getSyncInBackground() { 44 | return syncInBackground; 45 | } 46 | 47 | public void setSyncInBackground(boolean syncInBackground) { 48 | this.syncInBackground = syncInBackground; 49 | } 50 | 51 | public boolean getSyncOnlyWhenWifi() { 52 | return syncOnlyWhenWifi; 53 | } 54 | 55 | public void setSyncOnlyWhenWifi(boolean syncOnlyWhenWifi) { 56 | this.syncOnlyWhenWifi = syncOnlyWhenWifi; 57 | } 58 | 59 | public List getJsonRpcServers() { 60 | return jsonRpcServers; 61 | } 62 | 63 | public void setJsonRpcServers(List jsonRpcServers) { 64 | this.jsonRpcServers = jsonRpcServers; 65 | } 66 | 67 | public void addJsonRpcServer(String host, int port) { 68 | JsonRpcServer server = new JsonRpcServer(); 69 | server.setHost(host); 70 | server.setPort(port); 71 | jsonRpcServers.add(server); 72 | } 73 | 74 | public void addJsonRpcServer(JsonRpcServer jsonRpcServer) { 75 | this.jsonRpcServers.add(jsonRpcServer); 76 | } 77 | 78 | public void removeJsonRpcServer(JsonRpcServer jsonRpcServer) { 79 | this.jsonRpcServers.remove(jsonRpcServer); 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Syng 5 | Open Navigation Drawer 6 | Close Navigation Drawer 7 | 8 | Add Profile 9 | Profiles 10 | Save 11 | Password Protected 12 | Add Dapp 13 | 14 | Name 15 | Url 16 | Save 17 | Cancel 18 | Import 19 | 20 | Import Wallet 21 | OK 22 | Import json wallet 23 | Import hex encoded private key 24 | The specified file was not found 25 | Error reading specified file 26 | Invalid wallet or password 27 | 28 | Invalid url 29 | 30 | Profile Password 31 | This is PRE-ALPHA software and most likely contains numerous bugs. The layout, design, and functionality may change frequently. This also lacks numerous features that will be included in later versions. Using this software you agree that you hold yourself personally accountable for interacting with this software. 32 | WARNING 33 | Profile name 34 | Password 35 | Repeat password 36 | Create 37 | Cancel 38 | Import 39 | Export 40 | LoginActivity 41 | 42 | Hello world! 43 | Settings 44 | Remove profile 45 | 46 | 47 | -------------------------------------------------------------------------------- /app/src/main/java/io/syng/fragment/profile/ProfileGeneralFragment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Jarrad Hope 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | package io.syng.fragment.profile; 10 | 11 | 12 | import android.os.Bundle; 13 | import android.support.annotation.Nullable; 14 | import android.support.v4.app.Fragment; 15 | import android.text.Editable; 16 | import android.text.TextWatcher; 17 | import android.view.LayoutInflater; 18 | import android.view.View; 19 | import android.view.ViewGroup; 20 | import android.widget.EditText; 21 | 22 | import io.syng.R; 23 | import io.syng.entity.Profile; 24 | import io.syng.util.ProfileManager; 25 | 26 | public class ProfileGeneralFragment extends Fragment implements TextWatcher { 27 | 28 | private static final String ARG_PROFILE_ID = "profile_id"; 29 | private String mProfileId; 30 | 31 | public static ProfileGeneralFragment newInstance(String profileId) { 32 | Bundle bundle = new Bundle(); 33 | bundle.putString(ARG_PROFILE_ID, profileId); 34 | ProfileGeneralFragment dialogFragment = new ProfileGeneralFragment(); 35 | dialogFragment.setArguments(bundle); 36 | return dialogFragment; 37 | } 38 | 39 | @Override 40 | public void onCreate(@Nullable Bundle savedInstanceState) { 41 | super.onCreate(savedInstanceState); 42 | mProfileId = getArguments().getString(ARG_PROFILE_ID); 43 | } 44 | 45 | @Override 46 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 47 | Bundle savedInstanceState) { 48 | View view = inflater.inflate(R.layout.fragment_profile_general, container, false); 49 | EditText profileName = (EditText) view.findViewById(R.id.et_profile_name); 50 | profileName.addTextChangedListener(this); 51 | Profile profile = ProfileManager.getProfileById(mProfileId); 52 | if (profile != null) { 53 | profileName.setText(profile.getName()); 54 | } 55 | return view; 56 | } 57 | 58 | 59 | @Override 60 | public void beforeTextChanged(CharSequence s, int start, int count, int after) { 61 | } 62 | 63 | @Override 64 | public void onTextChanged(CharSequence s, int start, int before, int count) { 65 | Profile profile = ProfileManager.getProfileById(mProfileId); 66 | if (profile != null) { 67 | profile.setName(s.toString()); 68 | ProfileManager.updateProfile(profile); 69 | } 70 | } 71 | 72 | @Override 73 | public void afterTextChanged(Editable s) { 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /app/src/main/java/io/syng/activity/MainActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Jarrad Hope 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | package io.syng.activity; 10 | 11 | import android.content.Intent; 12 | import android.os.Bundle; 13 | import android.support.v4.app.Fragment; 14 | 15 | import io.syng.R; 16 | import io.syng.entity.Dapp; 17 | import io.syng.fragment.ConsoleFragment; 18 | import io.syng.fragment.WebViewFragment; 19 | import io.syng.util.ProfileManager; 20 | 21 | 22 | public class MainActivity extends BaseActivity { 23 | 24 | @Override 25 | protected void onCreate(Bundle savedInstanceState) { 26 | super.onCreate(savedInstanceState); 27 | 28 | setContentView(R.layout.activity_main); 29 | if (savedInstanceState == null) { 30 | if (!ProfileManager.getCurrentProfile().getDapps().isEmpty()) { 31 | Dapp dapp = ProfileManager.getCurrentProfile().getDapps().get(0); 32 | onDAppItemClick(dapp); 33 | }else{ 34 | replaceFragment(new ConsoleFragment()); 35 | } 36 | } 37 | processIntent(getIntent()); 38 | 39 | } 40 | 41 | @Override 42 | protected void onNewIntent(Intent intent) { 43 | super.onNewIntent(intent); 44 | processIntent(intent); 45 | } 46 | 47 | private void processIntent(Intent intent) { 48 | if (intent.getDataString() != null && intent.getDataString().indexOf("dapp://") == 0) { 49 | WebViewFragment wvF = new WebViewFragment(); 50 | Bundle args = new Bundle(); 51 | args.putString("url", intent.getDataString()); 52 | wvF.setArguments(args); 53 | replaceFragment(wvF); 54 | closeDrawer(); 55 | } 56 | } 57 | 58 | @Override 59 | protected void onDAppClick(Dapp dapp) { 60 | switch (dapp.getUrl()) { 61 | case "": 62 | replaceFragment(new ConsoleFragment()); 63 | getSupportActionBar().setTitle(R.string.app_name); 64 | break; 65 | default: 66 | WebViewFragment wvF = new WebViewFragment(); 67 | Bundle args = new Bundle(); 68 | args.putString("url", dapp.getUrl()); 69 | wvF.setArguments(args); 70 | replaceFragment(wvF); 71 | getSupportActionBar().setTitle(dapp.getName()); 72 | break; 73 | } 74 | } 75 | 76 | 77 | @SuppressWarnings("ConstantConditions") 78 | private void replaceFragment(Fragment fragment) { 79 | getSupportFragmentManager().beginTransaction(). 80 | replace(R.id.container, fragment).commit(); 81 | } 82 | 83 | 84 | } 85 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | Settings 3 | 4 | 5 | 6 | 7 | General 8 | 9 | Sync in background 10 | Enable syncing blockchain in background 11 | 12 | Sync only on wifi 13 | Sync blockchain only on wifi 14 | 15 | Display name 16 | John Smith 17 | 18 | Running Mode 19 | 20 | Full Client 21 | JSON Proxy 22 | Light Client 23 | 1 24 | 2 25 | 3 26 | 27 | 28 | @string/pref_running_mode_full_name 29 | @string/pref_running_mode_json_name 30 | 31 | 32 | 33 | 34 | @string/pref_running_mode_full_value 35 | @string/pref_running_mode_json_value 36 | 37 | 38 | 39 | 40 | Data & sync 41 | 42 | Sync frequency 43 | 44 | 15 minutes 45 | 30 minutes 46 | 1 hour 47 | 3 hours 48 | 6 hours 49 | Never 50 | 51 | 52 | 53 | 15 54 | 30 55 | 60 56 | 180 57 | 360 58 | -1 59 | 60 | 61 | 62 | http://rpc0.syng.io:8545 63 | pref_json_rpc_server_key 64 | JSON-RPC server address 65 | running_mode 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 25 | 26 | 27 | 28 | 29 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 60 | 63 | 64 | 65 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /app/src/main/res/xml/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | Syng 6 | 7 | 8 | Syng Ethereum 9 | 10 | 11 | 12 | Jarrad Hope 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /app/src/main/res/layout/drawer_bottom_part.xml: -------------------------------------------------------------------------------- 1 | 11 | 12 | 19 | 20 | 27 | 28 | 35 | 36 | 46 | 47 | 48 | 49 | 50 | 57 | 58 | 65 | 66 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /app/src/main/java/io/syng/activity/LoginActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Jarrad Hope 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | package io.syng.activity; 10 | 11 | import android.content.Intent; 12 | import android.os.Bundle; 13 | import android.support.v7.app.AppCompatActivity; 14 | import android.text.TextUtils; 15 | import android.view.View; 16 | import android.widget.EditText; 17 | import android.widget.ImageView; 18 | import android.widget.Toast; 19 | 20 | import com.afollestad.materialdialogs.MaterialDialog; 21 | import com.bumptech.glide.Glide; 22 | 23 | import org.ethereum.crypto.HashUtil; 24 | import org.spongycastle.util.encoders.Hex; 25 | 26 | import java.util.ArrayList; 27 | import java.util.List; 28 | 29 | import io.syng.R; 30 | import io.syng.entity.Profile; 31 | import io.syng.util.*; 32 | 33 | import static org.ethereum.config.SystemProperties.CONFIG; 34 | 35 | public class LoginActivity extends AppCompatActivity { 36 | 37 | @Override 38 | protected void onCreate(Bundle savedInstanceState) { 39 | super.onCreate(savedInstanceState); 40 | setContentView(R.layout.activity_login); 41 | 42 | ImageView backgroundImageView = (ImageView) findViewById(R.id.iv_background); 43 | Glide.with(this).load(R.drawable.console_bg).into(backgroundImageView); 44 | 45 | if (PrefsUtil.isFirstLaunch()) { 46 | createAndSetProfile(); 47 | } else { 48 | loginWallet(); 49 | } 50 | } 51 | 52 | private void startNextActivity() { 53 | startActivity(new Intent(this, MainActivity.class)); 54 | overridePendingTransition(R.anim.fade_in, R.anim.fade_out); 55 | finish(); 56 | } 57 | 58 | @Override 59 | public void finish() { 60 | super.finish(); 61 | overridePendingTransition(R.anim.fade_in, R.anim.fade_out); 62 | } 63 | 64 | private void createAndSetProfile() { 65 | GeneralUtil.showProfileCreateDialog(LoginActivity.this, false, new MaterialDialog.ButtonCallback() { 66 | @Override 67 | public void onPositive(MaterialDialog dialog) { 68 | if (GeneralUtil.processCreateDialog(LoginActivity.this, dialog)) { 69 | dialog.dismiss(); 70 | startNextActivity(); 71 | } 72 | } 73 | 74 | @Override 75 | public void onNegative(MaterialDialog dialog) { 76 | LoginActivity.this.finish(); 77 | dialog.dismiss(); 78 | } 79 | }); 80 | } 81 | 82 | private void loginWallet() { 83 | final Profile profile = ProfileManager.getCurrentProfile(); 84 | GeneralUtil.showProfilePasswordRequestDialog(LoginActivity.this, profile.getName(), new MaterialDialog.ButtonCallback() { 85 | @Override 86 | public void onPositive(MaterialDialog dialog) { 87 | View view = dialog.getCustomView(); 88 | EditText passwordText = (EditText) view.findViewById(R.id.et_pass); 89 | String password = passwordText.getText().toString(); 90 | if (profile.checkPassword(password)) { 91 | dialog.dismiss(); 92 | ProfileManager.setCurrentProfile(profile, password); 93 | startNextActivity(); 94 | } else { 95 | Toast.makeText(LoginActivity.this, "Password is not correct", Toast.LENGTH_SHORT).show(); 96 | } 97 | } 98 | 99 | @Override 100 | public void onNegative(MaterialDialog dialog) { 101 | LoginActivity.this.finish(); 102 | dialog.dismiss(); 103 | } 104 | }); 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /app/src/main/java/io/syng/util/PrefsUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Jarrad Hope 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | package io.syng.util; 10 | 11 | import android.content.Context; 12 | import android.content.SharedPreferences; 13 | import android.content.SharedPreferences.Editor; 14 | import android.preference.PreferenceManager; 15 | import android.support.annotation.DrawableRes; 16 | import android.support.annotation.StringRes; 17 | 18 | import java.util.ArrayList; 19 | 20 | import io.syng.R; 21 | import io.syng.entity.ObjectSerializer; 22 | import io.syng.entity.Profile; 23 | 24 | public final class PrefsUtil { 25 | 26 | private static final String PROFILES_KEY = "pref_profile_key"; 27 | private static final String FIRST_LAUNCH_KEY = "first_launch_key"; 28 | private static final String CURRENT_PROFILE_KEY = "current_profile"; 29 | 30 | private static PrefsUtil sInstance; 31 | private final Context mContext; 32 | 33 | private SharedPreferences mPreferences; 34 | 35 | private PrefsUtil(Context context) { 36 | mPreferences = PreferenceManager.getDefaultSharedPreferences(context); 37 | mContext = context; 38 | } 39 | 40 | public static void initialize(Context context) { 41 | if (sInstance != null) { 42 | throw new IllegalStateException("PrefsUtil have already been initialized"); 43 | } 44 | sInstance = new PrefsUtil(context); 45 | } 46 | 47 | private static PrefsUtil getInstance() { 48 | if (sInstance == null) { 49 | throw new IllegalStateException("PrefsUtil should be initialized first"); 50 | } 51 | return sInstance; 52 | } 53 | 54 | private static Editor getEditor() { 55 | return getPrefs().edit(); 56 | } 57 | 58 | private static SharedPreferences getPrefs() { 59 | return getInstance().mPreferences; 60 | } 61 | 62 | private static String getString(@StringRes int resourceId) { 63 | return getInstance().mContext.getString(resourceId); 64 | } 65 | 66 | public static void saveProfiles(ArrayList profiles) { 67 | try { 68 | getEditor().putString(PROFILES_KEY, ObjectSerializer.serialize(profiles)).commit(); 69 | } catch (Exception e) { 70 | e.printStackTrace(); 71 | } 72 | } 73 | 74 | @SuppressWarnings("unchecked") 75 | public static ArrayList getProfiles() { 76 | ArrayList profiles = new ArrayList<>(); 77 | try { 78 | profiles = (ArrayList) ObjectSerializer.deserialize( 79 | getPrefs().getString(PROFILES_KEY, ObjectSerializer.serialize(profiles))); 80 | } catch (Exception e) { 81 | e.printStackTrace(); 82 | } 83 | return profiles; 84 | } 85 | 86 | public static void setCurrentProfileId(String profileId) { 87 | getEditor().putString(CURRENT_PROFILE_KEY, profileId).commit(); 88 | } 89 | 90 | public static String getCurrentProfileId() { 91 | return getPrefs().getString(CURRENT_PROFILE_KEY, ""); 92 | } 93 | 94 | public static void setFirstLaunch(boolean isFirstLaunch) { 95 | getEditor().putBoolean(FIRST_LAUNCH_KEY, isFirstLaunch).apply(); 96 | } 97 | 98 | public static boolean isFirstLaunch() { 99 | return getPrefs().getBoolean(FIRST_LAUNCH_KEY, true); 100 | } 101 | 102 | 103 | public static void setBackgroundResourceId(String profileId, @DrawableRes int resourceId) { 104 | getEditor().putInt(profileId, resourceId).commit(); 105 | } 106 | 107 | public static int getBackgroundResourceId(String profileId) { 108 | return getPrefs().getInt(profileId, R.drawable.bg0_resized); 109 | } 110 | 111 | public static String getJsonRPCServerAddress() { 112 | return getPrefs().getString(getString(R.string.pref_json_rpc_server_key), getString(R.string.pref_json_rpc_server_default)); 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /app/src/main/java/io/syng/util/Encryption.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Jarrad Hope 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | package io.syng.util; 10 | 11 | import android.util.Base64; 12 | import android.util.Log; 13 | 14 | import java.security.SecureRandom; 15 | import java.security.spec.KeySpec; 16 | import java.util.regex.Pattern; 17 | 18 | import javax.crypto.Cipher; 19 | import javax.crypto.SecretKey; 20 | import javax.crypto.SecretKeyFactory; 21 | import javax.crypto.spec.IvParameterSpec; 22 | import javax.crypto.spec.PBEKeySpec; 23 | import javax.crypto.spec.SecretKeySpec; 24 | 25 | public class Encryption { 26 | 27 | private static final String TAG = "Encryption"; 28 | 29 | private static SecureRandom random = new SecureRandom(); 30 | private static String delimiter = "}"; 31 | private static int keyLength = 256; 32 | private static int saltLength = keyLength / 8; 33 | private static int iterationCount = 20000; 34 | 35 | public static String encrypt(String text, String password) { 36 | 37 | Log.d(TAG, "Encrypting: " + text); 38 | String encryptedText = ""; 39 | byte[] salt = generateSalt(saltLength); 40 | SecretKey key = generateKey(password, salt); 41 | if (key != null) { 42 | try { 43 | Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 44 | byte[] iv = new byte[cipher.getBlockSize()]; 45 | random.nextBytes(iv); 46 | IvParameterSpec ivParams = new IvParameterSpec(iv); 47 | cipher.init(Cipher.ENCRYPT_MODE, key, ivParams); 48 | byte[] encryptedKey = cipher.doFinal(text.getBytes("UTF-8")); 49 | 50 | encryptedText = Base64.encodeToString(salt, Base64.NO_WRAP); 51 | encryptedText += delimiter + Base64.encodeToString(iv, Base64.NO_WRAP); 52 | encryptedText += delimiter + Base64.encodeToString(encryptedKey, Base64.NO_WRAP); 53 | Log.d(TAG, "Encrypted: " + encryptedText); 54 | return encryptedText; 55 | } catch (Exception e) { 56 | Log.e(TAG, "encrypt(): " + e.toString()); 57 | } 58 | } 59 | return null; 60 | } 61 | 62 | private static byte[] generateSalt(int saltLength) { 63 | 64 | byte[] salt = new byte[saltLength]; 65 | random.nextBytes(salt); 66 | return salt; 67 | } 68 | 69 | private static SecretKey generateKey(String password, byte[] salt) { 70 | try { 71 | KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, iterationCount, keyLength); 72 | SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 73 | byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded(); 74 | return new SecretKeySpec(keyBytes, "AES"); 75 | } catch (Exception e) { 76 | Log.e(TAG, "generateKey(): " + e.toString()); 77 | } 78 | return null; 79 | } 80 | 81 | public static String decrypt(String encryptedText, String password) { 82 | 83 | Log.d(TAG, "Decrypting: " + encryptedText); 84 | String[] parts = encryptedText.split(Pattern.quote(delimiter)); 85 | byte[] salt = Base64.decode(parts[0], Base64.NO_WRAP); 86 | byte[] iv = Base64.decode(parts[1], Base64.NO_WRAP); 87 | byte[] cipherBytes = Base64.decode(parts[2], Base64.NO_WRAP); 88 | 89 | SecretKey key = generateKey(password, salt); 90 | if (key != null) { 91 | try { 92 | Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 93 | IvParameterSpec ivParams = new IvParameterSpec(iv); 94 | cipher.init(Cipher.DECRYPT_MODE, key, ivParams); 95 | byte[] decrypted = cipher.doFinal(cipherBytes); 96 | String decryptedText = new String(decrypted, "UTF-8"); 97 | Log.d(TAG, "Decrypted: " + decryptedText); 98 | return decryptedText; 99 | } catch (Exception e) { 100 | Log.e(TAG, "decrypt(): " + e.toString()); 101 | } 102 | } 103 | 104 | return null; 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /app/src/main/java/io/syng/fragment/ConsoleFragment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Jarrad Hope 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | package io.syng.fragment; 10 | 11 | 12 | import android.annotation.SuppressLint; 13 | import android.content.Intent; 14 | import android.net.Uri; 15 | import android.os.Bundle; 16 | import android.os.Handler; 17 | import android.os.Message; 18 | import android.support.v4.app.Fragment; 19 | import android.text.method.ScrollingMovementMethod; 20 | import android.view.LayoutInflater; 21 | import android.view.View; 22 | import android.view.View.OnClickListener; 23 | import android.view.ViewGroup; 24 | import android.widget.ImageView; 25 | import android.widget.TextView; 26 | 27 | import com.bumptech.glide.Glide; 28 | import com.squareup.leakcanary.RefWatcher; 29 | 30 | import org.ethereum.android.service.ConnectorHandler; 31 | import org.ethereum.android.service.events.EventFlag; 32 | 33 | import java.text.DateFormat; 34 | import java.text.SimpleDateFormat; 35 | import java.util.EnumSet; 36 | import java.util.UUID; 37 | 38 | import io.syng.R; 39 | import io.syng.app.SyngApplication; 40 | 41 | 42 | public class ConsoleFragment extends Fragment implements OnClickListener { 43 | 44 | private static final String ACTION_RECEIVE = "dapp://syng.io/dapps/wallet/#/tab/receive"; 45 | private static final String ACTION_SEND = "dapp://syng.io/dapps/wallet/#/tab/send/"; 46 | 47 | private final static int CONSOLE_LENGTH = 10000; 48 | private final static int CONSOLE_REFRESH_MILLS = 1000 * 5; //5 sec 49 | 50 | private TextView mConsoleText; 51 | 52 | private Handler mHandler = new Handler(); 53 | 54 | private Runnable mRunnable = new Runnable() { 55 | @Override 56 | public void run() { 57 | 58 | int length = SyngApplication.mConsoleLog.length(); 59 | if (length > CONSOLE_LENGTH) { 60 | SyngApplication.mConsoleLog = SyngApplication.mConsoleLog.substring(CONSOLE_LENGTH * ((length / CONSOLE_LENGTH) - 1) + length % CONSOLE_LENGTH); 61 | } 62 | mConsoleText.setText(SyngApplication.mConsoleLog); 63 | 64 | mHandler.postDelayed(mRunnable, CONSOLE_REFRESH_MILLS); 65 | } 66 | }; 67 | 68 | 69 | @Override 70 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 71 | Bundle savedInstanceState) { 72 | View view = inflater.inflate(R.layout.fragment_console, container, false); 73 | 74 | mConsoleText = (TextView) view.findViewById(R.id.tv_console_log); 75 | mConsoleText.setText(SyngApplication.mConsoleLog); 76 | mConsoleText.setMovementMethod(new ScrollingMovementMethod()); 77 | 78 | ImageView background = (ImageView) view.findViewById(R.id.iv_background); 79 | Glide.with(this).load(R.drawable.console_bg).into(background); 80 | 81 | view.findViewById(R.id.fab_send).setOnClickListener(this); 82 | view.findViewById(R.id.fab_receive).setOnClickListener(this); 83 | 84 | return view; 85 | } 86 | 87 | @Override 88 | public void onPause() { 89 | super.onPause(); 90 | mHandler.removeCallbacksAndMessages(null); 91 | } 92 | 93 | @Override 94 | public void onResume() { 95 | super.onResume(); 96 | mHandler.post(mRunnable); 97 | } 98 | 99 | @Override 100 | public void onDestroy() { 101 | super.onDestroy(); 102 | RefWatcher refWatcher = SyngApplication.getRefWatcher(getActivity()); 103 | refWatcher.watch(this); 104 | } 105 | 106 | @Override 107 | public void onClick(View v) { 108 | switch (v.getId()) { 109 | case R.id.fab_send: 110 | Intent intent1 = new Intent(Intent.ACTION_VIEW); 111 | intent1.setData(Uri.parse(ACTION_SEND)); 112 | if (intent1.resolveActivity(getActivity().getPackageManager()) != null) { 113 | startActivity(intent1); 114 | } 115 | break; 116 | case R.id.fab_receive: 117 | Intent intent2 = new Intent(Intent.ACTION_VIEW); 118 | intent2.setData(Uri.parse(ACTION_RECEIVE)); 119 | if (intent2.resolveActivity(getActivity().getPackageManager()) != null) { 120 | startActivity(intent2); 121 | } 122 | break; 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_console.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 17 | 18 | 22 | 23 | 29 | 30 | 36 | 37 | 41 | 42 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 96 | 97 | 106 | 107 | 108 | 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /app/src/main/java/io/syng/adapter/helper/SimpleItemTouchHelperCallback.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Paul Burke 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Copyright (c) 2015 Jarrad Hope 19 | * 20 | * This Source Code Form is subject to the terms of the Mozilla Public 21 | * License, v. 2.0. If a copy of the MPL was not distributed with this 22 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 23 | */ 24 | 25 | package io.syng.adapter.helper; 26 | 27 | import android.support.v7.widget.RecyclerView; 28 | import android.support.v7.widget.helper.ItemTouchHelper; 29 | 30 | /** 31 | * An implementation of {@link ItemTouchHelper.Callback} that enables basic drag & drop and 32 | * swipe-to-dismiss. Drag events are automatically started by an item long-press.
33 | *
34 | * Expects the RecyclerView.Adapter to listen for {@link 35 | * ItemTouchHelperAdapter} callbacks and the RecyclerView.ViewHolder to implement 36 | * {@link ItemTouchHelperViewHolder}. 37 | * 38 | * @author Paul Burke (ipaulpro) 39 | */ 40 | public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback { 41 | 42 | public static final float ALPHA_FULL = 1.0f; 43 | 44 | private final ItemTouchHelperAdapter mAdapter; 45 | 46 | public SimpleItemTouchHelperCallback(ItemTouchHelperAdapter adapter) { 47 | mAdapter = adapter; 48 | } 49 | 50 | @Override 51 | public boolean isLongPressDragEnabled() { 52 | return false; 53 | } 54 | 55 | @Override 56 | public boolean isItemViewSwipeEnabled() { 57 | return false; 58 | } 59 | 60 | @Override 61 | public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { 62 | } 63 | 64 | @Override 65 | public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { 66 | final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; 67 | final int swipeFlags = 0; 68 | return makeMovementFlags(dragFlags, swipeFlags); 69 | } 70 | 71 | @Override 72 | public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder source, RecyclerView.ViewHolder target) { 73 | if (source.getItemViewType() != target.getItemViewType()) { 74 | return false; 75 | } 76 | 77 | // Notify the adapter of the move 78 | mAdapter.onItemMove(source.getAdapterPosition(), target.getAdapterPosition()); 79 | return true; 80 | } 81 | 82 | 83 | // @Override 84 | // public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { 85 | // if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) { 86 | // // Fade out the view as it is swiped out of the parent's bounds 87 | // final float alpha = ALPHA_FULL - Math.abs(dX) / (float) viewHolder.itemView.getWidth(); 88 | // viewHolder.itemView.setAlpha(alpha); 89 | // viewHolder.itemView.setTranslationX(dX); 90 | // } else { 91 | // super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); 92 | // } 93 | // } 94 | 95 | // @Override 96 | // public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) { 97 | // // We only want the active item to change 98 | // if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) { 99 | // if (viewHolder instanceof ItemTouchHelperViewHolder) { 100 | // // Let the view holder know that this item is being moved or dragged 101 | // ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder; 102 | // itemViewHolder.onItemSelected(); 103 | // } 104 | // } 105 | // 106 | // super.onSelectedChanged(viewHolder, actionState); 107 | // } 108 | // 109 | // @Override 110 | // public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { 111 | // super.clearView(recyclerView, viewHolder); 112 | // 113 | // viewHolder.itemView.setAlpha(ALPHA_FULL); 114 | // 115 | // if (viewHolder instanceof ItemTouchHelperViewHolder) { 116 | // // Tell the view holder it's time to restore the idle state 117 | // ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder; 118 | // itemViewHolder.onItemClear(); 119 | // } 120 | // } 121 | } 122 | -------------------------------------------------------------------------------- /app/src/main/java/org/apache/cordova/device/Device.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | package org.apache.cordova.device; 20 | 21 | import java.util.TimeZone; 22 | 23 | import org.apache.cordova.CordovaWebView; 24 | import org.apache.cordova.CallbackContext; 25 | import org.apache.cordova.CordovaPlugin; 26 | import org.apache.cordova.CordovaInterface; 27 | import org.json.JSONArray; 28 | import org.json.JSONException; 29 | import org.json.JSONObject; 30 | 31 | import android.provider.Settings; 32 | 33 | public class Device extends CordovaPlugin { 34 | public static final String TAG = "Device"; 35 | 36 | public static String platform; // Device OS 37 | public static String uuid; // Device UUID 38 | 39 | private static final String ANDROID_PLATFORM = "Android"; 40 | private static final String AMAZON_PLATFORM = "amazon-fireos"; 41 | private static final String AMAZON_DEVICE = "Amazon"; 42 | 43 | /** 44 | * Constructor. 45 | */ 46 | public Device() { 47 | } 48 | 49 | /** 50 | * Sets the context of the Command. This can then be used to do things like 51 | * get file paths associated with the Activity. 52 | * 53 | * @param cordova The context of the main Activity. 54 | * @param webView The CordovaWebView Cordova is running in. 55 | */ 56 | public void initialize(CordovaInterface cordova, CordovaWebView webView) { 57 | super.initialize(cordova, webView); 58 | Device.uuid = getUuid(); 59 | } 60 | 61 | /** 62 | * Executes the request and returns PluginResult. 63 | * 64 | * @param action The action to execute. 65 | * @param args JSONArry of arguments for the plugin. 66 | * @param callbackContext The callback id used when calling back into JavaScript. 67 | * @return True if the action was valid, false if not. 68 | */ 69 | public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { 70 | if (action.equals("getDeviceInfo")) { 71 | JSONObject r = new JSONObject(); 72 | r.put("uuid", Device.uuid); 73 | r.put("version", this.getOSVersion()); 74 | r.put("platform", this.getPlatform()); 75 | r.put("model", this.getModel()); 76 | r.put("manufacturer", this.getManufacturer()); 77 | callbackContext.success(r); 78 | } 79 | else { 80 | return false; 81 | } 82 | return true; 83 | } 84 | 85 | //-------------------------------------------------------------------------- 86 | // LOCAL METHODS 87 | //-------------------------------------------------------------------------- 88 | 89 | /** 90 | * Get the OS name. 91 | * 92 | * @return 93 | */ 94 | public String getPlatform() { 95 | String platform; 96 | if (isAmazonDevice()) { 97 | platform = AMAZON_PLATFORM; 98 | } else { 99 | platform = ANDROID_PLATFORM; 100 | } 101 | return platform; 102 | } 103 | 104 | /** 105 | * Get the device's Universally Unique Identifier (UUID). 106 | * 107 | * @return 108 | */ 109 | public String getUuid() { 110 | String uuid = Settings.Secure.getString(this.cordova.getActivity().getContentResolver(), android.provider.Settings.Secure.ANDROID_ID); 111 | return uuid; 112 | } 113 | 114 | public String getModel() { 115 | String model = android.os.Build.MODEL; 116 | return model; 117 | } 118 | 119 | public String getProductName() { 120 | String productname = android.os.Build.PRODUCT; 121 | return productname; 122 | } 123 | 124 | public String getManufacturer() { 125 | String manufacturer = android.os.Build.MANUFACTURER; 126 | return manufacturer; 127 | } 128 | /** 129 | * Get the OS version. 130 | * 131 | * @return 132 | */ 133 | public String getOSVersion() { 134 | String osversion = android.os.Build.VERSION.RELEASE; 135 | return osversion; 136 | } 137 | 138 | public String getSDKVersion() { 139 | @SuppressWarnings("deprecation") 140 | String sdkversion = android.os.Build.VERSION.SDK; 141 | return sdkversion; 142 | } 143 | 144 | public String getTimeZoneID() { 145 | TimeZone tz = TimeZone.getDefault(); 146 | return (tz.getID()); 147 | } 148 | 149 | /** 150 | * Function to check if the device is manufactured by Amazon 151 | * 152 | * @return 153 | */ 154 | public boolean isAmazonDevice() { 155 | if (android.os.Build.MANUFACTURER.equals(AMAZON_DEVICE)) { 156 | return true; 157 | } 158 | return false; 159 | } 160 | 161 | } 162 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /app/src/main/java/org/apache/cordova/vibration/Vibration.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | package org.apache.cordova.vibration; 20 | 21 | import org.apache.cordova.CallbackContext; 22 | import org.apache.cordova.CordovaPlugin; 23 | import org.json.JSONArray; 24 | import org.json.JSONException; 25 | import android.content.Context; 26 | import android.os.Vibrator; 27 | import android.media.AudioManager; 28 | 29 | /** 30 | * This class provides access to vibration on the device. 31 | */ 32 | public class Vibration extends CordovaPlugin { 33 | 34 | /** 35 | * Constructor. 36 | */ 37 | public Vibration() { 38 | } 39 | 40 | /** 41 | * Executes the request and returns PluginResult. 42 | * 43 | * @param action The action to execute. 44 | * @param args JSONArray of arguments for the plugin. 45 | * @param callbackContext The callback context used when calling back into JavaScript. 46 | * @return True when the action was valid, false otherwise. 47 | */ 48 | public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { 49 | if (action.equals("vibrate")) { 50 | this.vibrate(args.getLong(0)); 51 | } 52 | else if (action.equals("vibrateWithPattern")) { 53 | JSONArray pattern = args.getJSONArray(0); 54 | int repeat = args.getInt(1); 55 | //add a 0 at the beginning of pattern to align with w3c 56 | long[] patternArray = new long[pattern.length()+1]; 57 | patternArray[0] = 0; 58 | for (int i = 0; i < pattern.length(); i++) { 59 | patternArray[i+1] = pattern.getLong(i); 60 | } 61 | this.vibrateWithPattern(patternArray, repeat); 62 | } 63 | else if (action.equals("cancelVibration")) { 64 | this.cancelVibration(); 65 | } 66 | else { 67 | return false; 68 | } 69 | 70 | // Only alert and confirm are async. 71 | callbackContext.success(); 72 | 73 | return true; 74 | } 75 | 76 | //-------------------------------------------------------------------------- 77 | // LOCAL METHODS 78 | //-------------------------------------------------------------------------- 79 | 80 | /** 81 | * Vibrates the device for a given amount of time. 82 | * 83 | * @param time Time to vibrate in ms. 84 | */ 85 | public void vibrate(long time) { 86 | // Start the vibration, 0 defaults to half a second. 87 | if (time == 0) { 88 | time = 500; 89 | } 90 | AudioManager manager = (AudioManager) this.cordova.getActivity().getSystemService(Context.AUDIO_SERVICE); 91 | if (manager.getRingerMode() != AudioManager.RINGER_MODE_SILENT) { 92 | Vibrator vibrator = (Vibrator) this.cordova.getActivity().getSystemService(Context.VIBRATOR_SERVICE); 93 | vibrator.vibrate(time); 94 | } 95 | } 96 | 97 | /** 98 | * Vibrates the device with a given pattern. 99 | * 100 | * @param pattern Pattern with which to vibrate the device. 101 | * Pass in an array of longs that 102 | * are the durations for which to 103 | * turn on or off the vibrator in 104 | * milliseconds. The first value 105 | * indicates the number of milliseconds 106 | * to wait before turning the vibrator 107 | * on. The next value indicates the 108 | * number of milliseconds for which 109 | * to keep the vibrator on before 110 | * turning it off. Subsequent values 111 | * alternate between durations in 112 | * milliseconds to turn the vibrator 113 | * off or to turn the vibrator on. 114 | * 115 | * @param repeat Optional index into the pattern array at which 116 | * to start repeating, or -1 for no repetition (default). 117 | */ 118 | public void vibrateWithPattern(long[] pattern, int repeat) { 119 | AudioManager manager = (AudioManager) this.cordova.getActivity().getSystemService(Context.AUDIO_SERVICE); 120 | if (manager.getRingerMode() != AudioManager.RINGER_MODE_SILENT) { 121 | Vibrator vibrator = (Vibrator) this.cordova.getActivity().getSystemService(Context.VIBRATOR_SERVICE); 122 | vibrator.vibrate(pattern, repeat); 123 | } 124 | } 125 | 126 | /** 127 | * Immediately cancels any currently running vibration. 128 | */ 129 | public void cancelVibration() { 130 | Vibrator vibrator = (Vibrator) this.cordova.getActivity().getSystemService(Context.VIBRATOR_SERVICE); 131 | vibrator.cancel(); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /app/src/main/java/org/apache/cordova/batterystatus/BatteryListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | package org.apache.cordova.batterystatus; 20 | 21 | import org.apache.cordova.CallbackContext; 22 | import org.apache.cordova.CordovaPlugin; 23 | import org.apache.cordova.PluginResult; 24 | import org.json.JSONArray; 25 | import org.json.JSONException; 26 | import org.json.JSONObject; 27 | 28 | import android.content.BroadcastReceiver; 29 | import android.content.Context; 30 | import android.content.Intent; 31 | import android.content.IntentFilter; 32 | import android.util.Log; 33 | 34 | public class BatteryListener extends CordovaPlugin { 35 | 36 | private static final String LOG_TAG = "BatteryManager"; 37 | 38 | BroadcastReceiver receiver; 39 | 40 | private CallbackContext batteryCallbackContext = null; 41 | 42 | /** 43 | * Constructor. 44 | */ 45 | public BatteryListener() { 46 | this.receiver = null; 47 | } 48 | 49 | /** 50 | * Executes the request. 51 | * 52 | * @param action The action to execute. 53 | * @param args JSONArry of arguments for the plugin. 54 | * @param callbackContext The callback context used when calling back into JavaScript. 55 | * @return True if the action was valid, false if not. 56 | */ 57 | public boolean execute(String action, JSONArray args, CallbackContext callbackContext) { 58 | if (action.equals("start")) { 59 | if (this.batteryCallbackContext != null) { 60 | callbackContext.error( "Battery listener already running."); 61 | return true; 62 | } 63 | this.batteryCallbackContext = callbackContext; 64 | 65 | // We need to listen to power events to update battery status 66 | IntentFilter intentFilter = new IntentFilter(); 67 | intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); 68 | if (this.receiver == null) { 69 | this.receiver = new BroadcastReceiver() { 70 | @Override 71 | public void onReceive(Context context, Intent intent) { 72 | updateBatteryInfo(intent); 73 | } 74 | }; 75 | webView.getContext().registerReceiver(this.receiver, intentFilter); 76 | } 77 | 78 | // Don't return any result now, since status results will be sent when events come in from broadcast receiver 79 | PluginResult pluginResult = new PluginResult(PluginResult.Status.NO_RESULT); 80 | pluginResult.setKeepCallback(true); 81 | callbackContext.sendPluginResult(pluginResult); 82 | return true; 83 | } 84 | 85 | else if (action.equals("stop")) { 86 | removeBatteryListener(); 87 | this.sendUpdate(new JSONObject(), false); // release status callback in JS side 88 | this.batteryCallbackContext = null; 89 | callbackContext.success(); 90 | return true; 91 | } 92 | 93 | return false; 94 | } 95 | 96 | /** 97 | * Stop battery receiver. 98 | */ 99 | public void onDestroy() { 100 | removeBatteryListener(); 101 | } 102 | 103 | /** 104 | * Stop battery receiver. 105 | */ 106 | public void onReset() { 107 | removeBatteryListener(); 108 | } 109 | 110 | /** 111 | * Stop the battery receiver and set it to null. 112 | */ 113 | private void removeBatteryListener() { 114 | if (this.receiver != null) { 115 | try { 116 | webView.getContext().unregisterReceiver(this.receiver); 117 | this.receiver = null; 118 | } catch (Exception e) { 119 | Log.e(LOG_TAG, "Error unregistering battery receiver: " + e.getMessage(), e); 120 | } 121 | } 122 | } 123 | 124 | /** 125 | * Creates a JSONObject with the current battery information 126 | * 127 | * @param batteryIntent the current battery information 128 | * @return a JSONObject containing the battery status information 129 | */ 130 | private JSONObject getBatteryInfo(Intent batteryIntent) { 131 | JSONObject obj = new JSONObject(); 132 | try { 133 | obj.put("level", batteryIntent.getIntExtra(android.os.BatteryManager.EXTRA_LEVEL, 0)); 134 | obj.put("isPlugged", batteryIntent.getIntExtra(android.os.BatteryManager.EXTRA_PLUGGED, -1) > 0 ? true : false); 135 | } catch (JSONException e) { 136 | Log.e(LOG_TAG, e.getMessage(), e); 137 | } 138 | return obj; 139 | } 140 | 141 | /** 142 | * Updates the JavaScript side whenever the battery changes 143 | * 144 | * @param batteryIntent the current battery information 145 | * @return 146 | */ 147 | private void updateBatteryInfo(Intent batteryIntent) { 148 | sendUpdate(this.getBatteryInfo(batteryIntent), true); 149 | } 150 | 151 | /** 152 | * Create a new plugin result and send it back to JavaScript 153 | * 154 | * @param connection the network info to set as navigator.connection 155 | */ 156 | private void sendUpdate(JSONObject info, boolean keepCallback) { 157 | if (this.batteryCallbackContext != null) { 158 | PluginResult result = new PluginResult(PluginResult.Status.OK, info); 159 | result.setKeepCallback(keepCallback); 160 | this.batteryCallbackContext.sendPluginResult(result); 161 | } 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /app/src/main/java/org/apache/cordova/statusbar/StatusBar.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | * 19 | */ 20 | package org.apache.cordova.statusbar; 21 | 22 | import android.app.Activity; 23 | import android.graphics.Color; 24 | import android.os.Build; 25 | import android.util.Log; 26 | import android.view.Window; 27 | import android.view.WindowManager; 28 | 29 | import org.apache.cordova.CallbackContext; 30 | import org.apache.cordova.CordovaArgs; 31 | import org.apache.cordova.CordovaInterface; 32 | import org.apache.cordova.CordovaPlugin; 33 | import org.apache.cordova.CordovaWebView; 34 | import org.apache.cordova.PluginResult; 35 | import org.json.JSONException; 36 | 37 | public class StatusBar extends CordovaPlugin { 38 | private static final String TAG = "StatusBar"; 39 | 40 | /** 41 | * Sets the context of the Command. This can then be used to do things like 42 | * get file paths associated with the Activity. 43 | * 44 | * @param cordova The context of the main Activity. 45 | * @param webView The CordovaWebView Cordova is running in. 46 | */ 47 | @Override 48 | public void initialize(final CordovaInterface cordova, CordovaWebView webView) { 49 | Log.v(TAG, "StatusBar: initialization"); 50 | super.initialize(cordova, webView); 51 | 52 | this.cordova.getActivity().runOnUiThread(new Runnable() { 53 | @Override 54 | public void run() { 55 | // Clear flag FLAG_FORCE_NOT_FULLSCREEN which is set initially 56 | // by the Cordova. 57 | Window window = cordova.getActivity().getWindow(); 58 | window.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); 59 | 60 | // Read 'StatusBarBackgroundColor' from config.xml, default is #000000. 61 | setStatusBarBackgroundColor(preferences.getString("StatusBarBackgroundColor", "#000000")); 62 | } 63 | }); 64 | } 65 | 66 | /** 67 | * Executes the request and returns PluginResult. 68 | * 69 | * @param action The action to execute. 70 | * @param args JSONArry of arguments for the plugin. 71 | * @param callbackContext The callback id used when calling back into JavaScript. 72 | * @return True if the action was valid, false otherwise. 73 | */ 74 | @Override 75 | public boolean execute(final String action, final CordovaArgs args, final CallbackContext callbackContext) throws JSONException { 76 | Log.v(TAG, "Executing action: " + action); 77 | final Activity activity = this.cordova.getActivity(); 78 | final Window window = activity.getWindow(); 79 | if ("_ready".equals(action)) { 80 | boolean statusBarVisible = (window.getAttributes().flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0; 81 | callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, statusBarVisible)); 82 | } 83 | 84 | if ("show".equals(action)) { 85 | this.cordova.getActivity().runOnUiThread(new Runnable() { 86 | @Override 87 | public void run() { 88 | window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); 89 | } 90 | }); 91 | return true; 92 | } 93 | 94 | if ("hide".equals(action)) { 95 | this.cordova.getActivity().runOnUiThread(new Runnable() { 96 | @Override 97 | public void run() { 98 | window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); 99 | } 100 | }); 101 | return true; 102 | } 103 | 104 | if ("backgroundColorByHexString".equals(action)) { 105 | this.cordova.getActivity().runOnUiThread(new Runnable() { 106 | @Override 107 | public void run() { 108 | try { 109 | setStatusBarBackgroundColor(args.getString(0)); 110 | } catch (JSONException ignore) { 111 | Log.e(TAG, "Invalid hexString argument, use f.i. '#777777'"); 112 | } 113 | } 114 | }); 115 | return true; 116 | } 117 | 118 | return false; 119 | } 120 | 121 | private void setStatusBarBackgroundColor(final String colorPref) { 122 | if (Build.VERSION.SDK_INT >= 21) { 123 | if (colorPref != null && !colorPref.isEmpty()) { 124 | final Window window = cordova.getActivity().getWindow(); 125 | // Method and constants not available on all SDKs but we want to be able to compile this code with any SDK 126 | window.clearFlags(0x04000000); // SDK 19: WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 127 | window.addFlags(0x80000000); // SDK 21: WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); 128 | try { 129 | // Using reflection makes sure any 5.0+ device will work without having to compile with SDK level 21 130 | window.getClass().getDeclaredMethod("setStatusBarColor", int.class).invoke(window, Color.parseColor(colorPref)); 131 | } catch (IllegalArgumentException ignore) { 132 | Log.e(TAG, "Invalid hexString argument, use f.i. '#999999'"); 133 | } catch (Exception ignore) { 134 | // this should not happen, only in case Android removes this method in a version > 21 135 | Log.w(TAG, "Method window.setStatusBarColor not found for SDK level " + Build.VERSION.SDK_INT); 136 | } 137 | } 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | package org.apache.cordova.whitelist; 21 | 22 | import org.apache.cordova.CordovaPlugin; 23 | import org.apache.cordova.ConfigXmlParser; 24 | import org.apache.cordova.Whitelist; 25 | import org.xmlpull.v1.XmlPullParser; 26 | 27 | import android.content.Context; 28 | import android.util.Log; 29 | 30 | public class WhitelistPlugin extends CordovaPlugin { 31 | private static final String LOG_TAG = "WhitelistPlugin"; 32 | private Whitelist allowedNavigations; 33 | private Whitelist allowedIntents; 34 | private Whitelist allowedRequests; 35 | 36 | // Used when instantiated via reflection by PluginManager 37 | public WhitelistPlugin() { 38 | } 39 | // These can be used by embedders to allow Java-configuration of whitelists. 40 | public WhitelistPlugin(Context context) { 41 | this(new Whitelist(), new Whitelist(), null); 42 | new CustomConfigXmlParser().parse(context); 43 | } 44 | public WhitelistPlugin(XmlPullParser xmlParser) { 45 | this(new Whitelist(), new Whitelist(), null); 46 | new CustomConfigXmlParser().parse(xmlParser); 47 | } 48 | public WhitelistPlugin(Whitelist allowedNavigations, Whitelist allowedIntents, Whitelist allowedRequests) { 49 | if (allowedRequests == null) { 50 | allowedRequests = new Whitelist(); 51 | allowedRequests.addWhiteListEntry("file:///*", false); 52 | allowedRequests.addWhiteListEntry("data:*", false); 53 | } 54 | this.allowedNavigations = allowedNavigations; 55 | this.allowedIntents = allowedIntents; 56 | this.allowedRequests = allowedRequests; 57 | } 58 | @Override 59 | public void pluginInitialize() { 60 | if (allowedNavigations == null) { 61 | allowedNavigations = new Whitelist(); 62 | allowedIntents = new Whitelist(); 63 | allowedRequests = new Whitelist(); 64 | new CustomConfigXmlParser().parse(webView.getContext()); 65 | } 66 | } 67 | 68 | private class CustomConfigXmlParser extends ConfigXmlParser { 69 | @Override 70 | public void handleStartTag(XmlPullParser xml) { 71 | String strNode = xml.getName(); 72 | if (strNode.equals("content")) { 73 | String startPage = xml.getAttributeValue(null, "src"); 74 | allowedNavigations.addWhiteListEntry(startPage, false); 75 | } else if (strNode.equals("allow-navigation")) { 76 | String origin = xml.getAttributeValue(null, "href"); 77 | if ("*".equals(origin)) { 78 | allowedNavigations.addWhiteListEntry("http://*/*", false); 79 | allowedNavigations.addWhiteListEntry("https://*/*", false); 80 | allowedNavigations.addWhiteListEntry("data:*", false); 81 | } else { 82 | allowedNavigations.addWhiteListEntry(origin, false); 83 | } 84 | } else if (strNode.equals("allow-intent")) { 85 | String origin = xml.getAttributeValue(null, "href"); 86 | allowedIntents.addWhiteListEntry(origin, false); 87 | } else if (strNode.equals("access")) { 88 | String origin = xml.getAttributeValue(null, "origin"); 89 | String subdomains = xml.getAttributeValue(null, "subdomains"); 90 | boolean external = (xml.getAttributeValue(null, "launch-external") != null); 91 | if (origin != null) { 92 | if (external) { 93 | Log.w(LOG_TAG, "Found within config.xml. Please use instead."); 94 | allowedIntents.addWhiteListEntry(origin, (subdomains != null) && (subdomains.compareToIgnoreCase("true") == 0)); 95 | } else { 96 | if ("*".equals(origin)) { 97 | allowedRequests.addWhiteListEntry("http://*/*", false); 98 | allowedRequests.addWhiteListEntry("https://*/*", false); 99 | } else { 100 | allowedRequests.addWhiteListEntry(origin, (subdomains != null) && (subdomains.compareToIgnoreCase("true") == 0)); 101 | } 102 | } 103 | } 104 | } 105 | } 106 | @Override 107 | public void handleEndTag(XmlPullParser xml) { 108 | } 109 | } 110 | 111 | @Override 112 | public Boolean shouldAllowNavigation(String url) { 113 | if (allowedNavigations.isUrlWhiteListed(url)) { 114 | return true; 115 | } 116 | return null; // Default policy 117 | } 118 | 119 | @Override 120 | public Boolean shouldAllowRequest(String url) { 121 | if (Boolean.TRUE == shouldAllowNavigation(url)) { 122 | return true; 123 | } 124 | if (allowedRequests.isUrlWhiteListed(url)) { 125 | return true; 126 | } 127 | return null; // Default policy 128 | } 129 | 130 | @Override 131 | public Boolean shouldOpenExternalUrl(String url) { 132 | if (allowedIntents.isUrlWhiteListed(url)) { 133 | return true; 134 | } 135 | return null; // Default policy 136 | } 137 | 138 | public Whitelist getAllowedNavigations() { 139 | return allowedNavigations; 140 | } 141 | 142 | public void setAllowedNavigations(Whitelist allowedNavigations) { 143 | this.allowedNavigations = allowedNavigations; 144 | } 145 | 146 | public Whitelist getAllowedIntents() { 147 | return allowedIntents; 148 | } 149 | 150 | public void setAllowedIntents(Whitelist allowedIntents) { 151 | this.allowedIntents = allowedIntents; 152 | } 153 | 154 | public Whitelist getAllowedRequests() { 155 | return allowedRequests; 156 | } 157 | 158 | public void setAllowedRequests(Whitelist allowedRequests) { 159 | this.allowedRequests = allowedRequests; 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /app/src/main/java/io/syng/fragment/profile/ProfileDialogFragment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Jarrad Hope 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | package io.syng.fragment.profile; 10 | 11 | import android.app.Dialog; 12 | import android.graphics.drawable.Drawable; 13 | import android.os.Bundle; 14 | import android.support.annotation.Nullable; 15 | import android.support.design.widget.TabLayout; 16 | import android.support.v4.app.DialogFragment; 17 | import android.support.v4.graphics.drawable.DrawableCompat; 18 | import android.support.v4.view.ViewPager; 19 | import android.support.v4.view.ViewPager.OnPageChangeListener; 20 | import android.support.v7.widget.Toolbar; 21 | import android.support.v7.widget.Toolbar.OnMenuItemClickListener; 22 | import android.view.LayoutInflater; 23 | import android.view.MenuItem; 24 | import android.view.View; 25 | import android.view.View.OnClickListener; 26 | import android.view.ViewGroup; 27 | import android.view.Window; 28 | import android.widget.Toast; 29 | 30 | import io.syng.R; 31 | import io.syng.adapter.ProfileViewPagerAdapter; 32 | import io.syng.entity.Profile; 33 | import io.syng.util.GeneralUtil; 34 | import io.syng.util.ProfileManager; 35 | 36 | public class ProfileDialogFragment extends DialogFragment implements OnPageChangeListener, 37 | OnClickListener, OnMenuItemClickListener { 38 | 39 | private static final String ARG_PROFILE_ID = "profile"; 40 | 41 | private ViewPager mViewPager; 42 | private Toolbar mToolbar; 43 | private String mProfileId; 44 | 45 | public static ProfileDialogFragment newInstance(final Profile profile) { 46 | Bundle bundle = new Bundle(); 47 | bundle.putString(ARG_PROFILE_ID, profile.getId()); 48 | ProfileDialogFragment dialogFragment = new ProfileDialogFragment(); 49 | dialogFragment.setArguments(bundle); 50 | return dialogFragment; 51 | } 52 | 53 | @Override 54 | public void onCreate(@Nullable Bundle savedInstanceState) { 55 | super.onCreate(savedInstanceState); 56 | setRetainInstance(true); 57 | mProfileId = getArguments().getString(ARG_PROFILE_ID); 58 | } 59 | 60 | @Override 61 | public Dialog onCreateDialog(Bundle savedInstanceState) { 62 | Dialog dialog = super.onCreateDialog(savedInstanceState); 63 | dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE); 64 | return dialog; 65 | } 66 | 67 | @Nullable 68 | @Override 69 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 70 | View view = inflater.inflate(R.layout.profile_edit_dialog, container); 71 | TabLayout tabLayout = (TabLayout) view.findViewById(R.id.profile_tabs); 72 | mViewPager = (ViewPager) view.findViewById(R.id.profile_view_pager); 73 | 74 | mViewPager.addOnPageChangeListener(this); 75 | mToolbar = (Toolbar) view.findViewById(R.id.profile_toolbar); 76 | mToolbar.setTitle("Edit Profile"); 77 | mToolbar.inflateMenu(R.menu.profile_menu); 78 | 79 | MenuItem exportProfile = mToolbar.getMenu().findItem(R.id.action_key_export); 80 | exportProfile.setVisible(false); 81 | exportProfile.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { 82 | @Override 83 | public boolean onMenuItemClick(MenuItem menuItem) { 84 | return false; 85 | } 86 | }); 87 | MenuItem importProfile = mToolbar.getMenu().findItem(R.id.action_key_import); 88 | importProfile.setVisible(false); 89 | importProfile.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { 90 | @Override 91 | public boolean onMenuItemClick(MenuItem menuItem) { 92 | GeneralUtil.showProfileImportDialog(getActivity()); 93 | return false; 94 | } 95 | }); 96 | 97 | mToolbar.setNavigationIcon(R.drawable.ic_arrow_back_black_24dp); 98 | mToolbar.setNavigationOnClickListener(this); 99 | mToolbar.setOnMenuItemClickListener(this); 100 | tintMenuItem(); 101 | 102 | mViewPager.setAdapter(new ProfileViewPagerAdapter(getChildFragmentManager(), getActivity(), mProfileId)); 103 | tabLayout.setupWithViewPager(mViewPager); 104 | 105 | return view; 106 | } 107 | 108 | private void tintMenuItem() { 109 | Drawable drawable1 = mToolbar.getMenu().findItem(R.id.action_key_export).getIcon(); 110 | drawable1 = DrawableCompat.wrap(drawable1); 111 | DrawableCompat.setTint(drawable1, getResources().getColor(R.color.drawer_icon_color)); 112 | mToolbar.getMenu().findItem(R.id.action_key_export).setIcon(drawable1); 113 | 114 | Drawable drawable2 = mToolbar.getMenu().findItem(R.id.action_key_import).getIcon(); 115 | drawable2 = DrawableCompat.wrap(drawable2); 116 | DrawableCompat.setTint(drawable2, getResources().getColor(R.color.drawer_icon_color)); 117 | mToolbar.getMenu().findItem(R.id.action_key_import).setIcon(drawable2); 118 | 119 | Drawable drawable3 = mToolbar.getMenu().findItem(R.id.action_remove).getIcon(); 120 | drawable3 = DrawableCompat.wrap(drawable3); 121 | DrawableCompat.setTint(drawable3, getResources().getColor(R.color.drawer_icon_color)); 122 | mToolbar.getMenu().findItem(R.id.action_remove).setIcon(drawable3); 123 | } 124 | 125 | @Override 126 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 127 | } 128 | 129 | @Override 130 | public void onPageSelected(int position) { 131 | invalidateToolbarMenu(); 132 | } 133 | 134 | @Override 135 | public void onPageScrollStateChanged(int state) { 136 | } 137 | 138 | private void invalidateToolbarMenu() { 139 | MenuItem exp = mToolbar.getMenu().findItem(R.id.action_key_export); 140 | MenuItem imp = mToolbar.getMenu().findItem(R.id.action_key_import); 141 | boolean showExport = mViewPager.getCurrentItem() == ProfileViewPagerAdapter.KEYS_POSITION; 142 | exp.setVisible(showExport); 143 | imp.setVisible(showExport); 144 | } 145 | 146 | @Override 147 | public boolean onMenuItemClick(MenuItem item) { 148 | switch (item.getItemId()) { 149 | case R.id.action_remove: 150 | Profile profile = ProfileManager.getProfileById(mProfileId); 151 | if (ProfileManager.removeProfile(profile)) { 152 | ProfileDialogFragment.this.dismiss(); 153 | } else { 154 | Toast.makeText(getActivity(), "Can't remove current account", Toast.LENGTH_SHORT).show(); 155 | } 156 | 157 | return true; 158 | } 159 | return false; 160 | } 161 | 162 | @Override 163 | public void onClick(View v) { 164 | dismiss(); 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /app/src/main/java/io/syng/util/ProfileManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Jarrad Hope 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | package io.syng.util; 10 | 11 | import android.support.annotation.DrawableRes; 12 | import android.support.annotation.Nullable; 13 | 14 | import java.util.ArrayList; 15 | import java.util.Collections; 16 | import java.util.List; 17 | 18 | import io.syng.app.SyngApplication; 19 | import io.syng.entity.Dapp; 20 | import io.syng.entity.Profile; 21 | 22 | public final class ProfileManager { 23 | 24 | public interface ProfilesChangeListener { 25 | void onProfilesChange(); 26 | } 27 | 28 | private static ProfileManager sInstance; 29 | 30 | private ProfilesChangeListener mProfilesChangeListener; 31 | 32 | public static void initialize() { 33 | if (sInstance != null) { 34 | throw new IllegalStateException("ProfileManager have already been initialized"); 35 | } 36 | sInstance = new ProfileManager(); 37 | } 38 | 39 | private static ProfileManager getInstance() { 40 | if (sInstance == null) { 41 | throw new IllegalStateException("ProfileManager should be initialized first"); 42 | } 43 | return sInstance; 44 | } 45 | 46 | @SuppressWarnings("unchecked") 47 | public static ArrayList getProfiles() { 48 | return PrefsUtil.getProfiles(); 49 | } 50 | 51 | public static void addProfile(Profile profile) { 52 | ArrayList profiles = PrefsUtil.getProfiles(); 53 | profiles.add(profile); 54 | PrefsUtil.saveProfiles(profiles); 55 | notifyListener(); 56 | } 57 | 58 | public static boolean removeProfile(Profile profile) { 59 | boolean removed = !profile.equals(ProfileManager.getCurrentProfile()); 60 | if (removed) { 61 | ArrayList profiles = PrefsUtil.getProfiles(); 62 | profiles.remove(profile); 63 | PrefsUtil.saveProfiles(profiles); 64 | notifyListener(); 65 | } 66 | return removed; 67 | } 68 | 69 | public static void updateProfile(Profile profile) { 70 | ArrayList profiles = getProfiles(); 71 | for (Profile item : profiles) { 72 | if (item.getId().equals(profile.getId())) { 73 | int index = profiles.indexOf(item); 74 | profiles.set(index, profile); 75 | PrefsUtil.saveProfiles(profiles); 76 | break; 77 | } 78 | } 79 | notifyListener(); 80 | } 81 | 82 | public static Profile getCurrentProfile() { 83 | // Add default cow account if not present 84 | // if (ProfileManager.getProfiles().isEmpty()) { 85 | // Profile profile = new Profile(); 86 | // profile.setName("Cow"); 87 | // // Add default cow and monkey addresses 88 | // List addresses = new ArrayList<>(); 89 | // byte[] cowAddr = HashUtil.sha3("cow".getBytes()); 90 | // addresses.add(Hex.toHexString(cowAddr)); 91 | // String secret = CONFIG.coinbaseSecret(); 92 | // byte[] cbAddr = HashUtil.sha3(secret.getBytes()); 93 | // addresses.add(Hex.toHexString(cbAddr)); 94 | // profile.setPrivateKeys(addresses); 95 | // profile.setPassword("qw"); 96 | // ProfileManager.addProfile(profile); 97 | // ProfileManager.setCurrentProfile(profile); 98 | // return profile; 99 | // } 100 | 101 | List profiles = ProfileManager.getProfiles(); 102 | String currentProfileId = PrefsUtil.getCurrentProfileId(); 103 | 104 | for (int i = 0; i < profiles.size(); i++) { 105 | if (currentProfileId.equals(profiles.get(i).getId())) { 106 | return profiles.get(i); 107 | } 108 | } 109 | 110 | return new Profile(); 111 | } 112 | 113 | public static void setCurrentProfile(Profile profile, String password) { 114 | List privateKeys = profile.getPrivateKeys(password); 115 | SyngApplication.sEthereumConnector.init(privateKeys); 116 | PrefsUtil.setCurrentProfileId(profile.getId()); 117 | notifyListener(); 118 | } 119 | 120 | public static void addDAppToProfile(Profile profile, Dapp dapp) { 121 | profile.addDapp(dapp); 122 | ProfileManager.updateProfile(profile); 123 | notifyListener(); 124 | } 125 | 126 | public static void removeDAppInProfile(Profile profile, Dapp dapp) { 127 | profile.removeDapp(dapp); 128 | ProfileManager.updateProfile(profile); 129 | notifyListener(); 130 | } 131 | 132 | public static void updateDAppInProfile(Profile profile, Dapp dapp) { 133 | profile.updateDapp(dapp); 134 | ProfileManager.updateProfile(profile); 135 | notifyListener(); 136 | } 137 | 138 | public static void reorderDAppsInProfile(Profile profile, int fromPosition, int toPosition) { 139 | List dapps = profile.getDapps(); 140 | Collections.swap(dapps, fromPosition, toPosition); 141 | profile.setDapps(dapps); 142 | 143 | ArrayList profiles = getProfiles(); 144 | for (Profile item : profiles) { 145 | if (item.getId().equals(profile.getId())) { 146 | int index = profiles.indexOf(item); 147 | profiles.set(index, profile); 148 | PrefsUtil.saveProfiles(profiles); 149 | break; 150 | } 151 | } 152 | } 153 | 154 | public static void reorderProfiles(int fromPosition, int toPosition) { 155 | List profiles = ProfileManager.getProfiles(); 156 | Collections.swap(profiles, fromPosition, toPosition); 157 | PrefsUtil.saveProfiles(new ArrayList<>(profiles)); 158 | } 159 | 160 | @Nullable 161 | public static Profile getProfileById(String profileId) { 162 | List profiles = ProfileManager.getProfiles(); 163 | for (Profile profile : profiles) { 164 | if (profile.getId().equals(profileId)) { 165 | return profile; 166 | } 167 | } 168 | return null; 169 | } 170 | 171 | public static void setCurrentProfileBackgroundResourceId(@DrawableRes int resourceId) { 172 | PrefsUtil.setBackgroundResourceId(ProfileManager.getCurrentProfile().getId(), resourceId); 173 | notifyListener(); 174 | } 175 | 176 | public static int getCurrentProfileBackgroundResourceId() { 177 | return PrefsUtil.getBackgroundResourceId(ProfileManager.getCurrentProfile().getId()); 178 | } 179 | 180 | public static void setProfilesChangeListener(ProfilesChangeListener listener) { 181 | getInstance().mProfilesChangeListener = listener; 182 | } 183 | 184 | public static void removeProfilesChangeListener(ProfilesChangeListener listener) { 185 | getInstance().mProfilesChangeListener = null; 186 | } 187 | 188 | private static void notifyListener() { 189 | if (getInstance().mProfilesChangeListener != null) { 190 | getInstance().mProfilesChangeListener.onProfilesChange(); 191 | } 192 | } 193 | 194 | } 195 | -------------------------------------------------------------------------------- /app/src/main/java/org/apache/cordova/contacts/ContactAccessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.apache.cordova.contacts; 18 | 19 | import java.util.HashMap; 20 | 21 | import android.util.Log; 22 | import org.apache.cordova.CordovaInterface; 23 | import org.json.JSONArray; 24 | import org.json.JSONException; 25 | import org.json.JSONObject; 26 | 27 | /** 28 | * This abstract class defines SDK-independent API for communication with 29 | * Contacts Provider. The actual implementation used by the application depends 30 | * on the level of API available on the device. If the API level is Cupcake or 31 | * Donut, we want to use the {@link ContactAccessorSdk3_4} class. If it is 32 | * Eclair or higher, we want to use {@link ContactAccessorSdk5}. 33 | */ 34 | public abstract class ContactAccessor { 35 | 36 | protected final String LOG_TAG = "ContactsAccessor"; 37 | protected CordovaInterface mApp; 38 | 39 | /** 40 | * Check to see if the data associated with the key is required to 41 | * be populated in the Contact object. 42 | * @param key 43 | * @param map created by running buildPopulationSet. 44 | * @return true if the key data is required 45 | */ 46 | protected boolean isRequired(String key, HashMap map) { 47 | Boolean retVal = map.get(key); 48 | return (retVal == null) ? false : retVal.booleanValue(); 49 | } 50 | 51 | /** 52 | * Create a hash map of what data needs to be populated in the Contact object 53 | * @param fields the list of fields to populate 54 | * @return the hash map of required data 55 | */ 56 | protected HashMap buildPopulationSet(JSONObject options) { 57 | HashMap map = new HashMap(); 58 | 59 | String key; 60 | try { 61 | JSONArray desiredFields = null; 62 | if (options!=null && options.has("desiredFields")) { 63 | desiredFields = options.getJSONArray("desiredFields"); 64 | } 65 | if (desiredFields == null || desiredFields.length() == 0) { 66 | map.put("displayName", true); 67 | map.put("name", true); 68 | map.put("nickname", true); 69 | map.put("phoneNumbers", true); 70 | map.put("emails", true); 71 | map.put("addresses", true); 72 | map.put("ims", true); 73 | map.put("organizations", true); 74 | map.put("birthday", true); 75 | map.put("note", true); 76 | map.put("urls", true); 77 | map.put("photos", true); 78 | map.put("categories", true); 79 | } else { 80 | for (int i = 0; i < desiredFields.length(); i++) { 81 | key = desiredFields.getString(i); 82 | if (key.startsWith("displayName")) { 83 | map.put("displayName", true); 84 | } else if (key.startsWith("name")) { 85 | map.put("displayName", true); 86 | map.put("name", true); 87 | } else if (key.startsWith("nickname")) { 88 | map.put("nickname", true); 89 | } else if (key.startsWith("phoneNumbers")) { 90 | map.put("phoneNumbers", true); 91 | } else if (key.startsWith("emails")) { 92 | map.put("emails", true); 93 | } else if (key.startsWith("addresses")) { 94 | map.put("addresses", true); 95 | } else if (key.startsWith("ims")) { 96 | map.put("ims", true); 97 | } else if (key.startsWith("organizations")) { 98 | map.put("organizations", true); 99 | } else if (key.startsWith("birthday")) { 100 | map.put("birthday", true); 101 | } else if (key.startsWith("note")) { 102 | map.put("note", true); 103 | } else if (key.startsWith("urls")) { 104 | map.put("urls", true); 105 | } else if (key.startsWith("photos")) { 106 | map.put("photos", true); 107 | } else if (key.startsWith("categories")) { 108 | map.put("categories", true); 109 | } 110 | } 111 | } 112 | } catch (JSONException e) { 113 | Log.e(LOG_TAG, e.getMessage(), e); 114 | } 115 | return map; 116 | } 117 | 118 | /** 119 | * Convenience method to get a string from a JSON object. Saves a 120 | * lot of try/catch writing. 121 | * If the property is not found in the object null will be returned. 122 | * 123 | * @param obj contact object to search 124 | * @param property to be looked up 125 | * @return The value of the property 126 | */ 127 | protected String getJsonString(JSONObject obj, String property) { 128 | String value = null; 129 | try { 130 | if (obj != null) { 131 | value = obj.getString(property); 132 | if (value.equals("null")) { 133 | Log.d(LOG_TAG, property + " is string called 'null'"); 134 | value = null; 135 | } 136 | } 137 | } 138 | catch (JSONException e) { 139 | Log.d(LOG_TAG, "Could not get = " + e.getMessage()); 140 | } 141 | return value; 142 | } 143 | 144 | /** 145 | * Handles adding a JSON Contact object into the database. 146 | * @return TODO 147 | */ 148 | public abstract String save(JSONObject contact); 149 | 150 | /** 151 | * Handles searching through SDK-specific contacts API. 152 | */ 153 | public abstract JSONArray search(JSONArray filter, JSONObject options); 154 | 155 | /** 156 | * Handles searching through SDK-specific contacts API. 157 | * @throws JSONException 158 | */ 159 | public abstract JSONObject getContactById(String id) throws JSONException; 160 | 161 | /** 162 | * Handles searching through SDK-specific contacts API. 163 | * @param desiredFields fields that will filled. All fields will be filled if null 164 | * @throws JSONException 165 | */ 166 | public abstract JSONObject getContactById(String id, JSONArray desiredFields) throws JSONException; 167 | 168 | /** 169 | * Handles removing a contact from the database. 170 | */ 171 | public abstract boolean remove(String id); 172 | 173 | /** 174 | * A class that represents the where clause to be used in the database query 175 | */ 176 | class WhereOptions { 177 | private String where; 178 | private String[] whereArgs; 179 | public void setWhere(String where) { 180 | this.where = where; 181 | } 182 | public String getWhere() { 183 | return where; 184 | } 185 | public void setWhereArgs(String[] whereArgs) { 186 | this.whereArgs = whereArgs; 187 | } 188 | public String[] getWhereArgs() { 189 | return whereArgs; 190 | } 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /app/src/main/java/org/apache/cordova/camera/ExifHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | package org.apache.cordova.camera; 20 | 21 | import java.io.IOException; 22 | 23 | import android.media.ExifInterface; 24 | 25 | public class ExifHelper { 26 | private String aperture = null; 27 | private String datetime = null; 28 | private String exposureTime = null; 29 | private String flash = null; 30 | private String focalLength = null; 31 | private String gpsAltitude = null; 32 | private String gpsAltitudeRef = null; 33 | private String gpsDateStamp = null; 34 | private String gpsLatitude = null; 35 | private String gpsLatitudeRef = null; 36 | private String gpsLongitude = null; 37 | private String gpsLongitudeRef = null; 38 | private String gpsProcessingMethod = null; 39 | private String gpsTimestamp = null; 40 | private String iso = null; 41 | private String make = null; 42 | private String model = null; 43 | private String orientation = null; 44 | private String whiteBalance = null; 45 | 46 | private ExifInterface inFile = null; 47 | private ExifInterface outFile = null; 48 | 49 | /** 50 | * The file before it is compressed 51 | * 52 | * @param filePath 53 | * @throws IOException 54 | */ 55 | public void createInFile(String filePath) throws IOException { 56 | this.inFile = new ExifInterface(filePath); 57 | } 58 | 59 | /** 60 | * The file after it has been compressed 61 | * 62 | * @param filePath 63 | * @throws IOException 64 | */ 65 | public void createOutFile(String filePath) throws IOException { 66 | this.outFile = new ExifInterface(filePath); 67 | } 68 | 69 | /** 70 | * Reads all the EXIF data from the input file. 71 | */ 72 | public void readExifData() { 73 | this.aperture = inFile.getAttribute(ExifInterface.TAG_APERTURE); 74 | this.datetime = inFile.getAttribute(ExifInterface.TAG_DATETIME); 75 | this.exposureTime = inFile.getAttribute(ExifInterface.TAG_EXPOSURE_TIME); 76 | this.flash = inFile.getAttribute(ExifInterface.TAG_FLASH); 77 | this.focalLength = inFile.getAttribute(ExifInterface.TAG_FOCAL_LENGTH); 78 | this.gpsAltitude = inFile.getAttribute(ExifInterface.TAG_GPS_ALTITUDE); 79 | this.gpsAltitudeRef = inFile.getAttribute(ExifInterface.TAG_GPS_ALTITUDE_REF); 80 | this.gpsDateStamp = inFile.getAttribute(ExifInterface.TAG_GPS_DATESTAMP); 81 | this.gpsLatitude = inFile.getAttribute(ExifInterface.TAG_GPS_LATITUDE); 82 | this.gpsLatitudeRef = inFile.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF); 83 | this.gpsLongitude = inFile.getAttribute(ExifInterface.TAG_GPS_LONGITUDE); 84 | this.gpsLongitudeRef = inFile.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF); 85 | this.gpsProcessingMethod = inFile.getAttribute(ExifInterface.TAG_GPS_PROCESSING_METHOD); 86 | this.gpsTimestamp = inFile.getAttribute(ExifInterface.TAG_GPS_TIMESTAMP); 87 | this.iso = inFile.getAttribute(ExifInterface.TAG_ISO); 88 | this.make = inFile.getAttribute(ExifInterface.TAG_MAKE); 89 | this.model = inFile.getAttribute(ExifInterface.TAG_MODEL); 90 | this.orientation = inFile.getAttribute(ExifInterface.TAG_ORIENTATION); 91 | this.whiteBalance = inFile.getAttribute(ExifInterface.TAG_WHITE_BALANCE); 92 | } 93 | 94 | /** 95 | * Writes the previously stored EXIF data to the output file. 96 | * 97 | * @throws IOException 98 | */ 99 | public void writeExifData() throws IOException { 100 | // Don't try to write to a null file 101 | if (this.outFile == null) { 102 | return; 103 | } 104 | 105 | if (this.aperture != null) { 106 | this.outFile.setAttribute(ExifInterface.TAG_APERTURE, this.aperture); 107 | } 108 | if (this.datetime != null) { 109 | this.outFile.setAttribute(ExifInterface.TAG_DATETIME, this.datetime); 110 | } 111 | if (this.exposureTime != null) { 112 | this.outFile.setAttribute(ExifInterface.TAG_EXPOSURE_TIME, this.exposureTime); 113 | } 114 | if (this.flash != null) { 115 | this.outFile.setAttribute(ExifInterface.TAG_FLASH, this.flash); 116 | } 117 | if (this.focalLength != null) { 118 | this.outFile.setAttribute(ExifInterface.TAG_FOCAL_LENGTH, this.focalLength); 119 | } 120 | if (this.gpsAltitude != null) { 121 | this.outFile.setAttribute(ExifInterface.TAG_GPS_ALTITUDE, this.gpsAltitude); 122 | } 123 | if (this.gpsAltitudeRef != null) { 124 | this.outFile.setAttribute(ExifInterface.TAG_GPS_ALTITUDE_REF, this.gpsAltitudeRef); 125 | } 126 | if (this.gpsDateStamp != null) { 127 | this.outFile.setAttribute(ExifInterface.TAG_GPS_DATESTAMP, this.gpsDateStamp); 128 | } 129 | if (this.gpsLatitude != null) { 130 | this.outFile.setAttribute(ExifInterface.TAG_GPS_LATITUDE, this.gpsLatitude); 131 | } 132 | if (this.gpsLatitudeRef != null) { 133 | this.outFile.setAttribute(ExifInterface.TAG_GPS_LATITUDE_REF, this.gpsLatitudeRef); 134 | } 135 | if (this.gpsLongitude != null) { 136 | this.outFile.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, this.gpsLongitude); 137 | } 138 | if (this.gpsLongitudeRef != null) { 139 | this.outFile.setAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF, this.gpsLongitudeRef); 140 | } 141 | if (this.gpsProcessingMethod != null) { 142 | this.outFile.setAttribute(ExifInterface.TAG_GPS_PROCESSING_METHOD, this.gpsProcessingMethod); 143 | } 144 | if (this.gpsTimestamp != null) { 145 | this.outFile.setAttribute(ExifInterface.TAG_GPS_TIMESTAMP, this.gpsTimestamp); 146 | } 147 | if (this.iso != null) { 148 | this.outFile.setAttribute(ExifInterface.TAG_ISO, this.iso); 149 | } 150 | if (this.make != null) { 151 | this.outFile.setAttribute(ExifInterface.TAG_MAKE, this.make); 152 | } 153 | if (this.model != null) { 154 | this.outFile.setAttribute(ExifInterface.TAG_MODEL, this.model); 155 | } 156 | if (this.orientation != null) { 157 | this.outFile.setAttribute(ExifInterface.TAG_ORIENTATION, this.orientation); 158 | } 159 | if (this.whiteBalance != null) { 160 | this.outFile.setAttribute(ExifInterface.TAG_WHITE_BALANCE, this.whiteBalance); 161 | } 162 | 163 | this.outFile.saveAttributes(); 164 | } 165 | 166 | public int getOrientation() { 167 | int o = Integer.parseInt(this.orientation); 168 | 169 | if (o == ExifInterface.ORIENTATION_NORMAL) { 170 | return 0; 171 | } else if (o == ExifInterface.ORIENTATION_ROTATE_90) { 172 | return 90; 173 | } else if (o == ExifInterface.ORIENTATION_ROTATE_180) { 174 | return 180; 175 | } else if (o == ExifInterface.ORIENTATION_ROTATE_270) { 176 | return 270; 177 | } else { 178 | return 0; 179 | } 180 | } 181 | 182 | public void resetOrientation() { 183 | this.orientation = "" + ExifInterface.ORIENTATION_NORMAL; 184 | } 185 | } 186 | --------------------------------------------------------------------------------