Meteor ddp notify specific client - meteor

I'm using meteor ddp (Distributed Data Protocol) to my application. Server code is written using meteor and Android client using java.
Server code
if (Meteor.isServer) {
Users = new Mongo.Collection('testUsers');
Meteor.publish('methodToListen', function(){
return Users.find();
});
}
Client code (https://github.com/delight-im/Android-DDP)
public class MainActivity extends AppCompatActivity implements MeteorCallback {
private Meteor mMeteor;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Meteor.setLoggingEnabled(true);
mMeteor = new Meteor(this, "ws://192.168.137.1:3000/websocket");
mMeteor.addCallback(this);
mMeteor.connect();
}
#Override
public void onConnect(boolean signedInAutomatically) {
String subscriptionId = mMeteor.subscribe("methodToListen");
}
#Override
public void onDisconnect() {
}
#Override
public void onException(Exception e) {
}
#Override
public void onDataAdded(String collectionName, String documentID, String newValuesJson) {
Log.d("DATACHANGED", "Add " + collectionName + ", " + documentID + ", " + newValuesJson);
}
#Override
public void onDataChanged(String collectionName, String documentID, String updatedValuesJson, String removedValuesJson) {
}
#Override
public void onDataRemoved(String collectionName, String documentID) {
}
}
So now every client that connects to server see live database updates. Is it possible to send updates only for specific client? So for example when user sign in to system it gets unique id and based on that id is it possible to send updated data?
Updated I can get information about connected clients
Meteor.onConnection(function(connection) {
console.log(connection.id + ", " + connection.clientAddress);
});
So for example ip addresses could be id

Related

Post value to server when no internet connection android studio

I'm trying to send a value to the server when the connection doesn't exist, when it connects to the internet it runs fine and is saved to the server and sqlite. but the problem arises when switching state from offline to online. I send one value to the server when the connection is offline but when the state moves to online the value I sent earlier becomes multiple on the server while in the sqlite database only one value is stored.
this is my network state checker class
public class NetworkStateCheckerNama extends BroadcastReceiver {
//context and database helper object
private Context context;
private Database db;
ApiRequestData apiRequestData;
#Override
public void onReceive(Context context, Intent intent) {
this.context = context;
apiRequestData = ServiceGenerator.createBaseService(this.context, ApiRequestData.class);
db = new Database(context);
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
//if there is a network
if (activeNetwork != null) {
//if connected to wifi or mobile data plan
if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI || activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
//getting all the unsynced user
Cursor cursor2 = db.getUnsyncedNama();
if (cursor2.moveToFirst()) {
do {
//calling the method to save the unsynced name to MySQL
Nama(
cursor2.getString(cursor2.getColumnIndexOrThrow(Database.KOLOM_NAMA_COBA)),
cursor2.getString(cursor2.getColumnIndexOrThrow(Database.KOLOM_NIP_COBA))
);
} while (cursor2.moveToNext());
}
}
}
}
private void Nama(final String nama,final String nip) {
//Call call = retrofit.create(APIInterface.class).saveName(name);
Call call = apiRequestData.nama_query(nama,nip);
call.enqueue(new Callback<Responses>() {
#Override
public void onResponse(Call<Responses> call, Response<Responses> response) {
if (response.code() == 200){
db.updateNamaStatus(nip, MainActivity.NAME_SYNCED_WITH_SERVER);
//sending the broadcast to refresh the list
context.sendBroadcast(new Intent(MainActivity.DATA_SAVED_BROADCAST_MAIN));
}
}
#Override
public void onFailure(Call<Responses> call, Throwable t) {
}
});
}
this is my MainActivity Class
public class MainActivity extends AppCompatActivity {
Session session;
Button buttonLogout,buttonKirim;
TextView textViewNamaMain, textViewNipMain;
EditText editTextNamaMain;
Database database;
private AdapterNama mAdapter;
private RecyclerView listviewNama;
ApiRequestData apiRequestData;
//1 means data is synced and 0 means data is not synced
public static final int NAME_SYNCED_WITH_SERVER = 1;
public static final int NAME_NOT_SYNCED_WITH_SERVER = 0;
//a broadcast to know weather the data is synced or not
public static final String DATA_SAVED_BROADCAST_MAIN = "com.example.myapplication.datasave2";
ArrayList<Nama> namaArray;
ArrayList<User> users;
BroadcastReceiver broadcastReceiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
session = new Session(this);
buttonLogout = findViewById(R.id.buttonLogout);
buttonKirim = findViewById(R.id.buttonKirim);
textViewNipMain = findViewById(R.id.textViewNipMain);
textViewNamaMain = findViewById(R.id.textViewNamaMain);
editTextNamaMain = findViewById(R.id.editTextTextNamaMain);
String nip = getIntent().getStringExtra("nip");
listviewNama = findViewById(R.id.lv_nama);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
listviewNama.setLayoutManager(layoutManager);
listviewNama.setItemAnimator(new DefaultItemAnimator());
database = new Database(this);
namaArray = new ArrayList<>();
users = new ArrayList<>();
apiRequestData = ServiceGenerator.createBaseService(this, ApiRequestData.class);
textViewNipMain.setText(nip);
registerReceiver(new NetworkStateCheckerNama(), new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
loadDaftarNama(nip);
broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//loading the names again
loadDaftarNama(nip);
}
};
registerReceiver(broadcastReceiver, new IntentFilter(DATA_SAVED_BROADCAST_MAIN));
if(!session.isUserLogin()){
logout();
}
buttonKirim.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
SimpanKeServer();
}
});
buttonLogout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
logout();
}
});
users.clear();
Cursor cursor = database.getUsersWhereNip(nip);
if (cursor.moveToFirst()) {
do {
User user = new User(
cursor.getString(cursor.getColumnIndexOrThrow(Database.KOLOM_NIP)),
cursor.getString(cursor.getColumnIndexOrThrow(Database.KOLOM_NAMA)),
cursor.getString(cursor.getColumnIndexOrThrow(Database.KOLOM_PASSWORD)),
cursor.getInt(cursor.getColumnIndexOrThrow(Database.KOLOM_STATUS))
);
users.add(user);
textViewNamaMain.setText(user.getNama());
} while (cursor.moveToNext());
}
}
private void SimpanKeServer(){
final ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Saving Name...");
progressDialog.show();
String nama = editTextNamaMain.getText().toString();
String nip = textViewNipMain.getText().toString();
Call call = apiRequestData.nama_query(nama,nip);
call.enqueue(new Callback<Responses>() {
#Override
public void onResponse(Call<Responses> call, Response<Responses> response) {
progressDialog.dismiss();
if(response.code() == 200){
//if there is a success
//storing the name to sqlite with status synced
SaveNamaToLocal(nama,nip,NAME_SYNCED_WITH_SERVER);
Toast.makeText(MainActivity.this, "Berhasil", Toast.LENGTH_SHORT).show();
}else {
progressDialog.dismiss();
//if there is some error
//saving the name to sqlite with status unsynced
SaveNamaToLocal(nama,nip,NAME_NOT_SYNCED_WITH_SERVER);
Toast.makeText(MainActivity.this, "Gagal", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<Responses> call, Throwable t) {
progressDialog.dismiss();
SaveNamaToLocal(nama,nip,NAME_NOT_SYNCED_WITH_SERVER);
Toast.makeText(MainActivity.this, "Gagal", Toast.LENGTH_SHORT).show();
}
});
}
private void SaveNamaToLocal(String nama, String nip, int status){
database.Nama(nama,nip,status);
Nama namas = new Nama(nama,nip,status);
namaArray.add(namas);
refreshList();
}
private void loadDaftarNama(String nip) {
namaArray.clear();
Cursor cursor = database.getNama(nip);
if (cursor.moveToFirst()) {
do {
Nama nama = new Nama(
cursor.getString(cursor.getColumnIndexOrThrow(Database.KOLOM_NAMA_COBA)),
cursor.getString(cursor.getColumnIndexOrThrow(Database.KOLOM_NIP_COBA)),
cursor.getInt(cursor.getColumnIndexOrThrow(Database.KOLOM_STATUS_NAMA_COBA))
);
namaArray.add(nama);
} while (cursor.moveToNext());
}
mAdapter = new AdapterNama(this, namaArray);
listviewNama.setAdapter(mAdapter);
}
#SuppressLint("NotifyDataSetChanged")
private void refreshList() {
mAdapter.notifyDataSetChanged();
}
private void logout(){
session.updateUserLoginStatus(false);
finish();
startActivity(new Intent(MainActivity.this,LoginActivity.class));
}
}
this when online
enter image description here
enter image description here
this the problem when state internet switch from offline to online
enter image description here
enter image description here
Even in server send 3 same values
I'm sorry for my english and my question structure im new in programmer, and thank you for the answer

Subscriber only called once in Rx android and Firebase Realtime-Database Implementation

I am new to android development.
Currently I am implementing Firebase Realtime-Database with Rx android.
Here the Rx Android is used to listen to any changes happened in a particular child node inside the Realtime-Database, retrieve a List of Java class object in it and then return the List so that it can be used by another class.
Below are my code snippets.
1) Here is a class that do basic Database operation such as read, write, update and delete, right now I'm only showing the read operation.
public class FirebaseDatabaseLayer {
private DatabaseReference databaseReference = FirebaseDatabase
.getInstance().getReference();
private List<TodoComponentFirebase> todoComponentFirebases = new ArrayList<>();
private FirebaseUser user;
public Observable<List<TodoComponentFirebase>> readModelFirebase() {
return Observable.create(new Observable.OnSubscribe<List<TodoComponentFirebase>>() {
#Override
public void call(final Subscriber<? super List<TodoComponentFirebase>> subscriber) {
user = FirebaseAuth.getInstance().getCurrentUser();
databaseReference.child(user.getUid())
.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
for (DataSnapshot todoComponentSnapshot: dataSnapshot.getChildren()) {
TodoComponentFirebase todoComponentFirebase = todoComponentSnapshot.getValue(TodoComponentFirebase.class);
todoComponentFirebases.add(todoComponentFirebase);
}
subscriber.onNext(todoComponentFirebases);
subscriber.onCompleted();
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
for (DataSnapshot todoComponentSnapshot: dataSnapshot.getChildren()) {
TodoComponentFirebase todoComponentFirebase = todoComponentSnapshot.getValue(TodoComponentFirebase.class);
todoComponentFirebases.add(todoComponentFirebase);
}
subscriber.onNext(todoComponentFirebases);
subscriber.onCompleted();
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
});
}
2) Here is class which has a subscriber that listening to the Observable defined in the class in number 1) inside readModelFirebase method
public class Presenter {
private FirebaseDatabaseLayer firebaseDatabaseLayer;
private Subscription readSubscriber = null;
public void readFirebaseModel() {
readSubscriber = firebaseDatabaseLayer
.readModelFirebase()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<List<TodoComponentFirebase>>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
}
#Override
public void onNext (List<TodoComponentFirebase> todoComponentFirebases) {
mainView.getFirebaseData(todoComponentFirebases);
}
});
}
}
Here the 2) class pass the List of TodoComponentFirebase to the parameter of mainView.getFirebaseData method (I'm not showing concrete implementation of this method here). The idea here is that the mainView.getFirebaseData method will get a List of TodoComponentObject saved in Firebase Database everytime there's change happened in the respective child node.
MainView class is an AppCompatActivity class, the readFirebaseMethod() inside Presenter class is being called in onCreate method of the MainView class, this serve as subscription initialisation.
At the first time initialization of MainView class, the onNext inside readFirebaseModel() is executed, the data being retrieved seamlessly.
However after that there's no execution on that onNext method even though there's changes occur in Child Node which is defined in the 1) class.
I don't understand why the subscription is not working even though there's changes happen in the child node, it only worked the time it is being initialised. Is there anything missed in my Rx usage ?
Thanks
try remove the
subscriber.onCompleted();
I think when you call the onCompleted() subscriber will end up and not called again after any child event on firebase.

Refresh recyclerView with new data Retrofit

I am using Retrofit 2.0 to retrieve data from my api and using a recyclerView to display it.
My main activity has a tab layout and one of those tabs has the recyclerView and the fragment class for that tab is being used to retrieve the data and update the layout.
In my main layout I have a fab which makes a post (all posts are being retrieved in fragment class) and this fab has it's function of making the post in main activity.
So how can I refresh the layout when the fab's function is over and the post is successfully saved in my database?
Basically
User clicks fab > Makes his post > Alert dialog closes > recyclerView should be refreshed with new data added.
My Fragment Class :
public class PostsRecentTab extends Fragment {
private static final String TAG = MainActivity.class.getSimpleName();
private RecyclerView feedView;
private ProgressDialog pDialog = MainActivity.pDialog;
LinearLayoutManager layoutManager;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View v = inflater.inflate(R.layout.tab_recent_posts, container, false);
pDialog.setCancelable(false);
layoutManager = new LinearLayoutManager(this.getContext());
feedView = (RecyclerView) v.findViewById(R.id.feedView);
requestData();
return v;
}
public void requestData() {
SocialHubAPI apiService = ApiClient.getClient().create(SocialHubAPI.class);
pDialog.setMessage("Refreshing...");
showDialog();
Call<StatusResponse> call = apiService.getStatuses();
call.enqueue(new Callback<StatusResponse>() {
#Override
public void onResponse(Call<StatusResponse> call, Response<StatusResponse> response) {
int statusCode = response.code();
List<Status> statuses = response.body().getStatuses();
Log.d(TAG, "Status Code: " + statusCode);
hideDialog();
updateView(statuses);
}
#Override
public void onFailure(Call<StatusResponse> call, Throwable t) {
Log.e(TAG, t.toString());
}
});
}
private void updateView(List<Status> statuses) {
StatusesAdapter adapter = new StatusesAdapter(statuses, R.layout.feed_item, getContext());
feedView.setLayoutManager(layoutManager);
feedView.setAdapter(adapter);
}
private void showDialog() {
if (!pDialog.isShowing())
pDialog.show();
}
private void hideDialog() {
if (pDialog.isShowing())
pDialog.dismiss();
}
}
My Fab On Click :
FloatingActionButton postStatus = (FloatingActionButton) findViewById(R.id.postStatus);
postStatus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View view) {
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle("Post Status");
// Set up the input
final EditText input = new EditText(MainActivity.this);
// Specify the type of input expected; this, for example, sets the input as a password, and will mask the text
input.setInputType(InputType.TYPE_CLASS_TEXT);
builder.setView(input);
// Set up the buttons
builder.setPositiveButton("Post", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
postText = input.getText().toString();
processPost(postText, sessionManager.getToken());
Snackbar.make(view, "Status posted!", Snackbar.LENGTH_LONG).show();
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
builder.show();
}
});
Fab onClick calls this method :
protected void processPost(String postText, String token) {
SocialHubAPI apiService = ApiClient.getClient().create(SocialHubAPI.class);
pDialog.setMessage("Posting...");
showDialog();
final PostRequest postRequest = new PostRequest();
postRequest.setStatus(postText);
Call<PostResponse> call = apiService.postStatus(postRequest, token);
call.enqueue(new Callback<PostResponse>() {
#Override
public void onResponse(Call<PostResponse> call, Response<PostResponse> response) {
hideDialog();
Toast.makeText(getApplicationContext(), "Status Posted Successfully!", Toast.LENGTH_LONG).show();
}
#Override
public void onFailure(Call<PostResponse> call, Throwable t) {
Log.e(TAG, t.toString());
}
});
}
You should invalidate your list in updateView(List<Status> statuses) instead of setting the adapter again. Instantiate adapter only in onCreate().
This function should be like this:
adapter.addNewStatutes(statuses)
in Adapter class
public void addNewStatutes(List<Status> statuses)
{
this.statuses.addAll(statuses);
notifyDataSetChanged();
}
Also in onResponse use EventBus or Rx, because your view can be destroyed and this method can crash your app.
Added notifyDataSetChanged as per docs.

Multiple Query Params with Asyncronous Call Retrofit

UPDATE:
I have learned what I am looking to do is to use the Async within Retrofit with multiple queries too. I have updated my code, but I cannot get the async with the queries.
I am using Retrofit to make my data calls to a movie database and need to change the sort order depending on user settings. I am not clear how I could add this functionality to my interface.
sort_by=highest_rating.desc
or
sort_by=popularity.desc
Interface:
public interface MovieDatabaseApiCient {
#GET("/3/discover/movie")
void getData(#Query("api_key") String apiKey, #Query("sort_by") String sortByValue, Callback<MovieDbModel> response);
}
UPDATED API INTERFACE:
public interface MovieDatabaseApiCient {
#GET("/3/discover/movie?sort_by=popularity.desc&api_key=xxxxxxx")
void getMoviesByPopularityDesc(Callback<MovieDbModel> response);
#GET("/3/discover/movie?sort_by=vote_average_desc&api_key=xxxxxxxx")
void getMoviesByVotingDesc(Callback<MovieDbModel> response);
}
UPDATED DATA CALL THAT WORKS:
private void makeDataCall(String sortPreference) {
final RestAdapter restadapter = new RestAdapter.Builder().setEndpoint(ENDPOINT_URL).build();
MovieDatabaseApiCient apiLocation = restadapter.create(MovieDatabaseApiCient.class);
if (sortPreference.equals(this.getString(R.string.sort_order_popularity)) ){
apiLocation.getMoviesByPopularityDesc (new Callback<MovieDbModel>() {
#Override
public void success(MovieDbModel movieModels, Response response) {
movieDbResultsList = movieModels.getResults();
MoviesGridViewAdapter adapter = new MoviesGridViewAdapter(getApplicationContext(), R.layout.movie_gridview_item, movieDbResultsList);
gridView.setAdapter(adapter);
}
#Override
public void failure(RetrofitError error) {
Log.d("ERROR", error.toString());
Toast.makeText(getApplicationContext(), "Error: " + error.toString(), Toast.LENGTH_SHORT).show();
}
});
} else {
apiLocation.getMoviesByVotingDesc( new Callback<MovieDbModel>() {
#Override
public void success(MovieDbModel movieModels, Response response) {
movieDbResultsList = movieModels.getResults();
MoviesGridViewAdapter adapter = new MoviesGridViewAdapter(getApplicationContext(), R.layout.movie_gridview_item, movieDbResultsList);
gridView.setAdapter(adapter);
}
#Override
public void failure(RetrofitError error) {
Log.d("ERROR", error.toString());
Toast.makeText(getApplicationContext(), "Error: " + error.toString(), Toast.LENGTH_SHORT).show();
}
});
}
}
My call for the data:
private void makeDataCall (String apiKey, String sortPreference) {
final RestAdapter restadapter = new RestAdapter.Builder().setEndpoint(ENDPOINT_URL).build();
MovieDatabaseApiCient apiLocation = restadapter.create(MovieDatabaseApiCient.class);
apiLocation.getData(apiKey, sortPreference, new Callback<MovieDbModel>){
#Override
public void success(MovieDbModel movieModels, Response response) {
movieDbResultsList = movieModels.getResults();
MoviesGridViewAdapter adapter = new MoviesGridViewAdapter(getApplicationContext(), R.layout.movie_gridview_item, movieDbResultsList);
gridView.setAdapter(adapter);
}
#Override
public void failure(RetrofitError error) {
Log.d("ERROR", error.toString());
Toast.makeText(getApplicationContext(), "Error: " + error.toString(), Toast.LENGTH_SHORT).show();
}
});
}
I found a way to do Synchronously, but not asynchronously.
From your question and comment, IHMO, you should import retrofit.Callback; instead of import com.squareup.okhttp.Callback;
My code as the following has no compile error:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// creating a RestAdapter using the custom client
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(API_URL_BASE)
.setLogLevel(RestAdapter.LogLevel.FULL)
.setClient(new OkClient(mOkHttpClient))
.build();
WebService webService = restAdapter.create(WebService.class);
retrofit.Callback<GetRoleData> callback = new Callback<GetRoleData>() {
#Override
public void success(GetRoleData getRoleData, retrofit.client.Response response) {
}
#Override
public void failure(RetrofitError error) {
}
};
webService.getData("api_key", "sort_by", callback);
}
Interface:
public interface WebService {
#GET("/3/discover/movie")
void getData(#Query("api_key") String apiKey, #Query("sort_by") String sortByValue, Callback<GetRoleData> response);
}
So, please check your code again

Firebase how to prevent duplicate entries atomically

I'm looking at using firebase as a data store for user data for a web app. My current thought is to store each user's data using the timestamp of when they joined as the key referencing that user's data. The advantage of this scheme is that it's a simple way to assign unique integer ids to users, and makes chronological sorting of users simple.
A downside, however, is that if two add user requests are submitted with identical data, the app will happily add two separate entries, which is unideal. I could shuffle things around (I'm starting to think I should use email as the key and prioritize by join data, rather than my current scheme), but suppose I don't want to. Is there any way to prevent duplicate data?
The naive approach would probably be just to do something like:
if(!searchFirebaseForUser(data)) {
addUser(data);
}
But this is definitely a race condition; it'd be easy for two requests to both query and find no user in the database, and both add. I'd like to do this in a transaction, but it doesn't seem like the Firebase transaction support covers this case. Is there any way to handle this?
You will probably have to use the username or email address as a key, and try to atomically write to that location.
Here is the relevant code sample from the transaction function reference. In this case, we use wilma as the key for the user.
// Try to create a user for wilma, but only if the user id 'wilma' isn't already taken.
var wilmaRef = new Firebase('https://SampleChat.firebaseIO-demo.com/users/wilma');
wilmaRef.transaction(function(currentData) {
if (currentData === null) {
return {name: {first: 'Wilma', last: 'Flintstone'} };
} else {
console.log('User wilma already exists.');
return; // Abort the transaction.
}
}, function(error, committed, snapshot) {
if (error)
console.log('Transaction failed abnormally!', error);
else if (!committed)
console.log('We aborted the transaction (because wilma already exists).');
else
console.log('User wilma added!');
console.log('Wilma\'s data: ', snapshot.val());
});
Are Security Rules not sufficient to enforce uniqueness? I have no idea if they are atomic or not.
{
"rules": {
"users": {
"$username": {
".write": "!data.exists()"
}
}
}
}
You can use push to automatically generate chronologically incremental IDs that won't conflict with other clients even if they're created at the same time (they have a random component in them).
For example:
var ref = new Firebase(URL);
var record = ref.push(userInfo);
console.log("User was assigned ID: " + record.name());
instead of defining the rule in fire-base database the easiest way to prevent duplicate entries is first of all get all the data from the fire-base database and compare it with the data(new Data) you want to store,if it is matched with previous data then discard storing in the database again otherwise store in database.check below for more clarity.
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private BroadcastReceiver mRegistrationBroadcastReceiver;
private TextView txtRegId, txtMessage;
DatabaseReference databaseArtists;
ListView listViewArtists;
public static String regId;
List<Artist> artistList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txtRegId = (TextView) findViewById(R.id.regid);
txtRegId.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
displayFirebaseRegId();
boolean flag=false;
String tokenId=regId;
for(Artist a:artistList)
{Log.d("RAaz",a.getTokenId()+" "+tokenId);
if(a.getTokenId().equalsIgnoreCase(tokenId))
{
flag=true;
Toast.makeText(MainActivity.this, "True", Toast.LENGTH_SHORT).show();
}
}
if(flag)
{
Toast.makeText(MainActivity.this, "User Already Exists", Toast.LENGTH_SHORT).show();
}
else {
addArtist();
}
}
});
mRegistrationBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// checking for type intent filter
if (intent.getAction().equals(Config.REGISTRATION_COMPLETE)) {
// gcm successfully registered
// now subscribe to `global` topic to receive app wide notifications
FirebaseMessaging.getInstance().subscribeToTopic(Config.TOPIC_GLOBAL);
displayFirebaseRegId();
} else if (intent.getAction().equals(Config.PUSH_NOTIFICATION)) {
// new push notification is received
String message = intent.getStringExtra("message");
Toast.makeText(getApplicationContext(), "Push notification: " + message, Toast.LENGTH_LONG).show();
txtMessage.setText(message);
}
}
};
displayFirebaseRegId();
databaseArtists = FirebaseDatabase.getInstance().getReference("artist");
artistList = new ArrayList<>();}
Below code is for adding data to the firebase
private void addArtist() {
String name = "User";
String genre = regId;
if (!TextUtils.isEmpty(name)) {
String id = databaseArtists.push().getKey();
Artist artist = new Artist(id,genre,name);
databaseArtists.child(id).setValue(artist);
Toast.makeText(this, "Artist Added", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "Please enter name", Toast.LENGTH_SHORT).show();
}
}
use onStart to get the details from firebase database
protected void onStart() {
super.onStart();
Toast.makeText(this, "On Start", Toast.LENGTH_SHORT).show();
databaseArtists.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
artistList.clear();
for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
Artist artist = dataSnapshot1.getValue(Artist.class);
artistList.add(artist);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
finally add the pojo class
public class Artist {
private String artistId;
private String tokenId;
private String roleName;
public Artist() {
}
public Artist(String artistId, String tokenId, String roleName) {
this.artistId = artistId;
this.tokenId = tokenId;
this.roleName = roleName;
}
public String getArtistId() {
return artistId;
}
public void setArtistId(String artistId) {
this.artistId = artistId;
}
public String getTokenId() {
return tokenId;
}
public void setTokenId(String tokenId) {
this.tokenId = tokenId;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
}

Resources