I was following a tutorial online on how to create an android chat app with Xamarin that was implemented in Visual Studio 2015 and I was using Visual Studio 2017. I also tried to InitializeApp to see if that would fix it, but it did not work. What could be the problem? There was a couple of changes that I implemented, but I have one problem. I am getting an error "Java.Lang.IllegalStateException: " on line FirebaseDatabase.Instance.GetReference("chats").AddValueEventListener(this);
This is how I implented the OnCreate method:
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.Main);
FirebaseApp.InitializeApp(this);
firebase = new FirebaseClient(FirebaseURL);
//firebase = new FirebaseClient(GetString(Resource.String.firebase_url)); //not working
FirebaseDatabase.Instance.GetReference("chats").AddValueEventListener(this);
fab = FindViewById<FloatingActionButton>(Resource.Id.fab);
edtChat = FindViewById<EditText>(Resource.Id.input);
lstChat = FindViewById<ListView>(Resource.Id.list_of_messages);
fab.Click += delegate
{
PostMessage();
};
if (FirebaseAuth.Instance.CurrentUser == null)
{
StartActivityForResult(new Android.Content.Intent(this, typeof(Signin)), MyResultCode);
}
else
{
Toast.MakeText(this, "Welcome " + FirebaseAuth.Instance.CurrentUser.Email, ToastLength.Short).Show();
DisplayChatMessage();
}
}
private async void PostMessage()
{
var items = await firebase.Child("chats").PostAsync(new MessageContent(FirebaseAuth.Instance.CurrentUser.Email, edtChat.Text));
edtChat.Text = "";
}
public void OnCancelled(DatabaseError error)
{
}
public void OnDataChange(DataSnapshot snapshot)
{
DisplayChatMessage();
}
private async void DisplayChatMessage()
{
lstMessage.Clear();
var items = await firebase.Child("chats")
.OnceAsync<MessageContent>();
foreach (var item in items)
lstMessage.Add(item.Object);
ListViewAdapter adapter = new ListViewAdapter(this, lstMessage);
lstChat.Adapter = adapter;
}
Related
I have a problem with the Facebook SDK. It works fine in Editor and in apk(if i check the development build option in Unity), but on release build it doesn't work.
Here is my code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Facebook.Unity;
using UnityEngine.UI;
using Facebook.MiniJSON;
public class FBManager : MonoBehaviour {
[SerializeField]private Text FBErrorText;
public RawImage FBProfilePicture;
public Image DefaultAvatar;
public Text UsernameText;
public Text WelcomeMessage;
public Button FacebookButton;
private Color fbProfilePictureColor;
private Color defaultAvatarColor;
private string getData;
private string FBUserName;
void Awake()
{
if (!FB.IsInitialized)
{ FBErrorText.text = "fb not ini, initializing";
FB.Init(InitCallBack, OnHideUnity);
FBErrorText.text = "called fb.init";
}
else
{ FBErrorText.text += "initialized";
FB.ActivateApp();
FBErrorText.text += "called fb.activateApp";
}
fbProfilePictureColor = FBProfilePicture.color;
defaultAvatarColor = DefaultAvatar.color;
fbProfilePictureColor.a = 0f;
FBProfilePicture.color = fbProfilePictureColor;
}
void Start()
{
//StartCoroutine (FbLoginWait ());
}
IEnumerator FbLoginWait()
{
yield return new WaitUntil (()=> FB.IsInitialized);
FBLogin ();
}
//auto logare
private void InitCallBack()
{
if (FB.IsInitialized)
{
//UsernameText.text = "Initialized FB SDK";
FBErrorText.text = "fb is initialized";
FB.ActivateApp ();
FBErrorText.text = "fb activated app";
}
else
{
FBErrorText.text = "Failed to initialize the Facebook SDK";
Debug.Log ("Failed to initialize the Facebook SDK");
}
}
private void OnHideUnity(bool isGameShown)
{
if (!isGameShown)
{
Time.timeScale = 0;
}
else
{
Time.timeScale = 1;
}
}
private void HandleLoginFB(bool IsLogged)
{
if (IsLogged)
{
FBErrorText.text = "user logged in";
Debug.Log ("User logged in");
}
else
{
FBErrorText.text = "user cancelled login";
Debug.Log ("User cancelled login");
}
}
private void AuthCallback(IResult result)
{
FBErrorText.text = "called authcallback";
HandleLoginFB (FB.IsLoggedIn);
FBErrorText.text = "handling fb";
if (FB.IsLoggedIn)
{
var aToken = Facebook.Unity.AccessToken.CurrentAccessToken;
Debug.Log (aToken.UserId);
foreach (string perm in aToken.Permissions) {
Debug.Log (perm);
}
FB.API ("/me/picture?type=square&height=50&width=50", HttpMethod.GET, UpdateProfileImage);
FB.API ("me?fields=name", HttpMethod.GET, GetUsername);
FBErrorText.text = "fb is logged in";
}
else
{
FBErrorText.text = "fb is not logged in";
}
}
public void FBLogin()
{
FBErrorText.text = "called fblogin";
List<string> perms = new List<string> () { "public_profile, email", "user_friends" };
FBErrorText.text = "created perms";
FB.LogInWithReadPermissions (perms, AuthCallback);
FBErrorText.text = "ended fblogin";
}
private void UpdateProfileImage(IGraphResult result)
{
if(result.Texture != null)
{
FBProfilePicture.texture = result.Texture;
defaultAvatarColor.a = 0f;
fbProfilePictureColor.a = 255f;
DefaultAvatar.color = defaultAvatarColor;
FBProfilePicture.color = fbProfilePictureColor;
}
}
private void GetUsername(IGraphResult result)
{
FBUserName = result.ResultDictionary ["name"].ToString ();
UsernameText.text = FBUserName;
WelcomeMessage.text = FBUserName + "'s NET WORTH";
}
}
(or the same code here https://hastebin.com/osatiketij.cs)
The last error text on the screen which appears is : "created perms", so right before the FB.LogInWithReadPermissions method is called, no error text appears after that, but no login also.
Any idea what it might be ?
For everyone coming to this thread : how I manage to fix this was by using Android Studio to see with the Logcat why it doesn't work, and it was "missing" a class. For anyone coming here, I fixed it by adding "-keep class com.facebook.** {*;}" to my proguard-user file.
I have used rxjava and retrofit to load data from backend and update the UI.
But there is no data displayed on section view. I have tested it, and the backend data load successful and the UI can be updated using fake data.
Are there something wrong when I use Rxjava?
private void retrieveCardInfo(String stripeId, String userToken) {
subscriptions.add(NetworkUtil.getRetrofit(userToken).getCustomerInfo(new GetCustomer(stripeId))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::handleCustomerResponse, this::handleError));
}
private void handleCustomerResponse(CreateStripeCustomerResponse response) {
if (response.getSuccess()) {
updateCardList(response);
bankSection.setState(Section.State.EMPTY);
} else {
Utils.toast(this,"Get credit card failed");
}
}
private void updateCardList(CreateStripeCustomerResponse response) {
List<CardInfo> cardList = response.getCustomer().getSources().getData();
if (cardList == null || cardList.size() == 0) {
cardSection.setState(Section.State.EMPTY);
} else {
list = new ArrayList<>();
for (int i = 0; i < cardList.size(); i++) {
CardInfo cardInfo = cardList.get(i);
String brand = cardInfo.getBrand();
String subTitle = cardInfo.getFunding() + "****" + cardInfo.getLast4();
list.add(new PaymentAccountItem(brand, subTitle, cardDrawable.get(brand)));
}
list.add(new PaymentAccountItem("title", "subtitle", R.drawable.ic__credit_amex_svg));
cardSection.swipeData(list);
}
}
private void handleError(Throwable throwable) {
}
// works fine without sectionedAdapter.notifyDataSetChanged(); when using fake data,
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_payment);
ButterKnife.bind(this);
subscriptions = new CompositeSubscription();
initialToolbar();
initialRecyclerView();
initialPaymentData();
}
private void initialPaymentData() {
stripeIdAndToken = Utils.getStripeIdAndToken(this);
if (TextUtils.isEmpty(stripeIdAndToken.first)) {
cardSection.setState(Section.State.EMPTY);
bankSection.setState(Section.State.EMPTY);
} else {
initialCardDrawableResource();
retrieveCardInfo(stripeIdAndToken.first, stripeIdAndToken.second);
}
// fake data here
// initialCardDrawableResource();
// list = new ArrayList<>();
// list.add(new PaymentCreditCardItem("Visa", "123456", 10, 2018, cardDrawable.get("Visa")));
// cardSection.swipeData(list);
}
private void initialCardDrawableResource() {
cardDrawable = new HashMap<>();
cardDrawable.put("Visa", R.drawable.ic_visa_svg);
cardDrawable.put("Discover", R.drawable.ic_discover_svg);
cardDrawable.put("American Express", R.drawable.ic__credit_amex_svg);
cardDrawable.put("Mastercard", R.drawable.cio_ic_mastercard);
}
private void retrieveCardInfo(String stripeId, String token) {
subscriptions.add(NetworkUtil.getRetrofit(token).getCustomerInfo(new GetCustomer(stripeId))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::handleCustomerResponse, this::handleError));
}
private void handleCustomerResponse(CreateStripeCustomerResponse response) {
if (response.getSuccess()) {
updateCardList(response);
} else {
Utils.toast(this, "Get credit card failed");
}
}
private void updateCardList(CreateStripeCustomerResponse response) {
List<CardInfo> cardList = response.getCustomer().getSources().getData();
if (cardList == null || cardList.size() == 0) {
cardSection.setState(Section.State.EMPTY);
} else {
list = new ArrayList<>();
for (int i = 0; i < cardList.size(); i++) {
CardInfo cardInfo = cardList.get(i);
String brand = cardInfo.getBrand();
String cardNum = cardInfo.getFunding() + "****" + cardInfo.getLast4();
list.add(new PaymentCreditCardItem(brand, cardNum, cardInfo.getExpMonth(), cardInfo.getExpYear(), cardDrawable.get(brand)));
}
cardSection.swipeData(list);
sectionedAdapter.notifyDataSetChanged();
}
}
private void handleError(Throwable throwable) {
}
private void initialRecyclerView() {
sectionedAdapter = new SectionedRecyclerViewAdapter();
cardSection = new PaymentCardAndAccountSection(this, R.layout.header_card, R.layout.payment_card_empty_view);
bankSection = new PaymentCardAndAccountSection(this, R.layout.header_bank, R.layout.payment_account_empty_view);
sectionedAdapter.addSection(cardSection);
sectionedAdapter.addSection(bankSection);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(sectionedAdapter);
bankSection.setState(Section.State.EMPTY);
}
private void initialToolbar() {
toolbar.setTitle("Payment");
toolbar.setNavigationIcon(R.drawable.ic_back_svg);
setSupportActionBar(toolbar);
}
#Override
public boolean onSupportNavigateUp() {
onBackPressed();
return true;
}
#OnClick(R.id.fab_add_payment)
void launchAddPaymentDialog() {
AddPaymentDialogFragment addPaymentDialogFragment = AddPaymentDialogFragment.newInstance();
addPaymentDialogFragment.setStyle(DialogFragment.STYLE_NO_FRAME, 0);
addPaymentDialogFragment.show(getSupportFragmentManager(), "dialog");
}
#Override
public void onPause() {
super.onPause();
if (subscriptions != null) {
subscriptions.clear();
}
}
Do you use an adapter? In this case adapter.notifyDataSetChanged();
Also, print yout error: throwable.printStackTrace(); in order to see if something goes wrong.
You need to add .observeOn(AndroidSchedulers.mainThread()) after you write subsribeOn() to tell your observable to perform your onNext callback on UI thread/MainThread.
I developed an application to my school and one of the features is principal's updates. For this, I'm using the Firebase realtime database. I need that the app will send automatically notification(background) when a new child(message) is added.
this is my read code(swift):
var messages = [Message]()
override func viewDidLoad() {
super.viewDidLoad()
observeMessages()
}
func observeMessages() {
let dbRef = FIRDatabase.database().reference().child("messageS")
dbRef.observe(.childAdded, with: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject] {
let text = Message()
text.setValuesForKeys(dictionary)
self.messages.insert(text, at: 0)
DispatchQueue.main.async(execute: {
self.tableView.reloadData()
})
}
}, withCancel: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return messages.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .subtitle, reuseIdentifier: "cellId")
let message = messages[indexPath.row]
cell.textLabel?.text = message.title
cell.textLabel?.textAlignment = .center
cell.detailTextLabel?.text = message.message
cell.detailTextLabel?.textAlignment = .right
// Configure the cell...
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let message = messages[indexPath.row]
let title = message.title
let msg = message.message
let controller = UIAlertController(title: title, message: msg, preferredStyle: .alert)
let cancelAction = UIAlertAction(title: "סגור", style: .cancel) { (handler) in
// Any action when you cancel
}
controller.addAction(cancelAction)
self.present(controller, animated: true, completion: nil)
}
this is my write code(swift):
#IBOutlet weak var MessageTitle: UITextField!
#IBOutlet weak var MessageText: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
func post() {
let title: String = MessageTitle.text!
let message: String = MessageText.text!
let post: [String: AnyObject] = ["title": title as AnyObject,
"message": message as AnyObject]
let dbRef = FIRDatabase.database().reference()
dbRef.child("messageS").childByAutoId().setValue(post)
}
#IBAction func Publish(_ sender: AnyObject) {
post()
let MessageSent = UIAlertController(title: "נשלח", message: "ההודעה נשלחה בהצלחה", preferredStyle: UIAlertControllerStyle.alert)
MessageSent.addAction(UIAlertAction(title: "תודה", style: UIAlertActionStyle.default, handler: nil))
self.present(MessageSent, animated: true, completion: nil)
}
this is my read code(android):
private Firebase mRef;
public ArrayList<String> messages = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_updates);
mRef = new Firebase("https://ksharet-d6a24.firebaseio.com");
mRef.child("messageS");
// Get ListView object from xml
final ListView listView = (ListView) findViewById(R.id.ListView);
// Create a new Adapter
final ArrayAdapter<String> adapter = new ArrayAdapter<>(this,
android.R.layout.simple_list_item_1, messages);
// Assign adapter to ListView
listView.setAdapter(adapter);
mRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
Message message = postSnapshot.getValue(Message.class);
messages.add(0, message.getTitle() + '\n' + message.getMessage());
}
adapter.notifyDataSetChanged();
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
}
this is my write code(android):
private Button sendData;
private Firebase mRef;
private EditText messageBox = (EditText) findViewById(R.id.MessageText);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_publish);
Firebase.setAndroidContext(this);
mRef = new Firebase("https://ksharet-d6a24.firebaseio.com/");
mRef.child("message");
sendData = (Button) findViewById(R.id.sendMessage);
sendData.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String message = messageBox.getText().toString();
//Firebase mRefChild = mRef.child("message");
//mRefChild.setValue(message);
mRef.push().setValue(message);
}
});
}
what should I create or change in the code(if you can, for both iOS and Android).
I recently purchased the Apple Developer Program membership and It'll probably be activated soon.
thanks for the helpers.
so, after a lot of time that I've been searching for solutions, I found a really easy way to do it, and it is by using cloud kit. that's the brian advent's tutorial:
https://youtu.be/BXl5o5_2aEU
I suggest you to go to his first video: https://youtu.be/XQ3nLV2778U and just do few of those things.
EDIT: 2017
Now we can use Firebase cloud functions in order to send a push notification when the database changes.
I get an IllegalStateException with "activity has been destroyed" when I close my app.
In my App.cs I declare a public static MasterPage:
protected override void OnStart()
{
// Handle when your app starts
if (Device.OS == TargetPlatform.Android)
{
Device.BeginInvokeOnMainThread(() =>
{
masterdetail = new MasterPage();
MainPage = masterdetail;
});
}
else
{
masterdetail = new MasterPage();
MainPage = masterdetail;
}
}
And in the MasterPage.cs I declare the Master and the DetilPage:
public partial class MasterPage : MasterDetailPage
{
public MasterPage()
{
var IsLoggedIn = false;
if (CrossSecureStorage.Current.HasKey("isLoggedIn"))
{
IsLoggedIn = string.Equals(CrossSecureStorage.Current.GetValue("isLoggedIn"), "true", System.StringComparison.CurrentCultureIgnoreCase);
}
Master = SetMasterContentPage();
if (IsLoggedIn)
{
Detail = new NavigationPage(new TaxonomyOverviewPage());
}
else {
Detail = new NavigationPage(new LoginPage());
}
}
ContentPage SetMasterContentPage()
{
var masterPage = new ContentPage { Title = "Test"};
masterPage.Content = new StackLayout
{
Children = {
new Label{Text="Label1"},
new Label{Text="Label2"},
new Label{Text="Label3"}
}
};
return masterPage;
}
protected override void OnDisappearing()
{
base.OnDisappearing();
GC.Collect();
}
}
Ok, that was a bug in Xamarin.Forms Version 2.3.3.175. To fix this bug install an earlier version of Xamarin.Forms. I get my app running with version 2.3.0.107.
The bug in version 2.3.3.175 should be fixed in version 2.3.4-pre1.
I am making a demo project to change color of a simple TextView using Firebase Remote Config. But the function mRemoteConfig.fetch(cacheExpiration) .addOnCompleteListener... does not trigger at all. The text color does not change.
Here is my code :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView) findViewById(R.id.text);
initRemoteConfig();
}
private void initRemoteConfig() {
mRemoteConfig = FirebaseRemoteConfig.getInstance();
HashMap<String, Object> defaults = new HashMap<>();
defaults.put("color_primary", getString(R.string.color_primary));
mRemoteConfig.setDefaults(defaults);
FirebaseRemoteConfigSettings remoteConfigSettings = new FirebaseRemoteConfigSettings.Builder()
.setDeveloperModeEnabled(true)
.build();
mRemoteConfig.setConfigSettings(remoteConfigSettings);
fetchRemoteConfigValues();
}
private void fetchRemoteConfigValues() {
long cacheExpiration = 3600;
//expire the cache immediately for development mode.
if (mRemoteConfig.getInfo().getConfigSettings().isDeveloperModeEnabled()) {
cacheExpiration = 0;
}
mRemoteConfig.fetch(cacheExpiration)
.addOnCompleteListener(this, new OnCompleteListener<Void>() {
#Override
public void onComplete(Task<Void> task) {
if (task.isSuccessful()) {
// task successful. Activate the fetched data
mRemoteConfig.activateFetched();
setupView();
} else {
//task failed
}
}
});
}
private void setupView() {
setTextColor();
}
private void setTextColor() {
boolean isPromoOn = true;
int color = isPromoOn ? Color.parseColor(mRemoteConfig.getString("color_primary")) :
ContextCompat.getColor(this, R.color.color_primary);
text.setTextColor(color);
}
Am I missing something ? Thanks for help :)
If you have set Firebase Console correctly, I suggest you check whether the newest Google Play Services is available on your phone and work.