আপনার Parse Android অ্যাপ Firebase-এ মাইগ্রেট করা

আপনি যদি একজন Parse ব্যবহারকারী হন এবং একটি বিকল্প ব্যাকএন্ড অ্যাজ এ পরিষেবা সমাধান খুঁজছেন, তাহলে Firebase আপনার Android অ্যাপের জন্য আদর্শ পছন্দ হতে পারে।

এই নির্দেশিকায় আপনার অ্যাপে নির্দিষ্ট পরিষেবা কীভাবে ইন্টিগ্রেট করবেন তা বর্ণনা করা হয়েছে। সাধারণ Firebase সেট-আপের নির্দেশিকা জানতে, Android সেট-আপ নির্দেশিকা দেখুন।

Google Analytics

Google Analytics হল একটি ফ্রি অ্যাপ মেজারমেন্ট সলিউশন যা অ্যাপের ব্যবহার এবং ব্যবহারকারীর এনগেজমেন্ট সম্পর্কে ইনসাইট প্রদান করে। Analytics Firebase-এর বিভিন্ন ফিচারের সাথে ইন্টিগ্রেট করে এবং Firebase SDK ব্যবহার করে আপনি যে ৫০০টি আলাদা আলাদা ইভেন্টকে সংজ্ঞায়িত করতে পারেন, সেগুলির জন্য আপনাকে আনলিমিটেড রিপোর্টিং প্রদান করে।

আরও জানতে Google Analytics ডকুমেন্ট দেখুন।

মাইগ্রেশন সংক্রান্ত সাজেস্ট করা স্ট্র্যাটেজি

বিভিন্ন অ্যানালিটিক্স পরিষেবা প্রদানকারী ব্যবহার করা একটি সাধারণ দৃশ্য যা সহজেই Google Analytics-এ প্রযোজ্য। ইভেন্ট ও ব্যবহারকারীর প্রপার্টি থেকে সুবিধা পেতে, আপনার অ্যাপে এটি যোগ করুন। Analytics প্রথমবার খোলা, অ্যাপ আপডেট, ডিভাইস মডেল, বয়স ইত্যাদি তথ্য অটোমেটিক সংগ্রহ করা হয়।

কাস্টম ইভেন্ট ও ব্যবহারকারীর প্রপার্টির জন্য, আপনি ইভেন্ট ও প্রপার্টি লগ করতে Parse Analytics ও Google Analytics, দুটিই ব্যবহার করে ডবল রাইট স্ট্র্যাটেজি প্রয়োগ করতে পারেন, যা আপনাকে নতুন সমাধান ধীরে ধীরে প্রকাশ করতে দেয়।

কোডের তুলনা

Parse Analytics

// Start collecting data
ParseAnalytics.trackAppOpenedInBackground(getIntent());

Map<String, String> dimensions = new HashMap<String, String>();
// Define ranges to bucket data points into meaningful segments
dimensions.put("priceRange", "1000-1500");
// Did the user filter the query?
dimensions.put("source", "craigslist");
// Do searches happen more often on weekdays or weekends?
dimensions.put("dayType", "weekday");

// Send the dimensions to Parse along with the 'search' event
ParseAnalytics.trackEvent("search", dimensions);

Google Analytics

// Obtain the FirebaseAnalytics instance and start collecting data
mFirebaseAnalytics = FirebaseAnalytics.getInstance(this);

Bundle params = new Bundle();
// Define ranges to bucket data points into meaningful segments
params.putString("priceRange", "1000-1500");
// Did the user filter the query?
params.putString("source", "craigslist");
// Do searches happen more often on weekdays or weekends?
params.putString("dayType", "weekday");

// Send the event
mFirebaseAnalytics.logEvent("search", params);

Firebase Realtime Database

Firebase Realtime Database হল NoSQL ক্লাউড-হোস্টেড ডেটাবেস। ডেটা JSON হিসেবে সেভ করা হয় এবং কানেক্ট করা প্রতিটি ক্লায়েন্টের সাথে রিয়েল-টাইমে সিঙ্ক করা হয়।

আরও জানতে Firebase Realtime Database ডকুমেন্ট দেখুন।

পার্স করা ডেটার সাথে পার্থক্য

জিনিসপত্র

Parse-এ আপনি ParseObject বা এর সাবক্লাস স্টোর করেন, যাতে JSON-এর সাথে মানানসই ডেটার কী-ভ্যালু পেয়ার থাকে। ডেটা স্কিমাহীন, যার অর্থ হল প্রতিটি ParseObject-এ কোন কী আছে তা আপনাকে নির্দিষ্ট করতে হবে না।

সব Firebase Realtime Database ডেটা JSON অবজেক্ট হিসেবে স্টোর করা হয় এবং ParseObject-এর সমতুল্য কিছু নেই; আপনি শুধু JSON ট্রি-তে এমন ধরনের ভ্যালু লেখেন যা উপলভ্য JSON ধরনের সাথে মেলে। ডেটাবেস থেকে পড়া ও লেখার কাজ সহজ করতে আপনি Java অবজেক্ট ব্যবহার করতে পারেন।

কোনও গেমের জন্য আপনি কীভাবে উচ্চ স্কোর সেভ করতে পারেন তার একটি উদাহরণ নিচে দেওয়া হল।

পার্স করুন
@ParseClassName("GameScore")
public class GameScore {
        public GameScore() {}
        public GameScore(Long score, String playerName, Boolean cheatMode) {
            setScore(score);
            setPlayerName(playerName);
            setCheatMode(cheatMode);
        }

        public void setScore(Long score) {
            set("score", score);
        }

        public Long getScore() {
            return getLong("score");
        }

        public void setPlayerName(String playerName) {
            set("playerName", playerName);
        }

        public String getPlayerName() {
            return getString("playerName");
        }

        public void setCheatMode(Boolean cheatMode) {
            return set("cheatMode", cheatMode);
        }

        public Boolean getCheatMode() {
            return getBoolean("cheatMode");
        }
}

// Must call Parse.registerSubclass(GameScore.class) in Application.onCreate
GameScore gameScore = new GameScore(1337, "Sean Plott", false);
gameScore.saveInBackground();
Firebase
// Assuming we defined the GameScore class as:
public class GameScore {
        private Long score;
        private String playerName;
        private Boolean cheatMode;

        public GameScore() {}
        public GameScore(Long score, String playerName, Boolean cheatMode) {
            this.score = score;
            this.playerName = playerName;
            this.cheatMode = cheatMode;
        }

        public Long getScore() {
            return score;
        }

        public String getPlayerName() {
            return playerName;
        }

        public Boolean getCheatMode() {
            return cheatMode;
        }
}

// We would save it to our list of high scores as follows:
DatabaseReference mFirebaseRef = FirebaseDatabase.getInstance().getReference();
GameScore score = new GameScore(1337, "Sean Plott", false);
mFirebaseRef.child("scores").push().setValue(score);
আরও বিবরণের জন্য, Android-এ ডেটা পড়া ও লেখা সংক্রান্ত নির্দেশিকা চেক করুন।

ডেটার মধ্যে সম্পর্ক

একটি ParseObject-এর সাথে অন্য একটি ParseObject-এর সম্পর্ক থাকতে পারে: যেকোনও অবজেক্ট অন্য অবজেক্টকে ভ্যালু হিসেবে ব্যবহার করতে পারে।

Firebase Realtime Database-এ, ফ্ল্যাট ডেটা স্ট্রাকচার ব্যবহার করে সম্পর্কগুলি আরও ভালভাবে প্রকাশ করা হয় যা ডেটাকে আলাদা আলাদা পাথে বিভক্ত করে, যাতে আলাদা আলাদা কলে সেগুলি দক্ষতার সাথে ডাউনলোড করা যায়।

ব্লগিং অ্যাপে পোস্ট এবং তাদের লেখকদের মধ্যে সম্পর্ক কীভাবে গঠন করবেন তার একটি উদাহরণ নিচে দেওয়া হল।

পার্স করা
// Create the author
ParseObject myAuthor = new ParseObject("Author");
myAuthor.put("name", "Grace Hopper");
myAuthor.put("birthDate", "December 9, 1906");
myAuthor.put("nickname", "Amazing Grace");

// Create the post
ParseObject myPost = new ParseObject("Post");
myPost.put("title", "Announcing COBOL, a New Programming Language");

// Add a relation between the Post and the Author
myPost.put("parent", myAuthor);

// This will save both myAuthor and myPost
myPost.saveInBackground();
Firebase
DatabaseReference firebaseRef = FirebaseDatabase.getInstance().getReference();
// Create the author
Map<String, String> myAuthor = new HashMap<String, String>();
myAuthor.put("name", "Grace Hopper");
myAuthor.put("birthDate", "December 9, 1906");
myAuthor.put("nickname", "Amazing Grace");

// Save the author
String myAuthorKey = "ghopper";
firebaseRef.child('authors').child(myAuthorKey).setValue(myAuthor);

// Create the post
Map<String, String> post = new HashMap<String, String>();
post.put("author", myAuthorKey);
post.put("title", "Announcing COBOL, a New Programming Language");
firebaseRef.child('posts').push().setValue(post);

নিম্নলিখিত ডেটা লে-আউট হল ফলাফল।

{
  // Info about the authors
  "authors": {
    "ghopper": {
      "name": "Grace Hopper",
      "date_of_birth": "December 9, 1906",
      "nickname": "Amazing Grace"
    },
    ...
  },
  // Info about the posts: the "author" fields contains the key for the author
  "posts": {
    "-JRHTHaIs-jNPLXOQivY": {
      "author": "ghopper",
      "title": "Announcing COBOL, a New Programming Language"
    }
    ...
  }
}
আরও বিবরণের জন্য, এই আপনার ডেটাবেস স্ট্রাকচার করুন গাইড দেখুন।

রিডিং ডেটা

Parse-এ, আপনি নির্দিষ্ট Parse অবজেক্টের আইডি ব্যবহার করে ডেটা পড়েন অথবা ParseQuery ব্যবহার করে কোয়েরি এক্সিকিউট করেন।

Firebase-এ, আপনি কোনও ডেটাবেস রেফারেন্সে অ্যাসিঙ্ক্রোনাস লিসনার অ্যাটাচ করে ডেটা রিট্রিভ করেন। ডেটার প্রাথমিক অবস্থার জন্য লিসনার একবার ট্রিগার হয় এবং ডেটা পরিবর্তিত হলে আবার ট্রিগার হয়। তাই ডেটা পরিবর্তিত হয়েছে কিনা তা নির্ধারণ করার জন্য আপনাকে কোনও কোড যোগ করতে হবে না।

"অবজেক্ট" বিভাগে দেখানো উদাহরণের ভিত্তিতে, আপনি কীভাবে কোনও নির্দিষ্ট প্লেয়ারের স্কোর রিট্রিভ করতে পারবেন, তার উদাহরণ নিচে দেওয়া হল।

পার্স করুন
ParseQuery<ParseObject> query = ParseQuery.getQuery("GameScore");
query.whereEqualTo("playerName", "Dan Stemkoski");
query.findInBackground(new FindCallback<ParseObject>() {
    public void done(List<ParseObject> scoreList, ParseException e) {
        if (e == null) {
            for (ParseObject score: scoreList) {
                Log.d("score", "Retrieved: " + Long.toString(score.getLong("score")));
            }
        } else {
            Log.d("score", "Error: " + e.getMessage());
        }
    }
});
Firebase
DatabaseReference mFirebaseRef = FirebaseDatabase.getInstance().getReference();
Query mQueryRef = mFirebaseRef.child("scores").orderByChild("playerName").equalTo("Dan Stemkoski");

// This type of listener is not one time, and you need to cancel it to stop
// receiving updates.
mQueryRef.addChildEventListener(new ChildEventListener() {
    @Override
    public void onChildAdded(DataSnapshot snapshot, String previousChild) {
        // This will fire for each matching child node.
        GameScore score = snapshot.getValue(GameScore.class);
        Log.d("score", "Retrieved: " + Long.toString(score.getScore());
    }
});
উপলভ্য ধরনের ইভেন্ট লিসেনার এবং ডেটা কীভাবে অর্ডার ও ফিল্টার করতে হয় সেই সম্পর্কে আরও জানতে, Android-এ ডেটা পড়ুন ও লিখুন গাইড দেখুন।

মাইগ্রেশনের জন্য সাজেস্ট করা স্ট্র্যাটেজি

আপনার ডেটা নিয়ে নতুন করে ভাবুন

Firebase Realtime Database সবকটি কানেক্ট করা ক্লায়েন্ট জুড়ে মিলিসেকেন্ডে ডেটা সিঙ্ক করার জন্য অপ্টিমাইজ করা হয় এবং এর ফলে যে ডেটা স্ট্রাকচার তৈরি হয় তা Parse কোড ডেটা থেকে আলাদা হয়। এর অর্থ হল, মাইগ্রেশনের প্রথম ধাপ হল আপনার ডেটায় কী কী পরিবর্তন করতে হবে তা বিবেচনা করা, যার মধ্যে রয়েছে:

  • আপনার Parse অবজেক্ট কীভাবে Firebase ডেটাতে ম্যাপ করা উচিত
  • আপনার যদি পেরেন্ট-চাইল্ড রিলেশন থাকে, তাহলে কীভাবে বিভিন্ন পাথ জুড়ে আপনার ডেটা স্প্লিট করবেন যাতে এটি আলাদা কলে দক্ষতার সাথে ডাউনলোড করা যায়।

আপনার ডেটা মাইগ্রেট করা

Firebase-এ ডেটা কীভাবে স্ট্রাকচার করবেন তা ঠিক করার পরে, আপনাকে পরিকল্পনা করতে হবে যে কীভাবে সেই সময়সীমা ম্যানেজ করবেন যখন আপনার অ্যাপকে দুটি ডেটাবেসেই লিখতে হবে। আপনার পছন্দগুলি হল:

ব্যাকগ্রাউন্ড সিঙ্ক

এই পরিস্থিতিতে, আপনার কাছে অ্যাপের দুটি ভার্সন আছে: পুরনো ভার্সন যা Parse ব্যবহার করে এবং নতুন ভার্সন যা Firebase ব্যবহার করে। দুটি ডেটাবেসের মধ্যে সিঙ্ক করার কাজটি Parse Cloud Code (Parse থেকে Firebase) দ্বারা পরিচালিত হয়। আপনার কোড Firebase-এ হওয়া পরিবর্তনগুলি শোনে এবং সেইসব পরিবর্তন Parse-এর সাথে সিঙ্ক করে। নতুন ভার্সন ব্যবহার শুরু করার আগে, আপনাকে অবশ্যই:

  • আপনার আগে থেকে থাকা পার্স ডেটা নতুন Firebase স্ট্রাকচারে কনভার্ট করুন এবং এটি Firebase Realtime Database-এ লিখুন।
  • Firebase REST API ব্যবহার করে Parse Cloud Code ফাংশন লিখুন যা Firebase Realtime Database পুরনো ক্লায়েন্টদের দ্বারা Parse ডেটাতে করা পরিবর্তনগুলি লেখে।
  • Firebase-এ হওয়া পরিবর্তনগুলি শোনে এবং সেগুলিকে Parse ডেটাবেসে সিঙ্ক করে এমন কোড লিখুন এবং ডিপ্লয় করুন।

এই পরিস্থিতিতে পুরনো ও নতুন কোড আলাদা করা নিশ্চিত করা হয় এবং ক্লায়েন্টকে সহজ রাখা হয়। এই পরিস্থিতির চ্যালেঞ্জ হল, প্রাথমিক এক্সপোর্ট করার সময় বড় ডেটাসেট ম্যানেজ করা এবং দ্বিমুখী সিঙ্ক যাতে অসীম রিকার্সন তৈরি না করে তা নিশ্চিত করা।

ডবল রাইট

এই পরিস্থিতিতে, আপনি অ্যাপের একটি নতুন ভার্সন লেখেন যা Firebase এবং Parse উভয়ই ব্যবহার করে, Parse Cloud Code ব্যবহার করে পুরনো ক্লায়েন্টদের করা পরিবর্তনগুলি Parse Data থেকে Firebase Realtime Database-এ সিঙ্ক করে। Parse-only ভার্সন থেকে যথেষ্ট সংখ্যক লোক মাইগ্রেট করে গেলে, আপনি ডবল রাইট ভার্সন থেকে Parse কোড সরিয়ে দিতে পারবেন।

এই পরিস্থিতিতে কোনও সার্ভার সাইড কোডের প্রয়োজন নেই। এর অসুবিধা হল, যে ডেটা অ্যাক্সেস করা হয়নি তা মাইগ্রেট করা হয় না এবং দুটি SDK ব্যবহার করার কারণে আপনার অ্যাপের সাইজ বেড়ে যায়।

Firebase Authentication

Firebase Authentication পাসওয়ার্ড এবং Google, Facebook ও Twitter-এর মতো জনপ্রিয় ফেডারেটেড পরিচয় প্রদানকারীর মাধ্যমে ব্যবহারকারীদের যাচাই করতে পারে। এছাড়াও, এটি UI লাইব্রেরি প্রদান করে যা আপনাকে সমস্ত প্ল্যাটফর্ম জুড়ে আপনার অ্যাপের জন্য সম্পূর্ণ যাচাইকরণ অভিজ্ঞতা প্রয়োগ ও বজায় রাখার জন্য প্রয়োজনীয় উল্লেখযোগ্য ইনভেস্টমেন্ট থেকে বাঁচায়।

আরও জানতে Firebase Authentication ডকুমেন্ট দেখুন।

Parse Auth-এর সাথে পার্থক্য

Parse, ParseUser নামে একটি বিশেষ ব্যবহারকারী ক্লাস প্রদান করে যা ব্যবহারকারীর অ্যাকাউন্ট ম্যানেজমেন্টের জন্য প্রয়োজনীয় কার্যকারিতা অটোমেটিক ম্যানেজ করে। ParseUser হল ParseObject-এর সাবক্লাস, যার অর্থ হল ব্যবহারকারীর ডেটা পার্স ডেটাতে উপলভ্য এবং অন্য যেকোনও ParseObject-এর মতো অতিরিক্ত ফিল্ডের সাথে বাড়ানো যেতে পারে।

FirebaseUser-এর নির্দিষ্ট কিছু প্রাথমিক প্রপার্টি থাকে—একটি অনন্য আইডি, একটি প্রাথমিক ইমেল আইডি, নাম ও ফটো URL—যা আলাদা প্রজেক্টের ব্যবহারকারীর ডেটাবেসে সেভ করা থাকে; সেইসব প্রপার্টি ব্যবহারকারী আপডেট করতে পারেন। আপনি সরাসরি FirebaseUser অবজেক্টে অন্যান্য প্রপার্টি যোগ করতে পারবেন না; পরিবর্তে, আপনি অতিরিক্ত প্রপার্টি আপনার Firebase Realtime Database-এ স্টোর করতে পারবেন।

আপনি কীভাবে কোনও ব্যবহারকারীকে সাইন-আপ করতে এবং অতিরিক্ত ফোন নম্বর ফিল্ড যোগ করতে পারেন তার একটি উদাহরণ নিচে দেওয়া হল।

পার্স করুন
ParseUser user = new ParseUser();
user.setUsername("my name");
user.setPassword("my pass");
user.setEmail("email@example.com");

// other fields can be set just like with ParseObject
user.put("phone", "650-253-0000");

user.signUpInBackground(new SignUpCallback() {
    public void done(ParseException e) {
        if (e == null) {
            // Hooray! Let them use the app now.
        } else {
            // Sign up didn't succeed. Look at the ParseException
            // to figure out what went wrong
        }
    }
});
Firebase
FirebaseAuth mAuth = FirebaseAuth.getInstance();

mAuth.createUserWithEmailAndPassword("email@example.com", "my pass")
    .continueWithTask(new Continuation<AuthResult, Task<Void>> {
        @Override
        public Task<Void> then(Task<AuthResult> task) {
            if (task.isSuccessful()) {
                FirebaseUser user = task.getResult().getUser();
                DatabaseReference firebaseRef = FirebaseDatabase.getInstance().getReference();
                return firebaseRef.child("users").child(user.getUid()).child("phone").setValue("650-253-0000");
            } else {
                // User creation didn't succeed. Look at the task exception
                // to figure out what went wrong
                Log.w(TAG, "signInWithEmail", task.getException());
            }
        }
    });

মাইগ্রেশনের জন্য সাজেস্ট করা স্ট্র্যাটেজি

অ্যাকাউন্ট মাইগ্রেট করা

Parse থেকে Firebase-এ ব্যবহারকারীর অ্যাকাউন্ট মাইগ্রেট করতে, আপনার ব্যবহারকারীর ডেটাবেস JSON বা CSV ফাইলে এক্সপোর্ট করুন, তারপর Firebase CLI-এর auth:import কমান্ড ব্যবহার করে আপনার Firebase প্রোজেক্টে ফাইলটি ইমপোর্ট করুন।

প্রথমে, Parse কনসোল বা আপনার সেল্ফ-হোস্টেড ডেটাবেস থেকে ব্যবহারকারীর ডেটাবেস এক্সপোর্ট করুন। যেমন, Parse কনসোল থেকে এক্সপোর্ট করা JSON ফাইলটি নিম্নলিখিতগুলির মতো দেখতে হতে পারে:

{ // Username/password user
  "bcryptPassword": "$2a$10$OBp2hxB7TaYZgKyTiY48luawlTuYAU6BqzxJfpHoJMdZmjaF4HFh6",
  "email": "user@example.com",
  "username": "testuser",
  "objectId": "abcde1234",
  ...
},
{ // Facebook user
  "authData": {
    "facebook": {
      "access_token": "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
      "expiration_date": "2017-01-02T03:04:05.006Z",
      "id": "1000000000"
    }
  },
  "username": "wXyZ987654321StUv",
  "objectId": "fghij5678",
  ...
}

তারপর, Firebase CLI-এর প্রয়োজনীয় ফর্ম্যাটে এক্সপোর্ট করা ফাইলটি ট্রান্সফর্ম করুন। আপনার Parse ব্যবহারকারীদের objectId, Firebase ব্যবহারকারীদের localId হিসেবে ব্যবহার করুন। এছাড়াও, Parse থেকে পাওয়া bcryptPassword ভ্যালু base64 এনকোড করুন এবং passwordHash ফিল্ডে ব্যবহার করুন। যেমন:

{
  "users": [
    {
      "localId": "abcde1234",  // Parse objectId
      "email": "user@example.com",
      "displayName": "testuser",
      "passwordHash": "JDJhJDEwJE9CcDJoeEI3VGFZWmdLeVRpWTQ4bHVhd2xUdVlBVTZCcXp4SmZwSG9KTWRabWphRjRIRmg2",
    },
    {
      "localId": "fghij5678",  // Parse objectId
      "displayName": "wXyZ987654321StUv",
      "providerUserInfo": [
        {
          "providerId": "facebook.com",
          "rawId": "1000000000",  // Facebook ID
        }
      ]
    }
  ]
}

সবশেষে, Firebase CLI-এর মাধ্যমে ট্রান্সফর্ম করা ফাইলটি ইমপোর্ট করুন এবং হ্যাশ অ্যালগরিদম হিসেবে bcrypt নির্দিষ্ট করুন:

firebase auth:import account_file.json --hash-algo=BCRYPT

ব্যবহারকারীর ডেটা মাইগ্রেট করা

আপনি যদি ব্যবহারকারীদের জন্য অতিরিক্ত ডেটা স্টোর করে থাকেন, তাহলে ডেটা মাইগ্রেশন বিভাগে বর্ণিত কৌশল ব্যবহার করে Firebase Realtime Database সেটি মাইগ্রেট করতে পারবেন। আপনি যদি অ্যাকাউন্ট মাইগ্রেশন বিভাগে বর্ণিত ফ্লো ব্যবহার করে অ্যাকাউন্ট মাইগ্রেট করেন, তাহলে আপনার Firebase অ্যাকাউন্টে আপনার Parse অ্যাকাউন্টের মতো একই আইডি থাকবে, যা আপনাকে সহজেই মাইগ্রেট করতে এবং ব্যবহারকারীর আইডি দ্বারা কী করা যেকোনও সম্পর্ক পুনরায় তৈরি করতে দেয়।

Firebase Cloud Messaging

Firebase Cloud Messaging (FCM) হল একটি ক্রস-প্ল্যাটফর্ম মেসেজিং সলিউশন যা আপনাকে নির্ভরযোগ্যভাবে মেসেজ ও বিজ্ঞপ্তি ডেলিভার করতে দেয়, এর জন্য কোনও খরচ লাগে না। বিজ্ঞপ্তি কম্পোজার হল একটি ফ্রি পরিষেবা যা Firebase Cloud Messaging-এ তৈরি করা হয়েছে। এটি মোবাইল অ্যাপ ডেভেলপারদের জন্য টার্গেট করা ব্যবহারকারীর বিজ্ঞপ্তি চালু করে।

আরও জানতে Firebase Cloud Messaging ডকুমেন্ট দেখুন।

Parse পুশ বিজ্ঞপ্তির সাথে পার্থক্য

বিজ্ঞপ্তির জন্য রেজিস্টার করা ডিভাইসে ইনস্টল করা প্রতিটি Parse অ্যাপ্লিকেশনের সাথে একটি Installation অবজেক্ট থাকে, যেখানে আপনি বিজ্ঞপ্তি টার্গেট করার জন্য প্রয়োজনীয় সব ডেটা স্টোর করেন। Installation হল ParseUser-এর একটি সাবক্লাস, যার অর্থ হল আপনি নিজের Installation ইনস্ট্যান্সে যেকোনও অতিরিক্ত ডেটা যোগ করতে পারবেন।

বিজ্ঞপ্তি কম্পোজার অ্যাপ, অ্যাপ ভার্সন ও ডিভাইসের ভাষার মতো তথ্যের উপর ভিত্তি করে আগে থেকে সংজ্ঞায়িত ব্যবহারকারীর বিভাগ প্রদান করে। অডিয়েন্স তৈরি করতে, আপনি Google Analytics ইভেন্ট ও প্রপার্টি ব্যবহার করে আরও জটিল ব্যবহারকারীর সেগমেন্ট তৈরি করতে পারবেন। আরও জানতে দর্শক সম্পর্কিত সহায়তা গাইড দেখুন। এই টার্গেটিং সংক্রান্ত তথ্য Firebase Realtime Database-এ দেখা যায় না।

মাইগ্রেশন সংক্রান্ত সাজেস্ট করা স্ট্র্যাটেজি

ডিভাইস টোকেন মাইগ্রেট করা

লেখার সময়, Parse Android SDK, FCM রেজিস্ট্রেশন টোকেনের পুরনো ভার্সন ব্যবহার করে, যা বিজ্ঞপ্তি কম্পোজারের অফার করা ফিচারের সাথে মানানসই নয়।

আপনার অ্যাপে FCM SDK যোগ করে আপনি নতুন টোকেন পেতে পারেন; তবে, এর ফলে Parse SDK-এর মাধ্যমে বিজ্ঞপ্তি পাওয়ার জন্য ব্যবহৃত টোকেনটি বাতিল হয়ে যেতে পারে। আপনি যদি এটি এড়াতে চান, তাহলে Parse-এর প্রেরক আইডি এবং আপনার প্রেরক আইডি, দুটিই ব্যবহার করার জন্য Parse SDK সেট-আপ করতে পারেন। এইভাবে আপনি Parse SDK-এর ব্যবহার করা টোকেন বাতিল করেন না, তবে মনে রাখবেন যে Parse তার প্রোজেক্ট বন্ধ করে দিলে এই সমাধান কাজ করা বন্ধ করে দেবে।

FCMটি বিষয়ে চ্যানেল মাইগ্রেট করা হচ্ছে

আপনি বিজ্ঞপ্তি পাঠানোর জন্য Parse চ্যানেল ব্যবহার করলে, FCM টপিকে মাইগ্রেট করতে পারবেন, যা একই প্রকাশক-সাবস্ক্রাইবার মডেল প্রদান করে। Parse থেকে FCM-এ ট্রানজিশন ম্যানেজ করতে, আপনি অ্যাপের একটি নতুন ভার্সন লিখতে পারেন যা Parse চ্যানেল থেকে আনসাবস্ক্রাইব করতে Parse SDK এবং সংশ্লিষ্ট FCM টপিকে সাবস্ক্রাইব করতে FCM SDK ব্যবহার করে। অ্যাপের এই ভার্সনে আপনাকে Parse SDK-তে বিজ্ঞপ্তি পাওয়া বন্ধ করতে হবে। এর জন্য অ্যাপের মেনিফেস্ট থেকে নিম্নলিখিত বিষয়গুলি সরিয়ে দিন:

<service android:name="com.parse.PushService" />
<receiver android:name="com.parse.ParsePushBroadcastReceiver"
  android:exported="false">
<intent-filter>
<action android:name="com.parse.push.intent.RECEIVE" />
<action android:name="com.parse.push.intent.DELETE" />
<action android:name="com.parse.push.intent.OPEN" />
</intent-filter>
</receiver>
<receiver android:name="com.parse.GcmBroadcastReceiver"
  android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />

<!--
IMPORTANT: Change "com.parse.starter" to match your app's package name.
-->
<category android:name="com.parse.starter" />
</intent-filter>
</receiver>

<!--
IMPORTANT: Change "YOUR_SENDER_ID" to your GCM Sender Id.
-->
<meta-data android:name="com.parse.push.gcm_sender_id"
  android:value="id:YOUR_SENDER_ID" />;

যেমন, আপনার ব্যবহারকারী "Giants" বিষয়ে সাবস্ক্রাইব করলে, আপনি এই ধরনের কিছু করতে পারেন:

ParsePush.unsubscribeInBackground("Giants", new SaveCallback() {
    @Override
    public void done(ParseException e) {
        if (e == null) {
            FirebaseMessaging.getInstance().subscribeToTopic("Giants");
        } else {
            // Something went wrong unsubscribing
        }
    }
});

এই স্ট্র্যাটেজি ব্যবহার করে, আপনি Parse চ্যানেল এবং সংশ্লিষ্ট FCM বিষয়ে মেসেজ পাঠাতে পারবেন, যা পুরনো ও নতুন ভার্সনের ব্যবহারকারীদের সাহায্য করবে। অ্যাপের শুধু-পার্স ভার্সন থেকে পর্যাপ্ত সংখ্যক ব্যবহারকারী মাইগ্রেট করে গেলে, আপনি সেই ভার্সন বন্ধ করে দিতে পারেন এবং শুধু FCM ব্যবহার করে পাঠানো শুরু করতে পারেন।

আরও জানতে FCM বিষয় সংক্রান্ত ডকুমেন্ট দেখুন।

Firebase Remote Config

Firebase Remote Config হল একটি ক্লাউড পরিষেবা যা ব্যবহারকারীদের জন্য কোনও অ্যাপ আপডেট ডাউনলোড করার প্রয়োজন ছাড়াই আপনাকে নিজের অ্যাপ কীভাবে কাজ করবে তা এবং এটির লেআউট পরিবর্তন করতে দেয়। রিমোট কনফিগ ব্যবহার করার সময়, আপনি অ্যাপ-মধ্যস্থ ডিফল্ট ভ্যালু তৈরি করেন যা আপনার অ্যাপের আচরণ ও চেহারা নিয়ন্ত্রণ করে। তারপর, আপনি পরে Firebase কনসোল ব্যবহার করে অ্যাপ ব্যবহারকারী সকলের জন্য বা আপনার ব্যবহারকারীর বেসের সেগমেন্টের জন্য অ্যাপ-মধ্যস্থ ডিফল্ট ভ্যালু ওভাররাইড করতে পারবেন।

আপনি যদি বিভিন্ন সমাধান পরীক্ষা করতে চান এবং আরও ক্লায়েন্টকে অন্য প্রদানকারীর কাছে ডাইনামিকভাবে শিফট করতে চান, তাহলে মাইগ্রেশনের সময় Firebase Remote Config খুব উপযোগী হতে পারে। যেমন, আপনার অ্যাপের এমন কোনও ভার্সন থাকলে যা ডেটার জন্য Firebase ও Parse, দুটিই ব্যবহার করে, তাহলে কোন ক্লায়েন্ট Firebase থেকে ডেটা পড়বে তা নির্ধারণ করতে আপনি র‍্যান্ডম পার্সেন্টাইল নিয়ম ব্যবহার করতে পারেন এবং ধীরে ধীরে শতাংশ বাড়াতে পারেন।

Firebase Remote Config সম্পর্কে আরও জানতে, Remote Config ভূমিকা দেখুন।

পার্স কনফিগারেশনের সাথে পার্থক্য

Parse কনফিগারেশনের মাধ্যমে আপনি Parse কনফিগারেশন ড্যাশবোর্ডে আপনার অ্যাপে কী/ভ্যালু পেয়ার যোগ করতে পারবেন এবং তারপর ক্লায়েন্টে ParseConfig ফেচ করতে পারবেন। আপনি যতগুলি ParseConfig ইনস্ট্যান্স পান সেগুলি সবসময় অপরিবর্তনীয় হয়। ভবিষ্যতে নেটওয়ার্ক থেকে নতুন ParseConfig নিয়ে এলে, এটি আগে থেকে থাকা কোনও ParseConfig ইনস্ট্যান্সকে পরিবর্তন করবে না, তবে এর পরিবর্তে একটি নতুন ইনস্ট্যান্স তৈরি করবে এবং getCurrentConfig()-এর মাধ্যমে এটি উপলভ্য করবে।

Firebase Remote Config-এর মাধ্যমে আপনি কী/ভ্যালু পেয়ারের জন্য ইন-অ্যাপ ডিফল্ট তৈরি করেন যা আপনি Firebase কনসোল থেকে ওভাররাইড করতে পারেন এবং আপনার ব্যবহারকারীর বিভিন্ন অংশের জন্য আপনার অ্যাপের ব্যবহারকারীর অভিজ্ঞতায় বৈচিত্র্য প্রদান করতে আপনি নিয়ম ও শর্তাবলী ব্যবহার করতে পারেন। Firebase Remote Config একটি সিঙ্গেলটন ক্লাস প্রয়োগ করে যা আপনার অ্যাপের জন্য কী/ভ্যালু পেয়ার উপলভ্য করে। প্রাথমিকভাবে সিঙ্গেলটন অ্যাপ-মধ্যস্থ ডিফল্ট ভ্যালু রিটার্ন করে। আপনার অ্যাপের জন্য সুবিধাজনক যেকোনও মুহূর্তে আপনি সার্ভার থেকে ভ্যালুর নতুন সেট ফেচ করতে পারবেন; নতুন সেট সফলভাবে ফেচ করার পরে, আপনি কখন এটি অ্যাক্টিভেট করবেন তা বেছে নিতে পারবেন যাতে অ্যাপের জন্য নতুন ভ্যালু উপলভ্য হয়।

মাইগ্রেশনের জন্য সাজেস্ট করা স্ট্র্যাটেজি

আপনি Firebase Remote Config-এ যেতে পারেন, এর জন্য আপনার Parse কনফিগারেশনের কী/ভ্যালু পেয়ার Firebase কনসোলে কপি করুন এবং তারপর Firebase Remote Config ব্যবহার করে অ্যাপের নতুন ভার্সন ডেপ্লয় করুন।

আপনি যদি Parse Config ও Firebase Remote Config, দুটিই নিয়ে পরীক্ষা করতে চান, তাহলে অ্যাপের একটি নতুন ভার্সন ডেপ্লয় করতে পারেন যেটি পর্যাপ্ত সংখ্যক ব্যবহারকারী শুধুমাত্র Parse ভার্সন থেকে মাইগ্রেট না করা পর্যন্ত দুটি SDK ব্যবহার করে।

কোড তুলনা করা

পার্স করুন

ParseConfig.getInBackground(new ConfigCallback() {
    @Override
    public void done(ParseConfig config, ParseException e) {
        if (e == null) {
            Log.d("TAG", "Yay! Config was fetched from the server.");
        } else {
            Log.e("TAG", "Failed to fetch. Using Cached Config.");
            config = ParseConfig.getCurrentConfig();
        }

        // Get the message from config or fallback to default value
        String welcomeMessage = config.getString("welcomeMessage", "Welcome!");
    }
});

Firebase

mFirebaseRemoteConfig = FirebaseRemoteConfig.getInstance();
// Set defaults from an XML resource file stored in res/xml
mFirebaseRemoteConfig.setDefaults(R.xml.remote_config_defaults);

mFirebaseRemoteConfig.fetch()
    .addOnSuccessListener(new OnSuccessListener<Void>() {
        @Override
        public void onSuccess(Void aVoid) {
            Log.d("TAG", "Yay! Config was fetched from the server.");
            // Once the config is successfully fetched it must be activated before newly fetched
            // values are returned.
            mFirebaseRemoteConfig.activateFetched();
        }
    })
    .addOnFailureListener(new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception exception) {
            Log.e("TAG", "Failed to fetch. Using last fetched or default.");
        }
    })

// ...

// When this is called, the value of the latest fetched and activated config is returned;
// if there's none, the default value is returned.
String welcomeMessage = mFirebaseRemoteConfig.getString("welcomeMessage");