FirebaseMessagingService singleton? Controlling the instance - firebase

I'm having a problem with use the FirebaseMessagingService. The FirebaseMessagingService works fine. I receive the messages and the notifications. But I need send the message to Activity opened, and invoke a method in activity.
I tried create a listener, but when receive a message, is created a new instance and the listener be null. I understand that FirebaseMessagingService is instanciated when have a message to receive. So I thought in singleton and listener together, don't work, the listener keep null.
Someone have a idea how I can send a message to activity opened?

I don't think any listeners are needed for this. Once you get message in onMessageReceived(), just broadcast it using LocalBroadcastmanager. and receive that broadcast in your activity.
Below is the code snippet to achieve what you want:
MyFirebaseMessagingService.java
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Intent intent = new Intent(**Action**);
intent.putExtra("Some Payload", message.getBody());
mLocalBroadcastManager.sendBroadcast(intent);
}
MainActivity.java
private LocalBroadcastManager mLocalBroadcastManager;
private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
}
};
#Override
protected void onStart() {
super.onStart();
registerBroadcastReceiver();
}
#Override
protected void onStop() {
super.onStop();
unregisterBroadcastReceiver();
}
private void registerBroadcastReceiver() {
mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(**Action**);
mLocalBroadcastManager.registerReceiver(mBroadcastReceiver, intentFilter);
}
private void unregisterBroadcastReceiver() {
mLocalBroadcastManager.unregisterReceiver(mBroadcastReceiver);
}

Be care full though not to exceed limitations of data sizes that can be passed using intents
refer here
https://code.google.com/p/android/issues/detail?id=5878
I understood your question with out any code. Here is pretty much a turn key solution for you that should work. I use this method a lot to pass data between services and activities.
The first thing you need to to is convert the data you want to pass to something that can be passed through an intent.
Strings are easy to work with so convert to string and put in an intent. On the activity side using onCreate and onNewItent you can receive this data no problem. Then convert it back how ever you wish. See code below for an example.
Working with broadcast receivers has the possibilities of giving you data leaks if the receiver is not unRegistered. It will happen if you app crashes and the unRegister is not told to shutdown.
In your FirebaseMessagingService class
import android.os.AsyncTask;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.Map;
/**
* Created by acopp
* Date: 12/31/2016.
* Time: 1:41 PM
* You have permission to use this file for any reason that is not for evil doing
*/
public class FBMService extends FirebaseMessagingService {
static String TAG = "FBMService";
static String FBMServiceAction = "FBMService.Action";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
MainActivity.passIntent(this,FBMServiceAction,getString(remoteMessage));
}
String getString(RemoteMessage message){
Map<String, String> messageData = message.getData();
JSONObject j = new JSONObject();
for (String key : messageData.keySet()) {
String value = messageData.get(key);
try {
j.put(key, value);
} catch (JSONException e) {
e.printStackTrace();
}
}
return j.toString();
}
}
Activity Class
//In your activity class
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* Created by acopp
* Date: 12/31/2016.
* Time: 1:41 PM
* You have permission to use this file for any reason that is not for evil doing
*/
public class MainActivity extends Activity {
private String TAG = "MainActivity";
//Call this from FBMService to start your activity or if your activity is start to receive a new intent
static void passIntent(Context context, String action, String messageDataString) {
Intent intent = new Intent(context, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("action", action);
intent.putExtra("message", messageDataString);
context.startActivity(intent);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate");
intentHandler(getIntent());
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Log.d(TAG, "onNewIntent");
intentHandler(intent);
}
//Use an intent handler to manage onNewIntent and onCreate the same way
void intentHandler(Intent intent) {
if (intent.hasExtra("action")) {
String action = intent.getStringExtra("action");
if(action.equals(FBMService.FBMServiceAction)){
if (intent.hasExtra("message")) {
String messageDataString = intent.getStringExtra("message");
new iterEat().execute(messageDataString);
}
}
}
}
//Convert your string to a HashMap in the background off the main thread
class iterEat extends AsyncTask<String,Void,Map<String, String> > {
#Override
protected Map<String, String> doInBackground(String... rm) {
String messageDataString = rm[0];
try{
return fromString(messageDataString);
}catch (NullPointerException e){
return null;
}
}
#Override
protected void onPostExecute(Map<String, String> s) {
//Your data is pooped out here
Map<String, String> messageData = s;//PLOP
}
}
Map<String, String> fromString(String jsonString) throws NullPointerException{
try {
Map<String, String> messageData = new HashMap<>();
JSONObject j = new JSONObject(jsonString);
Iterator<String> i = j.keys();
while(i.hasNext()){
String key = i.next();
String value = j.getString(key);
messageData.put(key,value);
}
return messageData;
} catch (JSONException e) {
throw new NullPointerException("Didn't work");
}
}
}

Related

I want to store my data in Realm database in Android Studio but it is not working

I want to store my data in realm but it is not working, it show me error when I click on save button where I add toast. There is no error found, but data is not saving.
My MainActivity Class
package com.deitel.realmrecyclerviewspinnerpriority;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.Toast;
import com.deitel.realmrecyclerviewspinnerpriority.Modelclass.ModelClass;
import io.realm.Realm;
public class MainActivity extends AppCompatActivity {
private static final String TAG="MainActivity";
Realm realm;
EditText text_name;
EditText text_details;
Button btn_save;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
realm=Realm.getDefaultInstance();
Realm.init(getApplicationContext());
text_name = findViewById(R.id.text_name);
text_details = findViewById(R.id.text_details);
btn_save.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
savedata(text_name.getText().toString(),text_details.getText().toString());
}
});
}
private void savedata(final String name, final String datails){
realm.executeTransactionAsync(new Realm.Transaction() {
#Override
public void execute(Realm bgrealm) {
// Number maxid=bgrealm.where(ModelClass.class).max("id");
// int newkey=(maxid==null) ? 1 : maxid.intValue()+1;
ModelClass user = bgrealm.createObject(ModelClass.class);
user.setName(name);
user.setDetails(datails);
}
}, new Realm.Transaction.OnSuccess() {
#Override
public void onSuccess() {
Toast.makeText(MainActivity.this, "success", Toast.LENGTH_SHORT).show();
}
}, new Realm.Transaction.OnError() {
#Override
public void onError(Throwable error) {
Toast.makeText(MainActivity.this, "Error", Toast.LENGTH_SHORT).show();
}
});
}
}
Realm Class Where I initilize configutation etc.
package com.deitel.realmrecyclerviewspinnerpriority;
import android.app.Application;
import io.realm.Realm;
import io.realm.RealmConfiguration;
public class MyApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
Realm.init(this);
RealmConfiguration configuration=new RealmConfiguration.Builder().name("RealmData.realm").build();
Realm.setDefaultConfiguration(configuration);
}
}
Model Class.
package com.deitel.realmrecyclerviewspinnerpriority.Modelclass;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
public class ModelClass extends RealmObject {
#PrimaryKey
private String Name;
private String Details;
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public String getDetails() {
return Details;
}
public void setDetails(String details) {
Details = details;
}
}
I think you are not setting primary key,
Try below approach
private void savedata(final String name, final String datails){
try(Realm mRealm = Realm.getDefaultInstance()){
ModelClass user = new ModelClass();
int newkey=(maxid==null) ? 1 : maxid.intValue()+1;
user.setId(newkey);
user.setName(name);
user.setDetails(datails);
mRealm.executeTransaction(rlm-> {
rlm.insertOrUpdate(user);
});
}
}
insertOrUpdate inserts a new record if PK doesn't exists else update it.

JavaFx 2.0 FXML project How to access variables and project structure

I am making an IRC client in a javafx fxml project.
I am having difficulties understanding the structure of the project. I get the MVC pattern however i don't know where i have to position the main code part of the client(object initialisation and communication start).
I want to be able to update a textarea with a String from a serverConnection object when the server sends a message.
So where do i position the code and how do i notify my controller that it has to update its text passing the String simultaneously?
This is the application class:
package jircclient;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.util.concurrent.*;
public class JircClient extends Application
{
#Override
public void start(Stage stage) throws Exception
{
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
stage.setTitle("jircClient");
stage.setScene(scene);
stage.show();
System.out.println("Stage SET!");
//This is where i thought that i could write the main part of the program
//but the stage will not load unless the start method finishes
//Creating a serverConnetion is not a problem since it's only an object
//but starting the communication does not let the method we are in to exit
//since it sticks in a while loop forever until i probably cancel it using a
//button (not implemented yet)
//serverConnection server1 = new serverConnection();
//server1.startCommunication();
}
public static void main(String[] args) throws Exception
{
//In this method i cannot go further unless i close the stage-window
//The purpose of it is to launch the start method
Application.launch(args);
}
}
This is the controller class:
package jircclient;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TextArea;
public class FXMLDocumentController implements Initializable
{
#FXML
private TextArea txt;
#FXML
private void handleButtonAction(ActionEvent event)
{
//In here i will be handling events, however i will need to have
//access to serverConnection objects
System.out.println("You clicked me!");
}
#Override
public void initialize(URL url, ResourceBundle rb)
{
}
}
This is the serverConnection class:
package jircclient;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
public class serverConnection
{
//VARIABLES
private clientInfo client;
private String server_to_connect = "someserver";
private String channel_to_connect = "#somechannel";
private String serv_resp;
private int port = 6667;
private Socket socket;
private BufferedWriter writer;
private BufferedReader reader;
private ArrayList<channel> channels;
//DEFAULT CONSTRUCTOR
public serverConnection() {client = new clientInfo("test1", "test1", "test1");}
//FULL CONSTRUCTOR
public serverConnection(String server_to_connect, int port, String channel_to_connect) throws IOException
{
client = new clientInfo("test1", "test1", "test1");
this.server_to_connect = server_to_connect;
this.port = port;
this.channel_to_connect = server_to_connect;
try
{
//Creating socket connection
this.socket = new Socket(this.server_to_connect,port);
//Socket output writer
writer = new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream()));
//Socket input writer
reader = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
serv_resp = null;
System.out.println("Connection established.");
}
catch(UnknownHostException exc)
{
System.out.println("ERROR: "+ exc.toString());
}
catch(IOException exc)
{
System.out.println("ERROR: "+ exc.toString());
}
finally
{
System.out.println("Closing connection.");
socket.close();
}
}
//server response getter
public String getServerResponse()
{
return serv_resp;
}
//Introduction to server and listen
public void startCommunication() throws IOException
{
this.socket = new Socket(this.server_to_connect,port);
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
serv_resp = null;
writer.write("NICK " + client.getClientNickname() + "\r\n");
writer.write("USER " + client.getClientLogin() + " 0 * : " +
client.getClientRealName() + "\r\n");
while ((serv_resp = reader.readLine()) != null)
{
System.out.println(serv_resp);
//FXMLDocumentController.txt.setText(serv_resp);
if (serv_resp.indexOf("004") >= 0)
{
break;
}
else if (serv_resp.indexOf("433") >= 0)
{
System.out.println("Nickname is already in use.");
return;
}
}
//Get channel list
writer.write("LIST \r\n");
writer.flush();
//Join desired client
writer.write("JOIN " + channel_to_connect + "\r\n");
writer.flush();
//keep listening
while ((serv_resp = reader.readLine()) != null)
{
//FXMLDocumentController.txt.setText(serv_resp);
if (serv_resp.startsWith("PING "))
{
this.pingPong();
} else
{
System.out.println(serv_resp);
}
}
}
//Ping respond
public void pingPong() throws IOException
{
writer.write("PONG " + serv_resp.substring(5) + "\r\n");
writer.flush();
}
}
I believe there is no need to add the fxml document since it's big and there is no need.
I also have to state that oracle tutorials were not helpful as they only use the event handling in the controller and they don't implement any other logic.
Here is one possible way to do this:
Give your ServerConnection class a callback to call when it receives a message:
public class ServerConnection {
private Consumer<String> messageCallback ;
public void setMessageCallback(Consumer<String> messageCallback) {
this.messageCallback = mesasgeCallback ;
}
// other fields and methods as before...
public void startCommunication() throws IOException {
// code as before ...
while ((servResp = reader.readLine()) !=null) {
if (messageCallback != null) {
messageCallback.accept(servResp);
}
// etc....
}
// etc
}
}
Now instantiate your ServerConnection class from the controller and pass it a callback:
public class FXMLDocumentController {
ServerConnection serverConnection ;
// ...
public void initialize() {
serverConnection = new ServerConnection();
serverConnection.setMessageCallback(message ->
Platform.runLater(() -> txt.appendText(message+"\n")));
Thread serverThread = new Thread(() -> serverConnection.startListening());
serverThread.setDaemon(true); // thread will not stop application from exiting
serverThread.start();
}
// ...
}

Reload ListFragment loaded by LoaderManager.LoaderCallbacks<List<Item>>

How i can refresh listfragment? no tutorials from net work :(
i have no idea, how reload this listfragment. I tried reload by transaktionmanager, but its colide with ActionBar.TabListener, this is not support.v4. how can i retrieve new data from loadermanager and update listfragment?
Activity:
package sk.test;
import android.app.ActionBar;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.app.FragmentTransaction;
import android.support.v4.app.LoaderManager;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import java.util.List;
import java.util.Locale;
import sk.test.frags.TodoFragment;
import sk.test.prefs.EditPreferences;
import sk.test.task.DataListLoader;
import sk.test.xml.Item;
public class MainActivity extends FragmentActivity implements ActionBar.TabListener {
SectionsPagerAdapter mSectionsPagerAdapter;
/**
* The {#link ViewPager} that will host the section contents.
*/
ViewPager mViewPager;
private TodoFragment todoFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Set up the action bar.
final ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Create the adapter that will return a fragment for each of the three
// primary sections of the app.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
// When swiping between different sections, select the corresponding
// tab. We can also use ActionBar.Tab#select() to do this if we have
// a reference to the Tab.
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
});
// For each of the sections in the app, add a tab to the action bar.
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
// Create a tab with text corresponding to the page title defined by
// the adapter. Also specify this Activity object, which implements
// the TabListener interface, as the callback (listener) for when
// this tab is selected.
actionBar.addTab(
actionBar.newTab()
.setText(mSectionsPagerAdapter.getPageTitle(i))
.setTabListener(this));
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
switch (item.getItemId()) {
case R.id.action_settings:
startActivity(new Intent(getApplicationContext(), EditPreferences.class));
return true;
case R.id.refresh:
//HERE CODE FOR RELOAD todoFragment.reloadData() ????
return true;
default:
return true;
}
}
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
// When the given tab is selected, switch to the corresponding page in
// the ViewPager.
mViewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
/**
* A {#link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
private boolean wantDone = false;
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
todoFragment = new TodoFragment();
this.wantDone = position == 0 ? false : true;
Bundle args = new Bundle();
args.putBoolean(TodoFragment.TASK_TYPE, this.wantDone);
todoFragment.setArguments(args);
return todoFragment;
}
#Override
public int getCount() {
return 2;
}
public boolean getWantDone(){
return this.wantDone;
}
#Override
public CharSequence getPageTitle(int position) {
Locale l = Locale.getDefault();
switch (position) {
case 0:
return getString(R.string.todotask_planned).toUpperCase(l);
case 1:
return getString(R.string.todotask_done).toUpperCase(l);
}
return null;
}
}
}
ListFragment:
package sk.test;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.util.Log;
import android.view.View;
import android.widget.ListView;
import java.util.List;
import sk.test.adapter.CustomArrayAdapter;
import sk.test.task.DataListLoader;
import sk.test.xml.Item;
/**
* Created by Peter on 29.7.2013.
*/
public class TodoFragment extends ListFragment implements LoaderManager.LoaderCallbacks<List<Item>> {
public static String TASK_TYPE = "taskType";
private static final String XML_SOURCE = "http://******/";
private boolean wantDone = false;
CustomArrayAdapter mAdapter;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.i("TODOLIST", "DataListFragment.onActivityCreated");
this.wantDone = getArguments().getBoolean(TASK_TYPE);
// Initially there is no data
setEmptyText("No Data Here");
// Create an empty adapter we will use to display the loaded data.
mAdapter = new CustomArrayAdapter(getActivity());
setListAdapter(mAdapter);
// Start out with a progress indicator.
setListShown(false);
// Prepare the loader. Either re-connect with an existing one,
// or start a new one.
getLoaderManager().initLoader(0, null, this);
setHasOptionsMenu(true);
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
// Insert desired behavior here.
Log.i("TODOLIST", "Item clicked: " + id);
}
#Override
public Loader<List<Item>> onCreateLoader(int i, Bundle bundle) {
Log.i("TODOLIST", "DataListFragment.onCreateLoader");
return new DataListLoader(getActivity(), this.wantDone);
}
#Override
public void onLoadFinished(Loader<List<Item>> listLoader, List<Item> items) {
mAdapter.setData(items);
Log.i("TODOLIST", "DataListFragment.onLoadFinished");
// The list should now be shown.
if (isResumed()) {
setListShown(true);
} else {
setListShownNoAnimation(true);
}
}
#Override
public void onLoaderReset(Loader<List<Item>> listLoader) {
}
public void reloadData(){
//UPDATE LIST.. HOW?
}
}
Loader:
package sk.test;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.v4.content.AsyncTaskLoader;
import android.util.Log;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import sk.test.commons.Commons;
import sk.test.xml.Item;
import sk.test.xml.Response;
/**
* Created by Peter Chovan on 29.7.2013.
*/
public class DataListLoader extends AsyncTaskLoader<List<Item>> {
private List<Item> todoTasks;
private boolean wantDone;
SharedPreferences prefs;
public DataListLoader(Context context, boolean wantDone) {
super(context);
this.wantDone = wantDone;
prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
}
#Override
public List<Item> loadInBackground() {
Log.i("TODOLIST", "DataListLoader.loadInBackground");
String xmlData = getXmlData(prefs.getString("service_url", "http://*****/"));
List<Item> entries = new ArrayList<Item>();
String state = wantDone ? "WANT DONE" : "WANT PLANNED";
if (xmlData != null) {
xmlData = xmlData.replaceAll("<([^/]+?)/>", "<$1> </$1>");
Serializer serializer = new Persister();
try {
Response res = serializer.read(Response.class, xmlData, false);
for (Item i : res.getItems().getItem()) {
if (i.isDone() == wantDone) {
entries.add(i);
}
}
} catch (Exception e) {
for (StackTraceElement s : e.getStackTrace()) {
Log.e("TEST serializer", s.toString());
}
}
} else {
Log.e("TODOLIST DATA", "NULL");
}
return entries;
}
public String getXmlData(String uri) {
try {
URL url = new URL(uri);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setDoOutput(true);
con.setRequestProperty("Accept", "application/xml");
Map<String, String> params = new HashMap<String, String>();
params.put("user", prefs.getString("service_login", "devel"));
params.put("pass", prefs.getString("service_password", "devel"));
params.put("class", "GetList");
OutputStreamWriter wr = new OutputStreamWriter(con.getOutputStream());
wr.write(Commons.getRequestData(params)); //add request params
wr.flush();
String xmlData = readStream(con.getInputStream());
wr.close();
con.disconnect();
return xmlData;
} catch (Exception e) {
for (StackTraceElement s : e.getStackTrace()) {
Log.e("TODOLIST", "doInBackground" + s.toString());
}
}
return null;
}
private String readStream(InputStream in) {
BufferedReader reader = null;
String result = "";
try {
reader = new BufferedReader(new InputStreamReader(in));
String line;
while ((line = reader.readLine()) != null) {
result += line + "\n";
}
return result;
} catch (IOException e) {
for (StackTraceElement s : e.getStackTrace()) {
Log.e("TODOLIST", "ReadStream || " + s.toString());
}
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
for (StackTraceElement s : e.getStackTrace()) {
Log.e("TODOLIST", "ReadStream || " + "Error while closing Reader");
}
}
}
}
return null;
}
/**
* Called when there is new data to deliver to the client. The
* super class will take care of delivering it; the implementation
* here just adds a little more logic.
*/
#Override
public void deliverResult(List<Item> listOfData) {
if (isReset()) {
// An async query came in while the loader is stopped. We
// don't need the result.
if (listOfData != null) {
onReleaseResources(listOfData);
}
}
List<Item> oldApps = listOfData;
todoTasks = listOfData;
if (isStarted()) {
// If the Loader is currently started, we can immediately
// deliver its results.
super.deliverResult(listOfData);
}
// At this point we can release the resources associated with
// 'oldApps' if needed; now that the new result is delivered we
// know that it is no longer in use.
if (oldApps != null) {
onReleaseResources(oldApps);
}
}
/**
* Handles a request to start the Loader.
*/
#Override
protected void onStartLoading() {
if (todoTasks != null) {
// If we currently have a result available, deliver it
// immediately.
deliverResult(todoTasks);
}
if (takeContentChanged() || todoTasks == null) {
// If the data has changed since the last time it was loaded
// or is not currently available, start a load.
forceLoad();
}
}
/**
* Handles a request to stop the Loader.
*/
#Override
protected void onStopLoading() {
// Attempt to cancel the current load task if possible.
cancelLoad();
}
/**
* Handles a request to cancel a load.
*/
#Override
public void onCanceled(List<Item> apps) {
super.onCanceled(apps);
// At this point we can release the resources associated with 'apps'
// if needed.
onReleaseResources(apps);
}
/**
* Handles a request to completely reset the Loader.
*/
#Override
protected void onReset() {
super.onReset();
// Ensure the loader is stopped
onStopLoading();
// At this point we can release the resources associated with 'apps'
// if needed.
if (todoTasks != null) {
onReleaseResources(todoTasks);
todoTasks = null;
}
}
/**
* Helper function to take care of releasing resources associated
* with an actively loaded data set.
*/
protected void onReleaseResources(List<Item> apps) {
}
}
Use this to restart the Loader: getLoaderManager().restartLoader(0, null, this);

Is PlayN websocket implementation in Java supposed to be working?

According to the platform status, it should. I am trying to accomplish a basic Hello World proof of concept but I can't get my Java client connect to my server with PlayN. As soon as I call createWebSocket(), the onClose() gets called. However, I was able to connect to my server using a standard html page.
Client code:
WebSocket s = PlayN.net().createWebSocket("ws://localhost:8080/test", new Net.WebSocket.Listener(){
public void onClose() {System.out.println("close");};
public void onDataMessage(ByteBuffer msg) {System.out.println("data");};
public void onError(String reason) {System.out.println("error");};
public void onOpen() {System.out.println("open");};
public void onTextMessage(String msg) { System.out.println("text");};
});
Here is sample WebSocket Servlet implementation on Jetty:
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.websocket.WebSocket;
import org.eclipse.jetty.websocket.WebSocketFactory;
public class SampleServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private WebSocketFactory wsFactory;
private final Set<SampleWebSocket> members = new CopyOnWriteArraySet<SampleWebSocket>();
#Override
public void init() throws ServletException {
wsFactory = new WebSocketFactory( new WebSocketFactory.Acceptor() {
#Override
public boolean checkOrigin( final HttpServletRequest request, final String origin ) {
// Allow all origins
return true;
}
#Override
public WebSocket doWebSocketConnect( final HttpServletRequest request, final String protocol ) {
return new SampleWebSocket();
}
} );
wsFactory.setBufferSize( 4096 );
wsFactory.setMaxIdleTime( 60000 );
}
#Override
protected void doGet( final HttpServletRequest request, final HttpServletResponse response ) throws IOException {
if ( wsFactory.acceptWebSocket( request, response ) ) {
return;
}
response.sendError( HttpServletResponse.SC_SERVICE_UNAVAILABLE, "Websocket only" );
}
public class SampleWebSocket implements WebSocket.OnTextMessage {
private volatile Connection connection;
public SampleWebSocket( ) {
}
#Override
public void onClose( final int closeCode, final String message ) {
members.remove( this );
System.out.println( "onClose: closeCode=" +closeCode+ ", message: '" +message+ "'" );
}
#Override
public void onOpen( final Connection connection ) {
this.connection = connection;
System.out.println( "onOpen: connection=" +connection );
members.add( this );
// Send sample binary message back
try {
connection.sendMessage( "Sample message" );
} catch ( final IOException e ) {
e.printStackTrace();
}
}
#Override
public void onMessage( final String data ) {
System.out.println( "onMessage: data=" +data );
// Relay message to other connected clients
for ( final SampleWebSocket member: members ) {
try {
member.connection.sendMessage( data );
} catch ( final IOException e ) {
e.printStackTrace();
}
}
}
}
}
I finally found the problem. Version 1.4 of PlayN uses Draft10 dy default. I have updated my local copy of PlayN to use : http://mvnrepository.com/artifact/com.netiq/websocket and I changed the default Draft to Draft17 and it could connect to Tomcat.

Asynchronous calls in my netty Client does not get handled

I have written a Netty server which sends asynchronous messages. The server is working as expected.
I can telnet to the server with a couple of telnet sessions and the asynchronous messages gets written out.
I have written a Netty Client but the client seems to be event driven and not asynchronous. On the server when the client connects; the server writes back to the client "Welcome" and the messages get handled in the client by the messageReceived event, any asynchronous event does not fire any event within the SimpleChannelHandler.
Question: How do I get the Netty client to pick up asynchronous message/events? At the moment it is event driven.
Just to add, the client is the Netty Telnet client.[http://netty.io/docs/stable/xref/org/jboss/netty/example/telnet/package-summary.html]
The Server Code
//---------Server code---------------
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
public class TestServer {
private final ServerBootstrap clientServerBootstrap;
private EchoServerFactory echoServerFactory;
private Channel appChannel;
public TestServer() {
this.clientServerBootstrap = new ServerBootstrap(
new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
this.clientServerBootstrap.setOption("child.tcpNoDelay", true);
}
public static void main(String[] args) {
try {
TestServer test = new TestServer();
test.start();
for(int i = 0; i < 100; i++) {
long time = System.currentTimeMillis()+1000;
String data = "setPhase();d(1,1,2.2342,"+time+");";
System.out.println(data);
test.write(data);
Thread.sleep(1000);
}
} catch(Exception ex) {
ex.printStackTrace();
}
}
public void start() {
echoServerFactory = new EchoServerFactory();
clientServerBootstrap.setPipelineFactory(echoServerFactory);
InetSocketAddress isaApp = new InetSocketAddress("127.0.0.1", 9090);
appChannel = clientServerBootstrap.bind(isaApp);
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
public void run() {
stop();
}
}));
}
public void write(String message) throws Exception {
echoServerFactory.write(message);
}
public void stop() {
clientServerBootstrap.releaseExternalResources();
}
}
//---------------Factory----------------------------
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.handler.codec.frame.DelimiterBasedFrameDecoder;
import org.jboss.netty.handler.codec.frame.Delimiters;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;
public class EchoServerFactory implements ChannelPipelineFactory {
EchoServerHandler handler = new EchoServerHandler();
public EchoServerHandler getHandler() {
return handler;
}
public void write(String message) throws Exception {
handler.write(message);
}
public ChannelPipeline getPipeline() throws Exception {
// Create a default pipeline implementation.
ChannelPipeline pipeline = org.jboss.netty.channel.Channels.pipeline();
// Add the text line codec combination first,
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());
// and then business logic.
pipeline.addLast("handler", handler);
return pipeline;
}
}
//---------------Handler----------------------------
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ChildChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.channel.WriteCompletionEvent;
import org.jboss.netty.channel.group.ChannelGroup;
import org.jboss.netty.channel.group.DefaultChannelGroup;
public class EchoServerHandler extends SimpleChannelHandler {
private static final Logger logger = Logger.getLogger(EchoServerHandler.class.getName());
static final ChannelGroup channels = new DefaultChannelGroup();
public void write(String message) throws Exception {
channels.write(message);
}
#Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
Channel channel = e.getChannel();
channels.add(channel);
channel.write("Welcome\n\n");
}
#Override
public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
// Unregister the channel from the global channel list
// so the channel does not receive messages anymore.
//channels.remove(e.getChannel());
}
#Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
// Send back the received message to the remote peer.
System.out.println("------------------------->"+e.getMessage());
Channel ch = e.getChannel();
ChannelFuture f = ch.write(e.getMessage());
/* f.addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) {
Channel ch = future.getChannel();
System.out.println("Completed : "+ch.isOpen());
}
});*/
}
#Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
// Close the connection when an exception is raised.
logger.log(
Level.WARNING,
"Unexpected exception from downstream.",
e.getCause());
e.getChannel().close();
}
}
The Client Code
//---------------- Client Code -------------------
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import org.jfree.ui.RefineryUtilities;
/**
* Simplistic telnet client.
*/
public class TelnetClient {
private final String host;
private final int port;
public TelnetClient(String host, int port) {
this.host = host;
this.port = port;
}
public void run() throws IOException {
// Configure the client.
ClientBootstrap bootstrap = new ClientBootstrap(
new NioClientSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
// Configure the pipeline factory.
bootstrap.setPipelineFactory(new TelnetClientPipelineFactory());
bootstrap.setOption("tcpNoDelay", true);
// Start the connection attempt.
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
// Wait until the connection attempt succeeds or fails.
Channel channel = future.awaitUninterruptibly().getChannel();
if (!future.isSuccess()) {
future.getCause().printStackTrace();
bootstrap.releaseExternalResources();
return;
}
// Read commands from the stdin.
ChannelFuture lastWriteFuture = null;
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
for (;;) {
String line = in.readLine();
if (line == null) {
break;
}
// Sends the received line to the server.
lastWriteFuture = channel.write(line + "\r\n");
// If user typed the 'bye' command, wait until the server closes
// the connection.
if (line.toLowerCase().equals("bye")) {
channel.getCloseFuture().awaitUninterruptibly();
break;
}
}
// Wait until all messages are flushed before closing the channel.
if (lastWriteFuture != null) {
lastWriteFuture.awaitUninterruptibly();
}
// Close the connection. Make sure the close operation ends because
// all I/O operations are asynchronous in Netty.
channel.close().awaitUninterruptibly();
// Shut down all thread pools to exit.
bootstrap.releaseExternalResources();
}
public static void main(String[] args) throws Exception {
try {
// Parse options.
String host = "127.0.0.1";
int port = 9090;
new TelnetClient(host, port).run();
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
//---------------- Client Factory -------------------
import static org.jboss.netty.channel.Channels.*;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.handler.codec.frame.DelimiterBasedFrameDecoder;
import org.jboss.netty.handler.codec.frame.Delimiters;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;
/**
* Creates a newly configured {#link ChannelPipeline} for a new channel.
*/
public class TelnetClientPipelineFactory implements ChannelPipelineFactory {
public ChannelPipeline getPipeline() throws Exception {
// Create a default pipeline implementation.
ChannelPipeline pipeline = pipeline();
// Add the text line codec combination first,
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(1118192, Delimiters.lineDelimiter()));
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());
// and then business logic.
pipeline.addLast("handler", new TelnetClientHandler2());
return pipeline;
}
}
//----------------- Client handler -------------------
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ChildChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
import org.jboss.netty.channel.WriteCompletionEvent;
/**
* Handles a client-side channel.
*/
public class TelnetClientHandler extends SimpleChannelHandler {
private static final Logger logger = Logger.getLogger(TelnetClientHandler.class.getName());
#Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
System.out.println("messageReceived");
String message = (String) e.getMessage();
parseMessage(message);
}
private void parseMessage(String message) {
try {
System.out.println("Messatge --> "+message);
} catch (Exception ex) {
ex.printStackTrace();
}
}
#Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
System.out.println(e.getCause());
logger.log(Level.WARNING,"Unexpected exception from downstream.", e.getCause());
e.getChannel().close();
}
}
Since you are using delimiter based frame decoder in the Netty Client App, it expects the delimiter at end of each message, but it looks like the server is not sending message with delimiter.
String data = "setPhase();d(1,1,2.2342,"+time+");";
System.out.println(data);
test.write(data);
after above messages are sent, frame decoder is keep waiting even after it received many messages. It works in telnet because, telnet session expects one character at a time. You have done it correctly only for the first message.
channel.write("Welcome\n\n");

Resources