หากคุณเป็นผู้ใช้การแยกวิเคราะห์ที่กำลังมองหาแบ็กเอนด์สำรองเป็น Firebase อาจเป็นตัวเลือกที่เหมาะสมสำหรับแอป Android ของคุณในฐานะโซลูชันบริการ
คู่มือนี้จะอธิบายวิธีผสานรวมบริการที่เฉพาะเจาะจงในแอปของคุณ สำหรับ วิธีพื้นฐานในการตั้งค่า Firebase โปรดดูการตั้งค่า Android
Google Analytics
Google Analytics คือโซลูชันการวัดผลแอปที่ไม่มีค่าใช้จ่ายซึ่งให้ข้อมูลเชิงลึกเกี่ยวกับการใช้แอปและ การมีส่วนร่วมของผู้ใช้ Analytics ผสานรวมฟีเจอร์ของ Firebase ทั้งหมดและให้คุณใช้งานได้แบบไม่จำกัด การรายงานสำหรับเหตุการณ์ที่แตกต่างกันได้สูงสุด 500 รายการที่คุณกำหนดได้โดยใช้ Firebase SDK
ดูข้อมูลเพิ่มเติมที่เอกสาร Google Analytics
กลยุทธ์การย้ายข้อมูลที่แนะนำ
การใช้ผู้ให้บริการวิเคราะห์ที่แตกต่างกันเป็นสถานการณ์ทั่วไปที่สามารถนำไปใช้กับ Google Analytics เพียงเพิ่มลงในแอปเพื่อใช้ประโยชน์จากเหตุการณ์และพร็อพเพอร์ตี้ผู้ใช้ที่ Analytics จะรวบรวมข้อมูล เช่น การเปิดครั้งแรก การอัปเดตแอป รุ่นอุปกรณ์ และอายุโดยอัตโนมัติ
สำหรับเหตุการณ์ที่กำหนดเองและพร็อพเพอร์ตี้ผู้ใช้ คุณสามารถใช้กลยุทธ์การเขียนแบบ 2 ชั้นได้โดยใช้ แยกวิเคราะห์ Analytics และ Google Analytics เพื่อบันทึกเหตุการณ์และพร็อพเพอร์ตี้ ซึ่งช่วยให้คุณ ค่อยๆ เปิดตัวโซลูชันใหม่
การเปรียบเทียบโค้ด
แยกวิเคราะห์ 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
ความแตกต่างกับการแยกวิเคราะห์ข้อมูล
วัตถุ
ในการแยกวิเคราะห์ คุณจัดเก็บ 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);
ความสัมพันธ์ระหว่างข้อมูล
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" } ... } }
กำลังอ่านข้อมูล
ในการแยกวิเคราะห์ คุณอ่านข้อมูลโดยใช้รหัสของออบเจ็กต์แยกวิเคราะห์ที่เฉพาะเจาะจง หรือ
กำลังทำการค้นหาโดยใช้ ParseQuery
ใน Firebase คุณดึงข้อมูลได้โดยการแนบ Listener แบบไม่พร้อมกันลงในการอ้างอิงฐานข้อมูล Listener จะทริกเกอร์ 1 ครั้งสำหรับสถานะเริ่มต้นของข้อมูล และอีกครั้งเมื่อข้อมูลเปลี่ยนแปลง คุณจึงไม่จำเป็นต้องเพิ่มโค้ดใดๆ เพื่อระบุว่าข้อมูลมีการเปลี่ยนแปลงหรือไม่
ต่อไปนี้เป็นตัวอย่างวิธีการดึงข้อมูลคะแนนสำหรับผู้เล่นแต่ละราย โดยพิจารณาจาก ตัวอย่างที่แสดงในส่วน "ออบเจ็กต์"
แยกวิเคราะห์
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());
}
});
กลยุทธ์การย้ายข้อมูลที่แนะนำ
ทบทวนข้อมูลของคุณ
Firebase Realtime Database ได้รับการเพิ่มประสิทธิภาพเพื่อซิงค์ข้อมูลเป็นมิลลิวินาทีในทุกอุปกรณ์ที่เชื่อมต่อแล้ว และโครงสร้างข้อมูลที่ได้จะแตกต่างจากการแยกวิเคราะห์ข้อมูลหลัก ซึ่งหมายความว่า ขั้นตอนแรกในการย้ายข้อมูลคือพิจารณาว่าข้อมูลต้องการการเปลี่ยนแปลงอะไรบ้าง ซึ่งได้แก่
- วิธีที่ออบเจ็กต์แยกวิเคราะห์ควรแมปกับข้อมูล Firebase
- หากคุณมีความสัมพันธ์แบบระดับบนสุดและระดับย่อย ให้แยกข้อมูลของคุณตามเส้นทางต่างๆ เพื่อให้ จะสามารถดาวน์โหลดได้อย่างมีประสิทธิภาพในการโทรแยกกัน
ย้ายข้อมูลของคุณ
หลังจากตัดสินใจถึงวิธีจัดโครงสร้างข้อมูลใน Firebase แล้ว คุณต้องวางแผนวิธีจัดการ ที่แอปของคุณจะต้องเขียนไปยังฐานข้อมูลทั้ง 2 แหล่ง โดยมีตัวเลือกดังนี้
การซิงค์ในเบื้องหลัง
ในสถานการณ์นี้ คุณจะมีแอป 2 เวอร์ชัน ได้แก่ เวอร์ชันเก่าที่ใช้การแยกวิเคราะห์และเวอร์ชันใหม่ เวอร์ชันที่ใช้ Firebase การซิงค์ระหว่างฐานข้อมูล 2 รายการได้รับการจัดการโดย Parse Cloud Code (แยกวิเคราะห์ กับ Firebase) โดยที่โค้ดจะรอฟังการเปลี่ยนแปลงใน Firebase และซิงค์การเปลี่ยนแปลงเหล่านั้นด้วยการแยกวิเคราะห์ คุณต้องดำเนินการต่อไปนี้ก่อนจึงจะเริ่มใช้เวอร์ชันใหม่ได้
- แปลงข้อมูลการแยกวิเคราะห์ที่มีอยู่เป็นโครงสร้าง Firebase ใหม่ และเขียนลงใน Firebase Realtime Database
- เขียนฟังก์ชันแยกวิเคราะห์ Cloud Code ที่ใช้ Firebase REST API เพื่อเขียนไปยัง มีการเปลี่ยนแปลง Firebase Realtime Database รายการในการแยกวิเคราะห์ข้อมูลโดยไคลเอ็นต์เก่า
- เขียนและติดตั้งใช้งานโค้ดที่รอฟังการเปลี่ยนแปลงใน Firebase และซิงค์กับการแยกวิเคราะห์ ฐานข้อมูล
สถานการณ์นี้ช่วยแยกโค้ดเก่าและโค้ดใหม่ออกจากกันและทำให้ไคลเอ็นต์เรียบง่าย ความท้าทายของสถานการณ์นี้คือการจัดการชุดข้อมูลขนาดใหญ่ในการส่งออกช่วงแรก และการตรวจสอบว่า การซิงค์แบบ 2 ทิศทางจะไม่สร้างการเกิดซ้ำที่ไม่สิ้นสุด
การเขียนแบบคู่
ในสถานการณ์นี้ คุณจะได้เขียนแอปเวอร์ชันใหม่ที่ใช้ทั้ง Firebase และ Parse โดยใช้ แยกวิเคราะห์โค้ดระบบคลาวด์เพื่อซิงค์การเปลี่ยนแปลงที่ทำโดยไคลเอ็นต์เก่าจากข้อมูลแยกวิเคราะห์ไปยัง Firebase Realtime Database เมื่อมีคนย้ายข้อมูลจากแอปเวอร์ชัน "แยกวิเคราะห์เท่านั้น" มากพอแล้ว สามารถนำโค้ดแยกวิเคราะห์ออกจากการดับเบิลคลิกเวอร์ชันเขียนได้
สถานการณ์นี้ไม่ต้องใช้โค้ดฝั่งเซิร์ฟเวอร์ ข้อเสียคือข้อมูลที่ไม่ ไม่มีการย้ายข้อมูล และขนาดของแอปเพิ่มขึ้นจากการใช้ SDK ทั้ง 2 ตัว
Firebase Authentication
Firebase Authentication สามารถตรวจสอบสิทธิ์ผู้ใช้โดยใช้รหัสผ่านและผู้ให้บริการข้อมูลประจำตัวแบบรวมศูนย์ที่ได้รับความนิยม เช่น Google, Facebook และ Twitter และยังมีไลบรารี UI เพื่อช่วยคุณบันทึก เงินลงทุนที่ต้องใช้เพื่อติดตั้งใช้งานและรักษาประสบการณ์การตรวจสอบสิทธิ์เต็มรูปแบบสำหรับแอปของคุณใน ทุกแพลตฟอร์ม
ดูข้อมูลเพิ่มเติมที่เอกสาร Firebase Authentication
ความแตกต่างกับการตรวจสอบสิทธิ์แบบแยกวิเคราะห์
การแยกวิเคราะห์มีคลาสผู้ใช้แบบพิเศษที่เรียกว่า 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());
}
}
});
กลยุทธ์การย้ายข้อมูลที่แนะนำ
ย้ายข้อมูลบัญชี
หากต้องการย้ายข้อมูลบัญชีผู้ใช้จากการแยกวิเคราะห์ไปยัง Firebase ให้ส่งออกฐานข้อมูลผู้ใช้ไปยัง
ไฟล์ JSON หรือ CSV แล้วนำเข้าไฟล์ไปยังโปรเจ็กต์ Firebase โดยใช้
auth:import
ของ Firebase CLI
คำสั่ง
ก่อนอื่น ให้ส่งออกฐานข้อมูลผู้ใช้จากคอนโซลแยกวิเคราะห์หรือโฮสต์ด้วยตนเอง ฐานข้อมูล ตัวอย่างเช่น ไฟล์ 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 ใช้ objectId
ของผู้ใช้การแยกวิเคราะห์เป็น
localId
ของผู้ใช้ Firebase นอกจากนี้ ให้เข้ารหัส base64
bcryptPassword
ค่าจากการแยกวิเคราะห์และใช้ใน 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 มีรหัสเดียวกันกับบัญชีแยกวิเคราะห์ คุณจึงย้ายข้อมูลและทำซ้ำได้อย่างง่ายดาย ความสัมพันธ์ใดๆ ที่อยู่ภายใต้ User-ID
Firebase Cloud Messaging
Firebase Cloud Messaging (FCM) เป็นโซลูชันการรับส่งข้อความข้ามแพลตฟอร์มที่ช่วยให้คุณ ส่งข้อความและการแจ้งเตือนได้โดยไม่มีค่าใช้จ่าย เครื่องมือเขียนการแจ้งเตือนเป็นบริการที่ไม่มีค่าใช้จ่ายซึ่งสร้างขึ้น ใน Firebase Cloud Messaging ที่เปิดใช้การแจ้งเตือนผู้ใช้เป้าหมายสำหรับนักพัฒนาแอปบนอุปกรณ์เคลื่อนที่
ดูข้อมูลเพิ่มเติมได้ที่เอกสาร Firebase Cloud Messaging
ความแตกต่างกับการแยกวิเคราะห์ข้อความ Push
แอปพลิเคชันการแยกวิเคราะห์ทั้งหมดที่ติดตั้งในอุปกรณ์ที่ลงทะเบียนสำหรับการแจ้งเตือนจะมีการเชื่อมโยง
Installation
ที่ซึ่งจะเก็บข้อมูลทั้งหมดที่ต้องใช้ในการกำหนดเป้าหมายการแจ้งเตือน
Installation
เป็นคลาสย่อยของ ParseUser
ซึ่งหมายความว่าคุณเพิ่มได้
ข้อมูลเพิ่มเติมที่คุณต้องการลงในอินสแตนซ์ Installation
การเขียนการแจ้งเตือนมีกลุ่มผู้ใช้ที่กำหนดไว้ล่วงหน้าโดยอิงตามข้อมูลต่างๆ เช่น แอป เวอร์ชันแอป และอุปกรณ์ ภาษา คุณสร้างกลุ่มผู้ใช้ที่ซับซ้อนขึ้นได้โดยใช้เหตุการณ์และพร็อพเพอร์ตี้ Google Analytics ในการสร้างกลุ่มเป้าหมาย ดูกลุ่มเป้าหมาย ผู้ช่วยอัตโนมัติเพื่อเรียนรู้เพิ่มเติม ข้อมูลการกำหนดเป้าหมายเหล่านี้จะไม่ปรากฏใน Firebase Realtime Database
กลยุทธ์การย้ายข้อมูลที่แนะนำ
การย้ายข้อมูลโทเค็นอุปกรณ์
ในขณะที่เขียนเอกสาร Parse Android SDK จะใช้ FCM เวอร์ชันเก่า โทเค็นการลงทะเบียนใช้ไม่ได้กับฟีเจอร์ที่เขียนโดยเครื่องมือการแจ้งเตือน
คุณรับโทเค็นใหม่ได้โดยเพิ่ม FCM SDK ลงในแอป อย่างไรก็ตาม การดำเนินการนี้อาจทำให้โทเค็นที่ Parse SDK ใช้รับการแจ้งเตือนใช้งานไม่ได้ หากไม่ต้องการให้เป็นเช่นนั้น คุณสามารถตั้งค่า Parse SDK ให้ใช้รหัสผู้ส่งของ Parse ทั้ง และรหัสผู้ส่ง ซึ่งจะช่วยให้คุณไม่ทำให้โทเค็นที่ Parse SDK ใช้อยู่ใช้งานไม่ได้ แต่โปรดทราบว่าวิธีแก้ปัญหาชั่วคราวนี้จะหยุดทำงานเมื่อ Parse ปิดโปรเจ็กต์
การย้ายข้อมูลช่องไปยัง FCM หัวข้อ
หากคุณใช้การแยกวิเคราะห์ช่องเพื่อส่งการแจ้งเตือน คุณสามารถย้ายข้อมูลไปยังหัวข้อ FCM ซึ่งจะให้ สมาชิกผู้เผยแพร่โฆษณา ในรูปแบบเดียวกัน คุณสามารถเขียนเวอร์ชันใหม่เพื่อจัดการการเปลี่ยนจากการแยกวิเคราะห์เป็น FCM ได้ ของแอปที่ใช้ Parse SDK เพื่อเลิกติดตามช่องจากการแยกวิเคราะห์และใช้ FCM SDK เพื่อสมัครใช้บริการ หัวข้อ FCM ที่เกี่ยวข้อง ในแอปเวอร์ชันนี้ คุณควรปิดใช้การรับการแจ้งเตือน แยกวิเคราะห์ SDK โดยนำข้อมูลต่อไปนี้ออกจากไฟล์ Manifest ของแอป
<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
}
}
});
เมื่อใช้กลยุทธ์นี้ คุณจะสามารถส่งข้อความให้กับช่องแยกวิเคราะห์และ FCM หัวข้อที่สนับสนุนผู้ใช้ทั้งเวอร์ชันเก่าและเวอร์ชันใหม่ เมื่อมีผู้ใช้ย้ายข้อมูลจาก เวอร์ชันแยกวิเคราะห์ของแอปเท่านั้น คุณจะเลิกใช้งานเวอร์ชันดังกล่าวและเริ่มส่งโดยใช้ FCM เท่านั้นได้
โปรดดู เอกสาร FCM หัวข้อ เพื่อดูข้อมูลเพิ่มเติม
Firebase Remote Config
Firebase Remote Config คือบริการระบบคลาวด์ที่ช่วยให้คุณเปลี่ยนลักษณะการทำงานและรูปลักษณ์ของ แอปโดยไม่ต้องให้ผู้ใช้ดาวน์โหลดอัปเดตแอป การใช้การกำหนดค่าระยะไกลจะเป็นการสร้างในแอป ค่าเริ่มต้นที่ควบคุมลักษณะการทำงานและรูปลักษณ์ของแอป จากนั้นคุณสามารถใช้ คอนโซล Firebase เพื่อลบล้างค่าเริ่มต้นในแอปสำหรับผู้ใช้แอปทั้งหมดหรือสำหรับกลุ่มฐานผู้ใช้
Firebase Remote Config อาจมีประโยชน์มากระหว่างการย้ายข้อมูลในกรณีที่คุณต้องการทดสอบ โซลูชันที่แตกต่าง และสามารถเปลี่ยนลูกค้าไปยังผู้ให้บริการรายอื่นแบบไดนามิก ตัวอย่างเช่น หากมีแอปเวอร์ชันที่ใช้ทั้ง Firebase และแยกวิเคราะห์ข้อมูล คุณสามารถใช้ กฎเปอร์เซ็นไทล์แบบสุ่มเพื่อหาไคลเอ็นต์ที่อ่านจาก Firebase แล้วค่อยๆ เพิ่มเปอร์เซ็นต์ขึ้น
ดูข้อมูลเพิ่มเติมเกี่ยวกับ Firebase Remote Config ได้ที่ ข้อมูลเบื้องต้นเกี่ยวกับ Remote Config
ความแตกต่างจากการกำหนดค่าการแยกวิเคราะห์
เมื่อใช้การกำหนดค่าการแยกวิเคราะห์ คุณจะเพิ่มคู่คีย์/ค่าลงในแอปในหน้าแดชบอร์ดการกำหนดค่าการแยกวิเคราะห์ได้ จากนั้น
ดึงข้อมูล ParseConfig
ในไคลเอ็นต์ ทุกๆ ParseConfig
อินสแตนซ์ที่คุณ
เป็นสิ่งที่เปลี่ยนแปลงไม่ได้เสมอ เมื่อคุณเรียกข้อมูล ParseConfig
ใหม่ในอนาคตจาก
เครือข่ายจะไม่แก้ไขอินสแตนซ์ ParseConfig
ที่มีอยู่ แต่จะแก้ไข
สร้างบัญชีใหม่และทำให้พร้อมใช้งานผ่าน getCurrentConfig()
Firebase Remote Config ช่วยให้คุณสร้างค่าเริ่มต้นในแอปสำหรับคู่คีย์/ค่าที่คุณลบล้างได้ จากคอนโซล Firebase และใช้กฎและเงื่อนไขเพื่อกำหนดเวอร์ชันต่างๆ ของแอปได้ ประสบการณ์ของผู้ใช้ไปยังกลุ่มผู้ใช้ที่แตกต่างกันได้ Firebase Remote Config ใช้ คลาส Singleton ที่ทำให้ชุดคีย์/ค่าพร้อมใช้งานสำหรับแอปของคุณ ตอนแรก Singleton กลับมาแล้ว ค่าเริ่มต้นที่คุณกำหนดในแอป คุณสามารถดึงข้อมูลชุดค่าใหม่จากเซิร์ฟเวอร์ ช่วงเวลาที่สะดวกสำหรับแอปของคุณ หลังจากที่ดึงข้อมูลชุดใหม่เรียบร้อยแล้ว คุณจะเลือกเวลาเปิดใช้งานได้ เพื่อให้ค่าใหม่ใช้ได้กับแอป
กลยุทธ์การย้ายข้อมูลที่แนะนำ
คุณสามารถย้ายไปยัง Firebase Remote Config ได้โดยคัดลอกคู่คีย์/ค่าของการกำหนดค่าการแยกวิเคราะห์ ในคอนโซล Firebase แล้วทำให้แอปเวอร์ชันใหม่ที่ใช้ Firebase Remote Config ใช้งานได้
หากต้องการทดสอบทั้งการกำหนดค่าการแยกวิเคราะห์และ Firebase Remote Config คุณสามารถติดตั้งใช้งานได้ มีแอปเวอร์ชันใหม่ที่ใช้ SDK ทั้ง 2 แบบจนกว่าผู้ใช้จะย้ายข้อมูลจากเวอร์ชัน "แยกวิเคราะห์เท่านั้น" เพียงพอ
การเปรียบเทียบโค้ด
แยกวิเคราะห์
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");