diff --git a/.gitignore b/.gitignore index f6b286c..81d4b50 100644 --- a/.gitignore +++ b/.gitignore @@ -34,7 +34,7 @@ captures/ # Intellij *.iml -.idea/workspace.xml +.idea/ # Keystore files *.jks diff --git a/README.md b/README.md index 79ed307..e1dc49b 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,106 @@ -# android-about-box -Modern About Box for an Android App +[![Circle CI](https://circleci.com/gh/eggheadgames/android-about-box.svg?style=svg)](https://circleci.com/gh/eggheadgames/android-about-box) +[![Release](https://jitpack.io/v/eggheadgames/android-about-box.svg)](https://jitpack.io/#eggheadgames/android-about-box) + +# About Box +A modern About Box for an Android App built on the [daniel-stoneuk/material-about-library](https://github.com/daniel-stoneuk/material-about-library). + +### Easily display the common items of an About Box in a modern Android friendly way + +## About + +Android About Box is configured with a set of (mostly) strings for the company name, twitter and Facebook accounts, website, and filenames to html files for help files, privacy policy etc. + +When triggered from a menu item, it will display the app name, icon and version, provide links to contact support, leave a review, share the app, go to other apps by the same company in the app store -- as well as links to Facebook etc. + +## Installation Instructions + +Add the JitPack.io repository to your root `build.gradle`: + +```gradle +allprojects { + repositories { + maven { url "https://jitpack.io" } + } +} +``` + +Add a dependency to your application related `build.gradle` + +```gradle +dependencies { + compile 'com.github.eggheadgames:android-about-box:' +} +``` + +## Example +### Setup Branch.io + +Branch.io integration can be found [here](https://github.com/BranchMetrics/android-branch-deep-linking) + +### Setup AboutBox + +Add AboutBox configuration to your Application class + +```java + AboutConfig aboutConfig = AboutConfig.getInstance(); + aboutConfig.appName = getString(R.string.app_name); + aboutConfig.appIcon = R.mipmap.ic_launcher; + aboutConfig.version = "1.0.0"; + aboutConfig.aboutLabelTitle = "About App"; + aboutConfig.packageName = getApplicationContext().getPackageName(); + aboutConfig.buildType = google ? AboutConfig.BuildType.GOOGLE : AboutConfig.BuildType.AMAZON; + + aboutConfig.facebookUserName = FACEBOOK_USER_NAME; + aboutConfig.twitterUserName = TWITTER_USER_NAME; + aboutConfig.webHomePage = WEB_HOME_PAGE; + + // app publisher for "Try Other Apps" item + aboutConfig.appPublisher = APP_PUBLISHER; + + // if pages are stored locally, then you need to override aboutConfig.dialog to be able use custom WebView + aboutConfig.companyHtmlPath = COMPANY_HTML_PATH; + aboutConfig.privacyHtmlPath = PRIVACY_HTML_PATH; + aboutConfig.acknowledgmentHtmlPath = ACKNOWLEDGMENT_HTML_PATH; + + aboutConfig.dialog = new IDialog() { + @Override + public void open(AppCompatActivity appCompatActivity, String url, String tag) { + // handle custom implementations of WebView. It will be called when user click to web items. (Example: "Privacy", "Acknowledgments" and "About") + } + }; + + aboutConfig.analytics = new IAnalytic() { + @Override + public void logUiEvent(String s, String s1) { + // handle log events. + } + + @Override + public void logException(Exception e, boolean b) { + // handle exception events. + } + }; + // set it only if aboutConfig.analytics is defined. + aboutConfig.logUiEventName = "Log"; + + // Contact Support email details + aboutConfig.emailAddress = EMAIL_ADDRESS; + aboutConfig.emailSubject = EMAIL_SUBJECT; + aboutConfig.emailBody = EMAIL_BODY; + + // Branch.io labels. + aboutConfig.shareMessageTitle = getString(R.string.share_message_title); + aboutConfig.shareMessage = getString(R.string.share_message); + aboutConfig.sharingTitle = getString(R.string.sharing_title); +``` + +Open AboutBox screen + +```java + AboutActivity.launch(activity); +``` + +## Screenshot + + + diff --git a/extras/example.png b/extras/example.png new file mode 100644 index 0000000..adb68b4 Binary files /dev/null and b/extras/example.png differ diff --git a/library/build.gradle b/library/build.gradle index 7e8dee8..8a7fc8f 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -11,9 +11,8 @@ android { defaultConfig { minSdkVersion 15 targetSdkVersion 24 - versionCode 1 - versionName "1.0" - + versionCode 2 + versionName "1.0.1" } buildTypes { release { diff --git a/library/src/main/java/com/eggheadgames/aboutbox/activity/AboutActivity.java b/library/src/main/java/com/eggheadgames/aboutbox/activity/AboutActivity.java index d2b1b67..14674e5 100644 --- a/library/src/main/java/com/eggheadgames/aboutbox/activity/AboutActivity.java +++ b/library/src/main/java/com/eggheadgames/aboutbox/activity/AboutActivity.java @@ -37,21 +37,21 @@ public class AboutActivity extends MaterialAboutActivity { .build()); generalInfoCardBuilder.addItem(new MaterialAboutActionItem.Builder() - .text(R.string.version) + .text(R.string.egab_version) .subText(config.version) .build()); MaterialAboutCard.Builder supportCardBuilder = new MaterialAboutCard.Builder(); supportCardBuilder.addItem(new MaterialAboutActionItem.Builder() - .text(R.string.contact_support) + .text(R.string.egab_contact_support) .icon(R.drawable.ic_email_black) .setOnClickListener(new MaterialAboutActionItem.OnClickListener() { @Override public void onClick() { EmailUtil.contactUs(AboutActivity.this); if (config.analytics != null) { - config.analytics.logUiEvent(config.logUiEventName, getString(R.string.contact_log_event)); + config.analytics.logUiEvent(config.logUiEventName, getString(R.string.egab_contact_log_event)); } } }) @@ -60,27 +60,27 @@ public class AboutActivity extends MaterialAboutActivity { MaterialAboutCard.Builder shareCardBuilder = new MaterialAboutCard.Builder(); shareCardBuilder.addItem(new MaterialAboutActionItem.Builder() - .text(R.string.leave_review) + .text(R.string.egab_leave_review) .icon(R.drawable.ic_review) .setOnClickListener(new MaterialAboutActionItem.OnClickListener() { @Override public void onClick() { - openApp(config.packageName, config.buildType == AboutConfig.BuildType.GOOGLE); + openApp(config.buildType, config.packageName); if (config.analytics != null) { - config.analytics.logUiEvent(config.logUiEventName, getString(R.string.review_log_event)); + config.analytics.logUiEvent(config.logUiEventName, getString(R.string.egab_review_log_event)); } } }) .build()); shareCardBuilder.addItem(new MaterialAboutActionItem.Builder() - .text(R.string.share) + .text(R.string.egab_share) .icon(R.drawable.ic_share_black) .setOnClickListener(new MaterialAboutActionItem.OnClickListener() { @Override public void onClick() { ShareUtil.share(AboutActivity.this); if (config.analytics != null) { - config.analytics.logUiEvent(config.logUiEventName, getString(R.string.share_log_event)); + config.analytics.logUiEvent(config.logUiEventName, getString(R.string.egab_share_log_event)); } } }) @@ -89,14 +89,14 @@ public class AboutActivity extends MaterialAboutActivity { MaterialAboutCard.Builder aboutCardBuilder = new MaterialAboutCard.Builder(); aboutCardBuilder.addItem(new MaterialAboutActionItem.Builder() - .text(R.string.try_other_apps) + .text(R.string.egab_try_other_apps) .icon(R.drawable.ic_try_other_apps) .setOnClickListener(new MaterialAboutActionItem.OnClickListener() { @Override public void onClick() { - openPublisher(config.buildType == AboutConfig.BuildType.GOOGLE, config.appPublisher); + openPublisher(config.buildType, config.appPublisher, config.packageName); if (config.analytics != null) { - config.analytics.logUiEvent(config.logUiEventName, getString(R.string.try_other_app_log_event)); + config.analytics.logUiEvent(config.logUiEventName, getString(R.string.egab_try_other_app_log_event)); } } }) @@ -123,7 +123,7 @@ public class AboutActivity extends MaterialAboutActivity { MaterialAboutCard.Builder socialNetworksCardBuilder = new MaterialAboutCard.Builder(); socialNetworksCardBuilder.addItem(new MaterialAboutActionItem.Builder() - .text(R.string.facebook_label) + .text(R.string.egab_facebook_label) .subText(config.facebookUserName) .icon(R.drawable.ic_facebook_24) .setOnClickListener(new MaterialAboutActionItem.OnClickListener() { @@ -131,13 +131,13 @@ public class AboutActivity extends MaterialAboutActivity { public void onClick() { getOpenFacebookIntent(AboutActivity.this, config.facebookUserName); if (config.analytics != null) { - config.analytics.logUiEvent(config.logUiEventName, getString(R.string.facebook_log_event)); + config.analytics.logUiEvent(config.logUiEventName, getString(R.string.egab_facebook_log_event)); } } }) .build()); socialNetworksCardBuilder.addItem(new MaterialAboutActionItem.Builder() - .text(R.string.twitter_label) + .text(R.string.egab_twitter_label) .subText(config.twitterUserName) .icon(R.drawable.ic_twitter_24dp) .setOnClickListener(new MaterialAboutActionItem.OnClickListener() { @@ -145,14 +145,14 @@ public class AboutActivity extends MaterialAboutActivity { public void onClick() { startTwitter(AboutActivity.this, config.twitterUserName); if (config.analytics != null) { - config.analytics.logUiEvent(config.logUiEventName, getString(R.string.twitter_log_event)); + config.analytics.logUiEvent(config.logUiEventName, getString(R.string.egab_twitter_log_event)); } } }) .build()); socialNetworksCardBuilder.addItem(new MaterialAboutActionItem.Builder() - .text(R.string.web_label) + .text(R.string.egab_web_label) .subText(config.webHomePage.replace("https://", "").replace("http://", "").replace("/", "")) .icon(R.drawable.ic_web_black_24dp) .setOnClickListener(new MaterialAboutActionItem.OnClickListener() { @@ -160,7 +160,7 @@ public class AboutActivity extends MaterialAboutActivity { public void onClick() { startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(config.webHomePage))); if (config.analytics != null) { - config.analytics.logUiEvent(config.logUiEventName, getString(R.string.website_log_event)); + config.analytics.logUiEvent(config.logUiEventName, getString(R.string.egab_website_log_event)); } } }) @@ -168,7 +168,7 @@ public class AboutActivity extends MaterialAboutActivity { MaterialAboutCard.Builder privacyCardBuilder = new MaterialAboutCard.Builder(); privacyCardBuilder.addItem(new MaterialAboutActionItem.Builder() - .text(R.string.privacy_policy) + .text(R.string.egab_privacy_policy) .icon(R.drawable.ic_privacy) .setOnClickListener(new MaterialAboutActionItem.OnClickListener() { @Override @@ -176,29 +176,29 @@ public class AboutActivity extends MaterialAboutActivity { if (config.dialog == null) { startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(config.privacyHtmlPath))); } else { - config.dialog.open(AboutActivity.this, config.privacyHtmlPath, getString(R.string.privacy_policy)); + config.dialog.open(AboutActivity.this, config.privacyHtmlPath, getString(R.string.egab_privacy_policy)); } if (config.analytics != null) { - config.analytics.logUiEvent(config.logUiEventName, getString(R.string.privacy_log_event)); + config.analytics.logUiEvent(config.logUiEventName, getString(R.string.egab_privacy_log_event)); } } }) .build()); privacyCardBuilder.addItem(new MaterialAboutActionItem.Builder() - .text(R.string.acknowledgment) - .icon(R.drawable.ic_acknowledgment) + .text(R.string.egab_acknowledgements) + .icon(R.drawable.ic_acknowledgements) .setOnClickListener(new MaterialAboutActionItem.OnClickListener() { @Override public void onClick() { if (config.dialog == null) { startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(config.acknowledgmentHtmlPath))); } else { - config.dialog.open(AboutActivity.this, config.acknowledgmentHtmlPath, getString(R.string.acknowledgment)); + config.dialog.open(AboutActivity.this, config.acknowledgmentHtmlPath, getString(R.string.egab_acknowledgements)); } if (config.analytics != null) { - config.analytics.logUiEvent(config.logUiEventName, getString(R.string.asknowledgment_log_event)); + config.analytics.logUiEvent(config.logUiEventName, getString(R.string.egab_acknowledgements_log_event)); } } }) @@ -217,53 +217,85 @@ public class AboutActivity extends MaterialAboutActivity { @Override protected CharSequence getActivityTitle() { - return getString(R.string.about_screen_title); + return getString(R.string.egab_about_screen_title); } public static void getOpenFacebookIntent(Activity context, String name) { - Intent intent; try { context.getPackageManager().getPackageInfo("com.facebook.katana", 0); - intent = new Intent(Intent.ACTION_VIEW, Uri.parse("fb://profile/" + name)); + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("fb://profile/" + name)); + context.startActivity(intent); } catch (Exception e) { - intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.facebook.com/" + name)); - } - context.startActivity(intent); - } - - - public static void startTwitter(Activity context, String name) { - Intent intent; - try { - context.getPackageManager().getPackageInfo("com.twitter.android", 0); - intent = new Intent(Intent.ACTION_VIEW, Uri.parse("twitter://user?screen_name=" + name)); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - } catch (Exception e) { - intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://twitter.com/" + name)); - } - context.startActivity(intent); - } - - public void openApp(String packageName, boolean googlePlay) {//true if Google Play, false if Amazon Store - try { - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse((googlePlay ? "market://details?id=" : "amzn://apps/android?p=") + packageName))); - } catch (ActivityNotFoundException e1) { try { - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse((googlePlay ? "http://play.google.com/store/apps/details?id=" : "http://www.amazon.com/gp/mas/dl/android?p=") + packageName))); - } catch (ActivityNotFoundException e2) { - Toast.makeText(this, R.string.can_not_open, Toast.LENGTH_SHORT).show(); + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.facebook.com/" + name)); + context.startActivity(intent); + } catch (Exception e1) { + Toast.makeText(context, R.string.egab_can_not_open, Toast.LENGTH_SHORT).show(); } } } - public void openPublisher(boolean googlePlay, String publisher) {//true if Google Play, false if Amazon Store + public static void startTwitter(Activity context, String name) { try { - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse((googlePlay ? "market://search?q=pub:" : "amzn://apps/android?showAll=1&p=") + publisher))); + context.getPackageManager().getPackageInfo("com.twitter.android", 0); + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("twitter://user?screen_name=" + name)); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } catch (Exception e) { + try { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://twitter.com/" + name)); + context.startActivity(intent); + } catch (Exception e1) { + Toast.makeText(context, R.string.egab_can_not_open, Toast.LENGTH_SHORT).show(); + } + } + + } + + public void openApp(AboutConfig.BuildType buildType, String packageName) { + String appURI = null; + String webURI = null; + switch (buildType) { + case GOOGLE: + appURI = "market://details?id=" + packageName; + webURI = "http://play.google.com/store/apps/details?id=" + packageName; + break; + case AMAZON: + appURI = "amzn://apps/android?p=" + packageName; + webURI = "http://www.amazon.com/gp/mas/dl/android?p=" + packageName; + break; + default: + //nothing + } + open(appURI, webURI); + } + + public void openPublisher(AboutConfig.BuildType buildType, String publisher, String packageName) { + String appURI = null; + String webURI = null; + switch (buildType) { + case GOOGLE: + appURI = "market://search?q=pub:" + publisher; + webURI = "http://play.google.com/store/search?q=pub:" + publisher; + break; + case AMAZON: + appURI = "amzn://apps/android?showAll=1&p=" + packageName; + webURI = "http://www.amazon.com/gp/mas/dl/android?showAll=1&p=" + packageName; + break; + default: + //nothing + } + open(appURI, webURI); + } + + private void open(String appURI, String webURI) { + try { + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(appURI))); } catch (ActivityNotFoundException e1) { try { - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse((googlePlay ? "http://play.google.com/store/search?q=pub:" : "http://www.amazon.com/gp/mas/dl/android?showAll=1&p=") + publisher))); + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(webURI))); } catch (ActivityNotFoundException e2) { - Toast.makeText(this, R.string.can_not_open, Toast.LENGTH_SHORT).show(); + Toast.makeText(this, R.string.egab_can_not_open, Toast.LENGTH_SHORT).show(); } } } diff --git a/library/src/main/java/com/eggheadgames/aboutbox/share/EmailUtil.java b/library/src/main/java/com/eggheadgames/aboutbox/share/EmailUtil.java index a186245..438612a 100644 --- a/library/src/main/java/com/eggheadgames/aboutbox/share/EmailUtil.java +++ b/library/src/main/java/com/eggheadgames/aboutbox/share/EmailUtil.java @@ -3,9 +3,11 @@ package com.eggheadgames.aboutbox.share; import android.app.Activity; import android.content.Intent; import android.net.Uri; +import android.os.Build; +import android.text.TextUtils; import com.eggheadgames.aboutbox.AboutConfig; -import com.eggheadgames.aboutbox.BuildConfig; +import com.eggheadgames.aboutbox.R; public final class EmailUtil { @@ -18,26 +20,35 @@ public final class EmailUtil { final Uri mailto = Uri.fromParts("mailto", config.emailAddress, null); - final String emailSubject; + String emailBody = config.emailBody; + if (TextUtils.isEmpty(emailBody)) { + String deviceInfo = ""; + deviceInfo += "\n App version: " + config.version; + deviceInfo += "\n Android version: " + Build.VERSION.RELEASE + " (" + android.os.Build.VERSION.SDK_INT + ")"; + deviceInfo += "\n Device: " + android.os.Build.MODEL + " (" + android.os.Build.PRODUCT + ")"; + deviceInfo += "\n Platform: " + platformName(config.buildType); - if ("google".equals(BuildConfig.FLAVOR)) { - emailSubject = config.emailSubject + "G"; - } else if ("amazon".equals(BuildConfig.FLAVOR)) { - emailSubject = config.emailSubject + "K"; - } else { - emailSubject = config.emailSubject; + emailBody = activity.getString(R.string.egab_email_body_prompt) + "\n\n\n\n\n" + + "---------------------------" + deviceInfo; } try { Intent emailIntent = new Intent(Intent.ACTION_SENDTO, mailto); - emailIntent.putExtra(Intent.EXTRA_SUBJECT, emailSubject); - emailIntent.putExtra(Intent.EXTRA_TEXT, config.emailBody); + emailIntent.putExtra(Intent.EXTRA_SUBJECT, config.emailSubject); + emailIntent.putExtra(Intent.EXTRA_TEXT, emailBody); activity.startActivity(Intent.createChooser(emailIntent, "Send email...")); } catch (Exception e) { if (config.analytics != null) { config.analytics.logException(e, false); } } + } + private static String platformName(AboutConfig.BuildType buildType) { + switch (buildType) { + case GOOGLE: return "Google Play"; + case AMAZON: return "Amazon Kindle"; + default: return "Unknown"; + } } } diff --git a/library/src/main/res/drawable/ic_acknowledgment.xml b/library/src/main/res/drawable/ic_acknowledgements.xml similarity index 100% rename from library/src/main/res/drawable/ic_acknowledgment.xml rename to library/src/main/res/drawable/ic_acknowledgements.xml diff --git a/library/src/main/res/values-pt/strings.xml b/library/src/main/res/values-pt/strings.xml new file mode 100644 index 0000000..00e8471 --- /dev/null +++ b/library/src/main/res/values-pt/strings.xml @@ -0,0 +1,25 @@ + + AboutBox + Avaliar + Contactar o Suporte + Experimentar outras aplicações + Versão + Facebook + Twitter + Web + Acknowledgements + Política de Privacidade + Sobre + Partilhar + Contactos + Avalie + Partilhar + Experimentar outras aplicações + Facebook + Twitter + Website + Privacicidade + Acknowledgements + Tu não tens nenhuma aplicação que possa abrir esta ligação + Digite sua pergunta aqui: + diff --git a/library/src/main/res/values/strings.xml b/library/src/main/res/values/strings.xml index b2eef7c..724d70c 100644 --- a/library/src/main/res/values/strings.xml +++ b/library/src/main/res/values/strings.xml @@ -1,25 +1,26 @@ AboutBox - Leave Review - Contact Support - Try Other Apps - Version - Facebook - Twitter - Web - Acknowledgment - Privacy Policy - About - Share - Contact - Review - Share - Try Other Apps - Facebook - Twitter - Website - Privacy - Acknowledgement - You don\'t have any app that can open this link + Leave Review + Contact Support + Try Other Apps + Version + Facebook + Twitter + Web + Acknowledgements + Privacy Policy + About + Share + Contact + Review + Share + Try Other Apps + Facebook + Twitter + Website + Privacy + Acknowledgements + You don\'t have any app that can open this link + Please type your question here: