C++-এর মাধ্যমে Google Play Games পরিষেবা ব্যবহার করে প্রমাণীকরণ করা

Firebase-এ তৈরি এবং C++-এ লেখা Android গেমে প্লেয়ারদের সাইন-ইন করাতে আপনি Google Play Games পরিষেবা ব্যবহার করতে পারবেন। Firebase-এর সাথে Google Play Games পরিষেবা সাইন-ইন করতে, প্রথমে Google Play Games-এর মাধ্যমে প্লেয়ারকে সাইন-ইন করান এবং এটি করার সময় একটি OAuth 2.0 অথ কোডের অনুরোধ করুন। তারপর, Firebase ক্রেডেনশিয়াল জেনারেট করতে PlayGamesAuthProvider-এ অথ কোডটি পাস করুন, যা আপনি Firebase-এর সাথে প্রমাণীকরণ করতে ব্যবহার করতে পারবেন।

শুরু করার আগে

আপনি Firebase Authentication ব্যবহার করার আগে, আপনাকে এগুলি করতে হবে:

  • আপনার C++ প্রোজেক্ট রেজিস্টার করুন এবং Firebase ব্যবহার করার জন্য এটি কনফিগার করুন।

    আপনার C++ প্রোজেক্টে আগে থেকেই Firebase ব্যবহার করা হলে, এটি আগেই Firebase-এর জন্য রেজিস্টার ও কনফিগার করা হয়ে গেছে।

  • আপনার C++ প্রোজেক্টে Firebase C++ SDK যোগ করুন।

মনে রাখবেন, আপনার C++ প্রোজেক্টে Firebase যোগ করার জন্য Firebase কনসোল এবং আপনার খোলা C++ প্রোজেক্ট (যেমন, আপনি কনসোল থেকে Firebase কনফিগারেশন ফাইল ডাউনলোড করেন, তারপর সেগুলি আপনার C++ প্রোজেক্টে সরান) দুটিতেই টাস্ক করতে হয়।

আপনার Firebase প্রোজেক্ট সেট-আপ করা

  1. আপনি আগে থেকে না করে থাকলে, আপনার অ্যাপের SHA-1 ফিঙ্গারপ্রিন্ট নির্দিষ্ট করুন।

    1. Firebase কনসোলে, সেটিংস > সাধারণ ট্যাব বিকল্পে যান।

    2. নিচের দিকে স্ক্রল করে আপনার অ্যাপ কার্ডে যান, আপনার Android অ্যাপ বেছে নিন এবং SHA সার্টিফিকেট ফিঙ্গারপ্রিন্ট ফিল্ডে আপনার SHA-1 ফিঙ্গারপ্রিন্ট যোগ করুন।

    আপনি gradle signingReport কমান্ডের মাধ্যমে আপনার সাইনিং সার্টিফিকেটের SHA হ্যাশ পেতে পারেন:

    ./gradlew signingReport

    আপনার অ্যাপের SHA ফিঙ্গারপ্রিন্ট কীভাবে পাবেন সেই বিষয়ে বিস্তারিত জানতে, আপনার ক্লায়েন্টকে যাচাই করা লিঙ্কে যান।

  2. সাইন-ইন পরিষেবা প্রদানকারী হিসেবে Google Play Games চালু করুন:

    1. Firebase কনসোলে, নিরাপত্তা > যাচাইকরণ বিকল্পে যান।

    2. আপনার প্রোজেক্টের ওয়েব সার্ভার ক্লায়েন্ট আইডি ও ক্লায়েন্ট সিক্রেট তৈরি ও সংগ্রহ করুন:

      1. সাইন-ইন পদ্ধতি ট্যাবে, Google সাইন-ইন প্রোভাইডার চালু করুন।

      2. Google সাইন-ইন প্রোভাইডার থেকে ওয়েব সার্ভার ক্লায়েন্ট আইডি ও সিক্রেট কপি করুন।

    3. সাইন-ইন পদ্ধতি ট্যাবে, Play Games সাইন-ইন প্রদানকারী চালু করুন এবং আপনার প্রজেক্টের ওয়েব সার্ভার ক্লায়েন্ট আইডি ও ক্লায়েন্ট সিক্রেট উল্লেখ করুন, যা আপনি আগের ধাপে পেয়েছেন।

আপনার Firebase অ্যাপের তথ্য দিয়ে Play Games services কনফিগার করুন

  1. Google Play কনসোলে, আপনার Google Play অ্যাপ খুলুন অথবা একটি তৈরি করুন।

  2. বাড়ান বিভাগে, Play Games services > সেট-আপ ও ম্যানেজমেন্ট > কনফিগারেশন বিকল্পে ক্লিক করুন।

  3. হ্যাঁ, আমার গেম আগে থেকেই Google API ব্যবহার করে বিকল্পে ক্লিক করুন, তালিকা থেকে আপনার Firebase প্রজেক্ট বেছে নিন এবং তারপর ব্যবহার করুন বিকল্পে ক্লিক করুন।

  4. Play Games services কনফিগারেশন পৃষ্ঠায়, ক্রেডেনশিয়াল যোগ করুন বিকল্পে ক্লিক করুন।

    1. গেম সার্ভার ধরন বেছে নিন।
    2. OAuth ক্লায়েন্ট ফিল্ডে, আপনার প্রোজেক্টের ওয়েব ক্লায়েন্ট আইডি বেছে নিন। সাইন-ইন চালু করার সময় আপনি যে ক্লায়েন্ট আইডি Play Games উল্লেখ করেছিলেন, এটি সেই একই আইডি কিনা তা নিশ্চিত করুন।
    3. আপনার করা পরিবর্তন সেভ করুন।
  5. এখনও Play Games services কনফিগারেশন পৃষ্ঠায়, আবার ক্রেডেনশিয়াল যোগ করুন বিকল্পে ক্লিক করুন।

    1. Android ধরন বেছে নিন।
    2. OAuth ক্লায়েন্ট ফিল্ডে, আপনার প্রোজেক্টের Android ক্লায়েন্ট আইডি বেছে নিন। (আপনি Android ক্লায়েন্ট আইডি দেখতে না পেলে, নিশ্চিত করুন যে আপনি Firebase কনসোলে আপনার গেমের SHA-1 ফিঙ্গারপ্রিন্ট সেট করেছেন।)
    3. আপনার করা পরিবর্তন সেভ করুন।
  6. টেস্টার পৃষ্ঠায়, যে ব্যবহারকারীদের Play Store-এ গেম রিলিজ করার আগে আপনার গেমে সাইন-ইন করতে হবে, তাদের ইমেল আইডি যোগ করুন।

আপনার গেমে Play Games সাইন-ইন ইন্টিগ্রেট করা

আপনার গেমে প্লেয়ারদের সাইন-ইন করার সুবিধা দেওয়ার আগে, আপনাকে অবশ্যই Google Play Games সাইন-ইন ইন্টিগ্রেট করতে হবে।

C++ Android প্রোজেক্টে Play Games সাইন-ইন করার সুবিধা যোগ করার সবচেয়ে সহজ ও সাজেস্ট করা উপায় হল Google সাইন-ইন C++ SDK ব্যবহার করা।

Google Sign-in C++ SDK ব্যবহার করে আপনার গেমে Play Games সাইন-ইন যোগ করতে, নিম্নলিখিত কাজগুলি করুন:

  1. Google সাইন-ইন Unity প্লাগ-ইন রিপোজিটরি ক্লোন বা ডাউনলোড করুন, যেখানে C++ SDK-ও আছে।

  2. staging/native/ ডিরেক্টরিতে থাকা প্রোজেক্টটি Android Studio বা gradlew build ব্যবহার করে বিল্ড করুন।

    বিল্ড, google-signin-cpp নামের ডিরেক্টরিতে এর আউটপুট কপি করে।

  3. আপনার গেমের নেটিভ কোড মেক ফাইলে Google Sign-in C++ SDK যোগ করুন:

    CMake

    আপনার টপ-লেভেল CMakeLists.txt ফাইলে:

    set(GSI_PACKAGE_DIR "/path/to/google-signin-cpp")
    add_library(lib-google-signin-cpp STATIC IMPORTED) set_target_properties(lib-google-signin-cpp PROPERTIES IMPORTED_LOCATION     ${GSI_PACKAGE_DIR}/lib/${ANDROID_ABI}/libgoogle-signin-cpp.a )
    ...
    target_link_libraries(     ...     lib-google-signin-cpp)

    ndk-build

    আপনার Android.mk ফাইলে:

    include $(CLEAR_VARS)
    LOCAL_MODULE := google-signin-cpp
    GSI_SDK_DIR := /path/to/google-signin-cpp
    LOCAL_SRC_FILES := $(GSI_SDK_DIR)/lib/$(TARGET_ARCH_ABI)/libgoogle-signin-cpp.a
    LOCAL_EXPORT_C_INCLUDES := $(GSI_SDK_DIR)/include
    include $(PREBUILT_STATIC_LIBRARY)

  4. এরপরে, C++ SDK-এর জন্য প্রয়োজনীয় Java হেল্পার কম্পোনেন্ট যোগ করুন।

    এটি করতে, আপনার প্রোজেক্ট-লেভেল build.gradle ফাইলে, SDK বিল্ড আউটপুট ডিরেক্টরিকে লোকাল রিপোজিটরি হিসেবে যোগ করুন:

    allprojects {
        repositories {
            // ...
            flatDir {
                dirs 'path/to/google-signin-cpp'
            }
        }
    }
    

    এবং, আপনার মডিউল-লেভেল build.gradle ফাইলে, হেল্পার কম্পোনেন্টকে ডিপেন্ডেন্সি হিসেবে ঘোষণা করুন:

    dependencies {
        implementation 'com.google.android.gms:play-services-auth:22.0.0'
        // Depend on the AAR built with the Google Sign-in SDK in order to add
        // the Java helper classes, which are used by the C++ library.
        compile(name:'google-signin-cpp-release', ext:'aar')
    }
    
  5. তারপরে, আপনার গেমে, Play Games সাইন-ইন ব্যবহার করতে এবং সার্ভার অথ কোড রিট্রিভ করতে একটি GoogleSignIn অবজেক্ট কনফিগার করুন:

    #include "google_signin.h"
    #include "future.h"
    
    using namespace google::signin;
    
    // ...
    
    GoogleSignIn::Configuration config = {};
    config.web_client_id = "YOUR_WEB_CLIENT_ID_HERE";
    config.request_id_token = false;
    config.use_game_signin = true;
    config.request_auth_code = true;
    
    GoogleSignIn gsi = GoogleSignIn(GetActivity(), GetJavaVM());
    gsi.Configure(config);
    
  6. সবশেষে, Play Games-এ প্লেয়ারকে সাইন-ইন করাতে SignIn()-কে কল করুন:

    Future<GoogleSignIn::SignInResult> &future = gsi.SignIn();
    

    SignIn()-এর মাধ্যমে রিটার্ন করা Future সমাধান হয়ে গেলে, আপনি ফলাফল থেকে সার্ভার অথ কোড পেতে পারেন:

    if (!future.Pending()) {
        const GoogleSignIn::StatusCode status =
                static_cast<GoogleSignIn::StatusCode>(future.Status());
        if (status == GoogleSignIn::kStatusCodeSuccess) {
            // Player successfully signed in to Google Play! Get auth code to
            //   pass to Firebase
            const GoogleSignIn::SignInResult result =
                    static_cast<GoogleSignIn::SignInResult>(future.Result());
            const char* server_auth_code = result.User.GetServerAuthCode();
        }
    }
    

Firebase-এর মাধ্যমে যাচাইকরণ

প্লেয়ার Play Games-এ সাইন-ইন করার পরে, আপনি Firebase-এর সাথে প্রমাণীকরণ করতে অথ কোড ব্যবহার করতে পারবেন।

  1. প্লেয়ার Play Games ব্যবহার করে সফলভাবে সাইন-ইন করার পরে, প্লেয়ারের অ্যাকাউন্টের জন্য একটি auth কোড পান।

  2. তারপর, Firebase ক্রেডেনশিয়ালের জন্য Play Games পরিষেবা থেকে পাওয়া অথ কোডটি এক্সচেঞ্জ করুন এবং প্লেয়ারকে যাচাই করতে Firebase ক্রেডেনশিয়াল ব্যবহার করুন:

    firebase::auth::Credential credential =
        firebase::auth::PlayGamesAuthProvider::GetCredential(server_auth_code);
    firebase::Future<firebase::auth::AuthResult> result =
        auth->SignInAndRetrieveDataWithCredential(credential);
    
  3. আপনার প্রোগ্রামে যদি নিয়মিত আপডেট লুপ চলে (যেমন, প্রতি সেকেন্ডে ৩০ বা ৬০ বার), তাহলে আপনি প্রতি আপডেটে একবার করে Auth::SignInAndRetrieveDataWithCredentialLastResult-এর মাধ্যমে ফলাফল চেক করতে পারেন:

    firebase::Future<firebase::auth::AuthResult> result =
        auth->SignInAndRetrieveDataWithCredentialLastResult();
    if (result.status() == firebase::kFutureStatusComplete) {
      if (result.error() == firebase::auth::kAuthErrorNone) {
        firebase::auth::AuthResult auth_result = *result.result();
        printf("Sign in succeeded for `%s`\n",
               auth_result.user.display_name().c_str());
      } else {
        printf("Sign in failed with error '%s'\n", result.error_message());
      }
    }

    অথবা, আপনার প্রোগ্রাম ইভেন্ট-নির্ভর হলে, আপনি Future-এ কলব্যাক রেজিস্টার করতে পারেন।

Future-এ কলব্যাক রেজিস্টার করা

কিছু প্রোগ্রামে Update ফাংশন আছে যা প্রতি সেকেন্ডে ৩০ বা ৬০ বার কল করা হয়। যেমন, অনেক গেম এই মডেল অনুসরণ করে। অ্যাসিঙ্ক্রোনাস কল পোল করার জন্য এইসব প্রোগ্রাম LastResult ফাংশন কল করতে পারে। তবে, আপনার প্রোগ্রাম ইভেন্ট-নির্ভর হলে, আপনি কলব্যাক ফাংশন রেজিস্টার করতে পারেন। Future সম্পূর্ণ হলে কলব্যাক ফাংশন কল করা হয়।
void OnCreateCallback(const firebase::Future<firebase::auth::User*>& result,
                      void* user_data) {
  // The callback is called when the Future enters the `complete` state.
  assert(result.status() == firebase::kFutureStatusComplete);

  // Use `user_data` to pass-in program context, if you like.
  MyProgramContext* program_context = static_cast<MyProgramContext*>(user_data);

  // Important to handle both success and failure situations.
  if (result.error() == firebase::auth::kAuthErrorNone) {
    firebase::auth::User* user = *result.result();
    printf("Create user succeeded for email %s\n", user->email().c_str());

    // Perform other actions on User, if you like.
    firebase::auth::User::UserProfile profile;
    profile.display_name = program_context->display_name;
    user->UpdateUserProfile(profile);

  } else {
    printf("Created user failed with error '%s'\n", result.error_message());
  }
}

void CreateUser(firebase::auth::Auth* auth) {
  // Callbacks work the same for any firebase::Future.
  firebase::Future<firebase::auth::AuthResult> result =
      auth->CreateUserWithEmailAndPasswordLastResult();

  // `&my_program_context` is passed verbatim to OnCreateCallback().
  result.OnCompletion(OnCreateCallback, &my_program_context);
}
আপনি চাইলে কলব্যাক ফাংশন ল্যামডা হিসেবেও ব্যবহার করতে পারেন।
void CreateUserUsingLambda(firebase::auth::Auth* auth) {
  // Callbacks work the same for any firebase::Future.
  firebase::Future<firebase::auth::AuthResult> result =
      auth->CreateUserWithEmailAndPasswordLastResult();

  // The lambda has the same signature as the callback function.
  result.OnCompletion(
      [](const firebase::Future<firebase::auth::User*>& result,
         void* user_data) {
        // `user_data` is the same as &my_program_context, below.
        // Note that we can't capture this value in the [] because std::function
        // is not supported by our minimum compiler spec (which is pre C++11).
        MyProgramContext* program_context =
            static_cast<MyProgramContext*>(user_data);

        // Process create user result...
        (void)program_context;
      },
      &my_program_context);
}

পরবর্তী ধাপ

কোনও ব্যবহারকারী প্রথমবার সাইন-ইন করার পরে, একটি নতুন ব্যবহারকারীর অ্যাকাউন্ট তৈরি করা হয় এবং সেটি তার Play Games আইডির সাথে লিঙ্ক করা হয়। এই নতুন অ্যাকাউন্টটি আপনার Firebase প্রোজেক্টের অংশ হিসেবে স্টোর করা হয় এবং আপনার প্রোজেক্টের প্রতিটি অ্যাপ জুড়ে কোনও ব্যবহারকারীকে শনাক্ত করতে এটি ব্যবহার করা যেতে পারে।

আপনার গেমে, আপনি firebase::auth::User অবজেক্ট থেকে ব্যবহারকারীর Firebase UID পেতে পারেন:

firebase::auth::User user = auth->current_user();
if (user.is_valid()) {
  std::string playerName = user.displayName();

  // The user's ID, unique to the Firebase project.
  // Do NOT use this value to authenticate with your backend server,
  // if you have one. Use firebase::auth::User::Token() instead.
  std::string uid = user.uid();
}

আপনার Firebase Realtime Database এবং Cloud Storage Security Rules-এ, আপনি auth ভেরিয়েবল থেকে সাইন-ইন করা ব্যবহারকারীর অনন্য ব্যবহারকারী আইডি পেতে এবং কোন ডেটা ব্যবহারকারী অ্যাক্সেস করতে পারবেন তা নিয়ন্ত্রণ করতে এটি ব্যবহার করতে পারবেন।

কোনও ব্যবহারকারীর Play Games প্লেয়ার সংক্রান্ত তথ্য পেতে বা Play Games পরিষেবা অ্যাক্সেস করতে, Google Play Games পরিষেবা C++ SDK-এর দেওয়া API ব্যবহার করুন।

কোনও ব্যবহারকারীকে সাইন-আউট করতে, SignOut()-এ কল করুন:

auth->SignOut();