Skip to content

Instantly share code, notes, and snippets.

@nooralibutt
Last active October 25, 2022 09:35
Show Gist options
  • Save nooralibutt/8b78809208464614a3703ccc27f234a0 to your computer and use it in GitHub Desktop.
Save nooralibutt/8b78809208464614a3703ccc27f234a0 to your computer and use it in GitHub Desktop.
Integration of more screen

Integrating of More Screen

1. Installing plugins

2. Add Strings

Add following strings in strings.dart file

static const privacy_policy = "Privacy Policy";
static const more = "More";
static const app_name = "XXXXXXX";
static const appStoreID = 'XXXXXXXXX';
static const iTunes_more_apps_link = 'XXXXXXXregent-branding-ltd/id1128207635';
static const android_developer_name = 'XXXXXXHamzah+Malik';

2. Add more directory

  • Create a more directory in lib/screens
  • Add more_screen.dart and privacy_policy_screen.dart in lib/screens/more
  • Import constants.dart and strings.dart file in both

3. Add route (Optional)

  • Open routes.dart file
  • add import '../screens/more/more_screen.dart';
  • In routes map, add MoreScreen.routeName: (context) => MoreScreen(), like this
    ...
    final Map<String, WidgetBuilder> routes = {
      WelcomeScreen.routeName: (context) => WelcomeScreen(),
      MoreScreen.routeName: (context) => MoreScreen(),
    };
    ...

4. Navigate to More screen

  • Using route: Navigator.pushNamed(context, MoreScreen.routeName);
  • else Navigator.push(context, MaterialPageRoute(builder: (context) => MoreScreen()));

5. Add In App Rating

  • Open prefs.dart and add following lines
    static const KEY_SHOW_IN_APP = "SHOW_IN_APP";
    static bool shouldIShowInAppReview() {
        final counter = _prefs.getInt(KEY_SHOW_IN_APP) ?? 1;
        _prefs.setInt(KEY_SHOW_IN_APP, counter + 1);
        return counter % 30 == 0;
    }
  • Open home_screen.dart and
  • import import 'package:in_app_review/in_app_review.dart';
  • also imort prefs.dart
  • add following method
    static _showInAppReview() async {
        final InAppReview inAppReview = InAppReview.instance;
        
        if (await inAppReview.isAvailable()) {
          inAppReview.requestReview();
        }
    }
  • Call above method in void initState() if its stateful widget else Widget build(BuildContext context) using if (Prefs.shouldIShowInAppReview()) _showInAppReview();

6. About Dialog

  • Make sure there is a an icon 'assets/images/icon.png' in assets/ folder
  • Change the text in _showAboutDialog method inside more_screen.dart according to your app ASO what this app do

7. App info

In App Info file, check out todo. There are times when app name could be null so we have to provide a hard coded value of app name

8. Add export compliance keys for iOS

  1. Go to ios/Runner/Info.plist
  2. Add this key in plist file
    <key>ITSAppUsesNonExemptEncryption</key>  
    <false/>
    
  3. Just paste before </dict></plist>
import 'dart:async';
import 'package:package_info/package_info.dart';
class AppInfo {
// Singleton instance code
static final AppInfo _instance = AppInfo._();
static AppInfo get instance => _instance;
AppInfo._();
PackageInfo _info;
Future<void> init() async => _info = await PackageInfo.fromPlatform();
// TODO: Change this app name to your app name
String get appName => _info.appName ?? 'App Name';
String get packageName => _info.packageName;
String get versionAndBuild => _info.version + '+' + _info.buildNumber;
}
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:in_app_review/in_app_review.dart';
import 'package:share/share.dart';
import 'package:url_launcher/url_launcher.dart';
import '../../all_utilities.dart';
import 'privacy_policy_screen.dart';
class MoreScreen extends StatefulWidget {
static const String routeName = "/moreScreen";
@override
_MoreScreenState createState() => _MoreScreenState();
}
class _MoreScreenState extends State<MoreScreen> {
final InAppReview inAppReview = InAppReview.instance;
@override
Widget build(BuildContext context) {
final style =
Theme.of(context).textTheme.headline6.copyWith(color: kRedAccent);
final iconColor = kRedAccent;
return Scaffold(
appBar: AppBar(
title: Text(
Strings.more,
style: Theme.of(context)
.textTheme
.headline6
.copyWith(color: kDarkPurple),
),
iconTheme: Theme.of(context).iconTheme.copyWith(color: kDarkPurple),
),
body: Column(
children: [
Expanded(
child: ListView(
children: [
ListTile(
title: Text(Strings.privacy_policy, style: style),
leading: Icon(Icons.security, color: iconColor),
onTap: _privacyPolicy,
),
ListTile(
title: Text('Rate Us', style: style),
leading: Icon(Icons.stars, color: iconColor),
onTap: _rateUs,
),
ListTile(
title: Text('Share', style: style),
leading: Icon(Icons.share, color: iconColor),
onTap: _share,
),
ListTile(
title: Text('More Apps', style: style),
leading: Icon(Icons.widgets, color: iconColor),
onTap: _moreApps,
),
ListTile(
title: Text(
'Contact Us',
style: style,
),
leading: Icon(Icons.email, color: iconColor),
onTap: _mailTo,
),
ListTile(
title: Text(
'About',
style: style,
),
leading: Icon(Icons.info_outline, color: iconColor),
onTap: _showAboutDialog,
),
],
),
)
],
),
);
}
_showAboutDialog() {
showAboutDialog(
context: context,
applicationName: AppInfo.instance.appName,
applicationIcon: Image.asset('assets/images/icon.png', width: 50),
applicationVersion: 'version ' + AppInfo.instance.versionAndBuild,
children: [
Text(
'Our game is an addictive hacking app with awesome levels about different kind of app hacks for fun like mind games or brain test game!\nIf you have any suggestions feel free to click on Contact Us button'),
]);
}
_mailTo() {
final Uri _emailLaunchUri = Uri(
scheme: 'mailto',
path: 'nalitt.apps@gmail.com',
queryParameters: {'subject': AppInfo.instance.appName});
_launchURL(_emailLaunchUri.toString());
}
_share() {
Share.share(
'Hey there check out the best ${AppInfo.instance.appName}: ' +
'iOS: itms-apps://itunes.apple.com/app/apple-store/id${Strings.appStoreID}?mt=8 ' +
' Android: https://play.google.com/store/apps/details?id=${AppInfo.instance.packageName}',
subject: AppInfo.instance.appName);
}
_rateUs() => inAppReview.openStoreListing(appStoreId: Strings.appStoreID);
_moreApps() async {
_launchURL(Platform.isIOS
? 'https://apps.apple.com/us/developer/' + Strings.iTunes_more_apps_link
: 'market://search?q=pub:' + Strings.android_developer_name);
}
_privacyPolicy() => Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => PrivacyPolicyScreen()));
void _launchURL(String? url) async {
if (url == null) {
_showDialog(
'Failed', 'Failed to launch. Please check your internet connection');
return;
}
final uri = Uri.tryParse(url);
if (uri != null && await canLaunchUrl(uri)) {
launchUrl(uri);
} else {
_showDialog(
'Failed', 'Failed to launch. Please check your internet connection');
}
}
_showDialog(String title, String description) {
showDialog(
context: context,
builder: (BuildContext context) {
// return object of type Dialog
return AlertDialog(
title: Text(
title,
style: Theme.of(context)
.textTheme
.headline6
.copyWith(color: Colors.white),
),
content: Text(
description,
style: Theme.of(context)
.textTheme
.bodyText1
.copyWith(color: Colors.white),
),
actions: <Widget>[
FlatButton(
child: Text('Dismiss'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
}
import 'package:digital_scale_ali/all_utilities.dart';
class PrivacyPolicyScreen extends StatelessWidget {
static const String routeName = "/privacy_policy";
const PrivacyPolicyScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Privacy Policy')),
body: SafeArea(
bottom: false,
child: Column(
children: [
Expanded(
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(20),
child: RichText(
text: TextSpan(
text:
'I appreciate your awesomeness.\n\nThis Privacy Policy conforms with all relevant data protection and privacy laws while outlining the many sorts of information we gather from you as you play our games.\n\n\nWe appreciate you playing our games.\n\nWe are very concerned about protecting your privacy, so we try to collect as little user data as possible. This Privacy Policy covers the kinds of information we collect when you download and play our games or use other Trickster Arts applications since we need to collect a limited amount of information in order to offer you with our games. Additionally, it outlines our practices for using, disclosing, retaining, and giving you choices about your information.\n\nYou are indicating your approval of this policy by participating in our games. Do not hesitate to contact us if you have any questions.',
style: Theme.of(context).textTheme.bodyText2,
children: [
TextSpan(
text: '\n\nTypes Of Information we collect.\n\n',
style: Theme.of(context).textTheme.subtitle2,
),
const TextSpan(
text:
'Usernames and other minimally identifying personal data regarding your play session are collected by us.\n\nYou freely provide us with the following information when you play our games:\n\nInformation found in-game (for example, a player username)\n\nBy integrating your game with third-party services, you can voluntarily give us permission to collect information from third parties:\n\nTechnical information regarding user behavior and patterns that cannot be used to personally identify a user is as follows:\n\nSessions data (for example, the generalized location of where you access our game from)IDs for mobile devices (for example, the specifications and operating system of your device).\n\nFor a better experience, while using our Service, we may require you to provide us with certain personally identifiable information, including our all apps and Games. The information that we request will be retained by us and used as described in this privacy policy.\n\nThe app does use third-party services that may collect information used to identify you.\n\nLink to the privacy policy of third-party service providers used by the app\n\nAdMob\n\nFacebook\n\nUnity\n\nAppLovin'),
TextSpan(
text: '\n\nHow we use your Information:\n\n',
style: Theme.of(context).textTheme.subtitle2,
),
const TextSpan(
text:
'In order to deliver a useful game and features, as well as to guarantee the security of your account, we process your data.\n\nWe utilize the data we gather in the following ways to guarantee the performance of our games:\n\nin order to offer in-game features. For instance, we display nearby players\' usernames and use your player name on our leaderboards in-game.\n\nto notify you of in-game events. For instance, we use data from Google/Apple to offer you in-game information if push notifications are enabled on your device.\n\nto enhance your video game playing. For instance, if you permit us to access your Facebook information, we will use that data to link you to your Facebook friends.\n\nto boost the caliber of our offerings. We, for instance, utilize session data to identify fraudulent usage of your account.'),
TextSpan(
text:
'\n\nHow and when we share your information:\n\n',
style: Theme.of(context).textTheme.subtitle2,
),
const TextSpan(
text:
'We don\'t trade off your data. To enhance our services, we divulge non-personal information to third parties.\n\nNone of the information we collect is sold. Your information may be distributed in the following ways:\n\nOur games\' social aspects are a key element. Other players may access your profile information, participate in your in-game activities, or read any in-game communications you have posted if we share your in-game information with them.\n\nTo better serve you, we might offer third-party game services and analytics with anonymised technical information.\n\nWe may share and provide data with public authorities and other affiliated businesses and organizations in response to legitimate requests.'),
TextSpan(
text: '\n\nHow we handle your information:\n\n',
style: Theme.of(context).textTheme.subtitle2,
),
const TextSpan(
text:
'We keep your information safe, and will only use it until you inform us that you no longer wish us to play our games.\n\nIf you do inform us, we may retain limited information about you where required to do so.\n\nWe will securely retain your personal information for as long as needed to provide our services. As soon as we will no longer require your personal data to provide our services, we will promptly delete or anonymize it on request.\n\nIn some cases we may not be able to delete your personal information, and will retain and use your information for as long as necessary to comply with our legal obligations, resolve any related disputes, maintain the functionality of our services and/or enforce our agreements.'),
TextSpan(
text: '\n\nChildren’s Privacy\n\n',
style: Theme.of(context).textTheme.subtitle2,
),
const TextSpan(
text:
'These Services do not address anyone under the age of 13. We do not knowingly collect personally identifiable information from children under 13 years of age. In the case we discover that a child under 13 has provided us with personal information, we immediately delete this from our servers. If you are a parent or guardian and you are aware that your child has provided us with personal information, please contact us so that we will be able to do the necessary actions.'),
TextSpan(
text:
'\n\nYour rights regarding your information:\n\n',
style: Theme.of(context).textTheme.subtitle2,
),
const TextSpan(
text:
'Know your rights! Depending on where you live in the world, you can also have more rights.\n\nYou have the right to request that your data be updated, destroyed, or subject to restrictions on how it is used or shared. If we are unable to use this data, you might not be able to use some features of our games. Upon request, we shall de-identify any data connected to an inactive game account. If you request that we delete your personal information, we may keep some of it if it is essential for our legitimate business purposes, such as to maintain the quality of our services, settle disputes, and adhere to any legal obligations. You might also have more privacy rights depending on where you live.We will respond to all requests for your information within 30 days, and if you have any concerns about your privacy please contact us first. If you have an unresolved privacy or data use concern that we have not addressed satisfactorily, please contact your local Data Protection Authority within the Czech bureau for any unresolved complaints.'),
TextSpan(
text: '\n\nHow we make changes to this policy:\n\n',
style: Theme.of(context).textTheme.subtitle2,
),
const TextSpan(
text:
'Our Privacy Policy may change in the future. After being posted online for 30 days, these modifications will become effective.\n\nIf we determine that changing this Privacy Policy is required by law or is essential to reflect changes in our services, we will do so.\n\nYou shall be bound by any modifications to this Privacy Policy after 30 days from the day we put them online. If you have any specific inquiries concerning the modifications within this thirty day period, please get in touch with us. You accept the updated policy if you use our services after those changes have taken effect.'),
TextSpan(
text: '\n\nContact Us\n\n',
style: Theme.of(context).textTheme.subtitle2,
),
const TextSpan(
text:
'If you have any questions or suggestions about our Privacy Policy, do not hesitate to contact us at crosscode.dev\n\n'),
],
),
),
),
),
)
],
),
),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment