Showing posts with label flutter. Show all posts
Showing posts with label flutter. Show all posts

Sunday, April 7, 2024

How to Implement Multi-Language Support in Flutter app (Localization)

Hey dear readers, welcome back in our blog 1GB Developer. Now we are going to implement the feature which is responsible for supporting multi-language in your device. For example if you dont like english then change the app language into hindi.

So let start our coding for multi-language  support in flutter application :


Step 1. 

create two file named a) app_en.arb and b)app_hi.arb in lib/l10n :


a) app_hi.arb which contain data like this:

{

  "signup_welcome_desc": "เคถुเคฐू เค•เคฐเคจे เค•े เคฒिเค เคซॉเคฐ्เคฎ เคญเคฐें",

  "welcome_back": "เคตाเคชเคธी เคชเคฐ เคธ्เคตाเค—เคค เคนै!",

  "login_welcome_desc": "เค…เคชเคจे เค–ाเคคा เค•ो เคช्เคฐเคฌंเคงिเคค เค•เคฐเคจे เค•े เคฒिเค เคฒॉเค—िเคจ เค•เคฐें",

  "mobile_no": "เคฎोเคฌाเค‡เคฒ เคจंเคฌเคฐ",

  "email_address": "เคˆเคฎेเคฒ เคชเคคा",

  "mobile_no_email":"เคฎोเคฌाเค‡เคฒ เคจंเคฌเคฐ/เคˆเคฎेเคฒ",

  "forgot_password":"เคชाเคธเคตเคฐ्เคก เคญूเคฒ เค—เค?",

  "password": "เคชाเคธเคตเคฐ्เคก",

  "confirm_password": "เคชाเคธเคตเคฐ्เคก เค•ी เคชुเคท्เคŸि เค•เคฐें",

  "name":"เคจाเคฎ",

  "referral":"เคฐेเคซ़เคฐเคฒ เคฆเคฐ्เคœ เค•เคฐें (เคตैเค•เคฒ्เคชिเค•)",

  "get_started": "เคถुเคฐू เคนो เคœाเค“",

  "have_an_account": "{prefix} เคเค• เค–ाเคคा เคนै",

  "login": "เคฒॉเค—िเคจ",

  "sign_up": "เคธाเค‡เคจ เค…เคช",

  "trending_products": "เคšเคฐ्เคšिเคค เค‰เคค्เคชाเคฆ",

  "popular_products": "เคฒोเค•เคช्เคฐिเคฏ เค‰เคค्เคชाเคฆ",

  "new_products": "เคจเค เค‰เคค्เคชाเคฆ",

  "known_products": "เคช्เคฐเคธिเคฆ्เคง เค‰เคค्เคชाเคฆ",

  "signup_for_newsletter": "เคธเคฎाเคšाเคฐ เคชเคค्เคฐिเค•ा เค•े เคฒिเค เคธाเค‡เคจ เค…เคช เค•เคฐें",

  "contact_info": "เคธंเคชเคฐ्เค• เคœाเคจเค•ाเคฐी",

  "rupee":"₹. {value}",

  "edit_profile": "เคช्เคฐोเคซ़ाเค‡เคฒ เคธंเคชाเคฆिเคค เค•เคฐें",

  "wallet": "เคฌเคŸुเค†",

  "manage_address": "เคชเคคे เค•ा เคช्เคฐเคฌंเคงเคจ",

  "language": "เคญाเคทा",

  "setting": "เคธेเคŸिंเค—्เคธ",

  "privacy": "เค—ोเคชเคจीเคฏเคคा",

  "sign_out": "เคธाเค‡เคจ เค†เค‰เคŸ",

  "your_orders": "เค†เคชเค•े เค†เคฆेเคถ",

  "buy_again": "เคซिเคฐ เคธे เค–เคฐीเคฆें",

  "your_account": "เค†เคชเค•ा เค–ाเคคा",

  "your_lists": "เค†เคชเค•ी เคธूเคšिเคฏाँ",

  "term_and_condition": "เคจिเคฏเคฎ เค”เคฐ เคถเคฐ्เคคें",

  "search": "เค–ोเคœें",

  "add_to_cart": "เค•ाเคฐ्เคŸ เคฎें เคกाเคฒें",

  "add_to_wishlist": "เค‡เคš्เค›ा เคธूเคšी เคฎें เคœोเคก़ें",

  "added_to_wishlist": "เค‡เคš्เค›ा เคธूเคšी เคฎें เคœोเคก़ा เค—เคฏा",

  "percent_discount": "{value}% เค›ूเคŸ",

  "compare": "เคคुเคฒเคจा เค•เคฐें",

  "color": "เคฐंเค—",

  "delivery": "เคกिเคฒीเคตเคฐी",

  "product_description": "เค‰เคค्เคชाเคฆ เคตिเคตเคฐเคฃ",

  "available_offers": "เค‰เคชเคฒเคฌ्เคง เค‘เคซ़เคฐ",

  "quantity": "เคฎाเคค्เคฐा",

  "go_to_cart": "เค•ाเคฐ्เคŸ เคชเคฐ เคœाเคं",

  "checkout": "เคšेเค•เค†เค‰เคŸ",

  "save_for_later": "เคฌाเคฆ เคฎें เคธเคนेเคœें",

  "delete": "เคนเคŸाเคं",

  "proceed_with_defaul_address": "เคกिเคซ़ॉเคฒ्เคŸ เคชเคคे เค•े เคธाเคฅ เค†เค—े เคฌเคข़ें",

  "proceed": "เค†เค—े เคฌเคข़ें",

  "pay_online": "เค‘เคจเคฒाเค‡เคจ เคญुเค—เคคाเคจ เค•เคฐें",

  "cash_on_delivery": "เค•ैเคถ เค‘เคจ เคกिเคฒीเคตเคฐी"

}


b) app_hi.arb which contain data like this:


{

  "signup_welcome_desc":"Fill out the form to get started",

  "welcome_back":"Sign in",

  "login_welcome_desc":"Login to manage your account",

  "mobile_no_email":"Mobile No./Email",

  "mobile_no":"Mobile No.",

  "forgot_password":"Forgot Password?",

  "email_address":"Email address",

  "password":"Password",

  "confirm_password":"Confirm Password",

  "name":"Name",

  "referral":"Enter Referral (optional)",

  "get_started":"Get Started",

  "have_an_account":"{prefix} have an account.",

  "login":"Login",

  "sign_up":"Sign Up",

  "trending_products": "Trending Products",

  "popular_products":"Popular Products",

  "new_products":"New Products",

  "known_products":"Known Products",

  "signup_for_newsletter":"Sign up for Newsletter",

  "contact_info":"Contact Info",

  "rupee":"Rs. {value}",

  "edit_profile":"Edit Profile",

  "wallet":"Wallet",

  "manage_address":"Manage Address",

  "language":"Language",

  "setting":"Setting",

  "privacy":"Privacy",

  "sign_out":"Sign Out",

  "your_orders":"Your Orders",

  "buy_again":"Buy Again",

  "your_account":"Your Account",

  "your_lists":"Your Lists",

  "term_and_condition":"Term and conditions",

  "search":"Search",

  "add_to_cart":"Add to cart",

  "add_to_wishlist":"Add to wishlist",

  "added_to_wishlist":"Added to wishlist",

  "percent_discount":"{value}% off",

  "compare":"Compare",

  "color":"Color",

  "delivery":"Delivery",

  "product_description":"Product Description",

  "available_offers":"Available Offers",

  "quantity":"Quantity",

  "go_to_cart":"Go to Kart",

  "checkout":"Checkout",

  "save_for_later":"Save for Later",

  "delete":"Delete",

  "proceed_with_defaul_address":"Proceed with default address",

  "proceed":"Proceed",

  "pay_online":"Pay Online",

  "cash_on_delivery":"Cash On Delivery"


}


step 2.  

In root directory where pubs.yaml file is present create new file with name l10n.yaml and put this code inside:


arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart


Step 3. 

Go to main.dart file and put this code :



import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
@override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: 'Localizations Sample App',
      debugShowCheckedModeBanner: false,
      locale: Locale('hi'),
      localizationsDelegates: const [
        AppLocalizations.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      supportedLocales: const [
        Locale('en'),
        Locale('hi'),
      ],



Now this path will generated later when you build the code:

import 'package:flutter_gen/gen_l10n/app_localizations.dart';

Also dont forget to add this line in your pubs.yaml file:

# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter packages.
flutter:
  generate: true

  # The following line ensures that the Material Icons font is
  # included with your application, so that you can use the icons in
  # the material Icons class.
  uses-material-design: true

  # To add assets to your application, add an assets section, like this:
  assets:
    - assets/
  #   - images/a_dot_ham.jpeg
  # An image asset can refer to one or more resolution-specific "variants", see
  # https://flutter.dev/assets-and-images/#resolution-aware
  # For details regarding adding assets from package dependencies, see
  # https://flutter.dev/assets-and-images/#from-packages
  # To add custom fonts to your application, add a fonts section here,
  # in this "flutter" section. Each entry in this list should have a
  # "family" key with the font family name, and a "fonts" key with a
  # list giving the asset and other descriptors for the font. For

This generate:true will generate the file for localization.

also install this package: intl:^0.18.1


Thank you. Happy flutter  ๐Ÿ˜ƒ

Saturday, March 30, 2024

New Concept For BottomNavigationBar in Flutter

 Hey Friends ! Whats-uppppp, I am back with my limited knowledge ๐Ÿ˜‚๐Ÿ˜ in flutter but it is important for you.

So Today we are going to know, when we navigate through BottomNavigationBar and click on back button it does not trace previous visited BottomNavigationItem, if you are learning flutter from youtube.

They suggest to take List<Widget> screen and render the Widget via index of screens. Personally i think, it is not better to remove widget suddenly from widget tree.

So finally i came with this new code:

We are going to use get package for state-management here also simple flutter code:

Create file bottom_navigation_screen.dart:

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:badges/badges.dart' as badges;

class BottomNavigationScreen
extends StatelessWidget {
BottomNavigationScreen({Key? key}) : super(key: key);

  final BottomNavigationController
_bottomNavigationController =
    Get.put(BottomNavigationController());

   final PageController _pageController
= PageController(initialPage: 0);
  List<Widget> screens = [
    HomeScreen(),
    ProfileScreen(),
    SearchScreen(),
    CartScreen()
  ];

  @override
  Widget build(BuildContext context) {
  return Obx(() {
  return PopScope(
  canPop: _bottomNavigationController
    .wantBack.value,
  onPopInvoked: (bool didPop) async {
  print(didPop);
  if (didPop) return;
  if (_bottomNavigationController
    .visitedIndexes.length > 1) {
  _bottomNavigationController.visitedIndexes
   .removeLast(); // Remove current index
   _pageController.animateToPage(
    _bottomNavigationController.visitedIndexes.last,
    duration: Duration(milliseconds: 300),
                curve: Curves.linear);
            _bottomNavigationController.stackIndex.value =
                _bottomNavigationController
                    .visitedIndexes.last; // Go back to previous index

            return;
          } else {
            _bottomNavigationController.wantBack.value = true;
            Get.back();
          }
        },
        child: Scaffold(
          body: PageView.builder(
            physics: NeverScrollableScrollPhysics(),
            itemCount: screens.length,
            controller: _pageController,
            itemBuilder: (BuildContext context, int index) {
              return screens[index];
            },
          ),
          bottomNavigationBar: BottomNavigationBar(
            currentIndex: _bottomNavigationController.stackIndex.value,
            selectedItemColor: Colors.amber,
            unselectedItemColor: Colors.black,
            elevation: 5,
            onTap: (int index) {
              if (!_bottomNavigationController.visitedIndexes.contains(index)) {
                _bottomNavigationController.visitedIndexes
                    .add(index);
// Add index to visited indexes list
              }
              _bottomNavigationController.stackIndex.value = index;
              _pageController.animateToPage(index,
                  duration: Duration(milliseconds: 300), curve: Curves.linear);
                          },
            items: [
              BottomNavigationBarItem(
                  icon: CustomIcons.homeOutline(),
                  activeIcon: CustomIcons.home(
                      color: CustomColors.amber,
                  label: 'Home'),
              BottomNavigationBarItem(
                  icon: Icon(Icons.person_outline),
                  activeIcon: Icon(Icons.person),
                  label: 'Profile'),
              const BottomNavigationBarItem(
                  icon: Icon(Icons.search), label: 'Search'),
              BottomNavigationBarItem(
                  icon: Icon(Icons.cart_outline),
                  activeIcon: Icon(Icons.cart,color: Colors.amber,), 
                  label: 'Cart'),
            ],
             
          ),
        ),
      );
    }
    );
  }
}


Create another file
bottom_navigation_controller.dart:


import 'package:get/get.dart';

class BottomNavigationController extends GetxController {
  final stackIndex = 0.obs;
  final visitedIndexes = <int>[0].obs;
// Keep track of visited indexes
  final wantBack = false.obs;
}




Tuesday, March 26, 2024

Integrate Cashfree Payment Gateway in Flutter

Payment Gateway:

payment gateway is a merchant service provided by an e-commerce application service provider that authorizes credit card or direct payments processing for e-businessesonline retailersbricks and clicks, or traditional brick and mortar.[1] The payment gateway may be provided by a bank to its customers, but can be provided by a specialised financial service provider as a separate service, such as a payment service provider.

A payment gateway facilitates a payment transaction by the transfer of information between a payment portal (such as a website, mobile phone or interactive voice response service) and the front end processor or acquiring bank.

Payment gateways are a service that helps merchants initiate ecommerce, in-app, and point of sale payments for a broad variety of payment methods. The gateway is not directly involved in the money flow; typically it is a web server to which a merchant's website or POS system is connected. A payment gateway often connects several acquiring banks and payment methods under one system.


To Integrate cashfree Payment Gateway into your flutter project follow these step only (For Android) :

Step 1.


install this dependancy after runing this command in terminal:

flutter pub get flutter_cashfree_pg_sdk

Step 2.



// Please put cursor on every import where it is break the line
// and make it one liner

import 'dart:convert';
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter_cashfree_pg_sdk/api/cferrorresponse
/cferrorresponse.dart';
import 'package:flutter_cashfree_pg_sdk/api/cfpayment
/cfdropcheckoutpayment.dart';
import 'package:flutter_cashfree_pg_sdk/api/cfpaymentcomponents
/cfpaymentcomponent.dart';
import 'package:flutter_cashfree_pg_sdk/api/cfpaymentgateway
/cfpaymentgatewayservice.dart';
import 'package:flutter_cashfree_pg_sdk/api/cfsession
/cfsession.dart';
import 'package:flutter_cashfree_pg_sdk/api/cftheme
/cftheme.dart';
import 'package:flutter_cashfree_pg_sdk/utils
/cfenums.dart';
import 'package:flutter_cashfree_pg_sdk/utils
/cfexceptions.dart';
import 'package:get/get.dart';
import 'package:http/http.dart' as http;


class PaymentMethodScreen extends StatefulWidget {
  const PaymentMethodScreen({super.key});

  @override
  State<PaymentMethodScreen> createState() =>
_PaymentMethodScreenState();
}

class _PaymentMethodScreenState extends
State<PaymentMethodScreen> {
 
  CFPaymentGatewayService cfPaymentGatewayService =
      CFPaymentGatewayService(); // Cashfree Payment Instance
  bool? isSuccess;

  @override
  void initState() {
    super.initState();
    // Attach events when payment is success and
// when error occured
    cfPaymentGatewayService.setCallback(verifyPayment, onError);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Payment Method'),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.start,
        children: [
          ListTile(
            onTap: () {
              pay();
            },
            title: Text("Online Pay"),
          ),
        ],
      ),
    );
  } // When payment is done successfully

  void verifyPayment(String orderId) {
    // Here we will only print the statement
    // to check payment is done or not
    isSuccess = true;
    setState(() {});
// redirect to final screen from here
 
    print("Verify Payment $orderId");
  }

// If some error occur during payment this will trigger
  void onError(CFErrorResponse errorResponse, String orderId) {
    // printing the error message so that we can show
    // it to user or checkourselves for testing
    isSuccess = false;
    setState(() {});
    print(errorResponse.getMessage());
    print("Error while making payment");
  }

  String orderId = new DateTime.now()
    .millisecondsSinceEpoch
    .toString();

  Future<CFSession?> createSession() async {
    try {
     
final mySessionIDData = await createSessionID(
          orderId);
// This will create session id from flutter itself

     

      print(mySessionIDData);

      // Now we will se some parameter like orderID ,
        //environment,payment sessionID
      // after that we wil create the checkout session
      // which will launch through which user can pay.
      var session = CFSessionBuilder()
          .setEnvironment(CFEnvironment.SANDBOX)
          .setOrderId(mySessionIDData["order_id"])
          .setPaymentSessionId(
            mySessionIDData["payment_session_id"])
          .build();
      return session;
    } on CFException catch (e) {
      print(e.message);
    }
    return null;
  }

  pay() async {
    try {
      var session = await createSession();
      List<CFPaymentModes> components = <CFPaymentModes>[];
      // If you want to set paument mode to be shown
// to customer
      var paymentComponent =
          CFPaymentComponentBuilder()
        .setComponents(components)
        .build();
      // We will set theme of checkout session page like
        //fonts, color
      var theme = CFThemeBuilder()
          .setNavigationBarBackgroundColorColor("#FF0000")
          .setPrimaryFont("Menlo")
          .setSecondaryFont("Futura")
          .build();
      // Create checkout with all the settings
//we have set earlier
      var cfDropCheckoutPayment =
     CFDropCheckoutPaymentBuilder()
          .setSession(session!)
          .setPaymentComponent(paymentComponent)
          .setTheme(theme)
          .build();
      // Launching the payment page

      cfPaymentGatewayService.doPayment(cfDropCheckoutPayment);
    } on CFException catch (e) {
      print(e.message);
    }
  }


}

createSessionID(String orderID) async {
  var headers = {
    'Content-Type': 'application/json',
    'x-client-id': "Your app id of cashfree account" ?? "",
    'x-client-secret': "your app secret of cashfree account" ?? "",
    'x-api-version': '2022-09-01',
    // This is latest version for API
    'x-request-id': 'fluterwings'
  };
  print(headers);
  var request =
      http.Request('POST',
Uri.parse('https://sandbox.cashfree.com/pg/orders'));
  request.body = json.encode({
    "order_amount": 1,
// Order Amount in Rupees
    "order_id": orderID,
// OrderiD created by you it must be unique
    "order_currency": "INR",
// Currency of order like INR,USD
    "customer_details": {
      "customer_id": "customer_id",
// Customer id
      "customer_name": "customer_name",
// Name of customer
      "customer_email": "customer_email@gmail.com",
// Email id of customer
      "customer_phone": "+91 customer_mobile_number"
// Phone Number of customer
    },
    "order_meta": {"notify_url": "https://test.cashfree.com"},
    "order_note": "some order note here"
// If you want to store something extra
  });
  request.headers.addAll(headers);

  http.StreamedResponse response = await request.send();

  if (response.statusCode == 200) {
    // If All the details is correct it will return the
    // response and you can get sessionid for checkout
    return jsonDecode(await response.stream.bytesToString());
  } else {
    print(await response.stream.bytesToString());
    print(response.reasonPhrase);
  }
}

Sunday, March 24, 2024

App Linking in Flutter for Beginners

App Linking:

Suppose we have flutter application in which we are going to implement referral functionality. It mean whenever anyone visit to provided link "https://example.com/register/referral='ABS683H'" then automatic open the installed app which is associated to this link. more

For Android Application

Step 1:

Create a flutter application using this command:   flutter create applinktest  

Step 2:


Go to: android/app/src/main/AndroidMenifest.xml


<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>


<!-- applinking  -->
<meta-data android:name="flutter_deeplinking_enabled"
android:value="true" />
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Accepts URIs that begin with YOUR_SCHEME://YOUR_HOST -->
 <data
  android:scheme="https"
  android:host="your_domain.com"
  android:pathPrefix="/register/" />
 </intent-filter>

Step 3:

Go to github create new repo with the name - ".well-known" and under this create a file with name assetLink.json and paste this code:



[{"relation": ["delegate_permission/common.handle_all_urls"],"target": {"namespace": "android_app","package_name": "com.example.applinktest","sha256_cert_fingerprints": ["..."]}}]

visit this link to get above data if successfully deploy: https://your_github_username.github.io/.well-known/assetlinks.json

Step 4: 

Time to generate SHA256, Go to applinktest/android of your project directory terminal and run this command: ./gradlew signingReport where you can find SHA256.


Step 5: 

Go to this link https://github.com/your_github_username/.well-known/settings/pages:


gith page deploy

page where you can deploy your page

Step 6: 

Create main.dart file like this

import 'package:applinktest/pages/color_app_home_page.dart';
import 'package:applinktest/pages/color_detail_page.dart';
import 'package:applinktest/pages/show_referral.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Deep Linking Flutter',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
        seedColor: Colors.deepPurple
        ),
        // Ensure to set useMaterial3 to true if you're using
        // Material3.
        // useMaterial3: true,
      ),
      defaultTransition: Transition.fade,
      getPages: [
        GetPage(name: '/',
         page: () => const ColorAppHomePage()),
        GetPage(name: '/red',
       page: () => const ColorDetailPage(color: Colors.red)),
        GetPage(name: '/blue',
        page: () => const ColorDetailPage(color: Colors.blue)),
        GetPage(name: '/register',
         page: () => const Showreferral()),
      ],
      initialRoute: '/',
    );
  }
}


Step 7: 

Create show_referral.dart page, you can remove ColorDetailPage().


import 'package:flutter/material.dart';
import 'package:uni_links/uni_links.dart';

class Showreferral extends StatefulWidget {
  const Showreferral({super.key});

  @override
  State<Showreferral> createState() => _ShowreferralState();
}

class _ShowreferralState extends State<Showreferral> {
  String? _referralCode;

  @override
  void initState() {
    super.initState();
    _initDeepLinkListener();
  }

  Future<void> _initDeepLinkListener() async {
    // Initialize the deep link stream
    final initialLink = await getInitialUri();
    _handleDeepLink(initialLink);
    print("initial link: $initialLink");

    // Listen for deep link changes
    uriLinkStream.listen((Uri? uri) {
      _handleDeepLink(uri);
    }, onError: (err) {
      print('Error listening to URI links: $err');
    });
  }

  void _handleDeepLink(Uri? uri) {
        if (uri != null) {
      // Extract the referral code from the deep link
      setState(() {
        _referralCode = uri.queryParameters['referral'];
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text("referral= $_referralCode"),
      ),
    );
  }
}


Make sure to install these dependancies: 


dependencies:
  get: ^4.6.6
  uni_links: ^0.5.1


Now you can build and install your app in physical device and visit this link :

 https://your_github_username.github.io/register/?referral=Abdh647h (paste it in anywhere in mobile and click on it)



hdhhdh


kkk

๐Ÿ’˜ Constructors & Destructors in C++ – Jab GF-BF Ke Life Me Entry Aur Breakup Hota ๐Ÿ’”๐Ÿฅน

Constructors & Destructors in C++ – GF-BF Format ๐Ÿ’ก "Constructor tab call hota jab relationship start hoyi ...