I am testing chatting service with "Web socket"
The code doesn't make any error. But, when I lunch the app, it even cannot be started with
the error
06-10 16:59:22.420: E/AndroidRuntime(10814): FATAL EXCEPTION: main
06-10 16:59:22.420: E/AndroidRuntime(10814): java.lang.RuntimeException: Unable to resume activity {com.websocketchat_test/com.websocketchat_test.WebsocketChat}: android.os.NetworkOnMainThreadException
06-10 16:59:22.420: E/AndroidRuntime(10814): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2466)
06-10 16:59:22.420: E/AndroidRuntime(10814): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2494)
06-10 16:59:22.420: E/AndroidRuntime(10814): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2008)
06-10 16:59:22.420: E/AndroidRuntime(10814): at android.app.ActivityThread.access$600(ActivityThread.java:123)
06-10 16:59:22.420: E/AndroidRuntime(10814): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1169)
My main code is here..
public class WebsocketChat extends Activity implements View.OnClickListener{
private static String SERVER_HOST = "10.0.0.1";
private WebSocket websocket;
private EditText messageEditText;
private TextView logsTextView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
messageEditText = (EditText)this.findViewById(R.id.messageEditText);
logsTextView = (TextView)this.findViewById(R.id.logsTextView);
try {
URI url = new URI("ws://" + SERVER_HOST + "/");
websocket = new WebSocketConnection(url);
websocket.setEventHandler(new WebSocketEventHandler() {
Handler handler = new Handler();
public void onOpen() {
updateLog("connected.");
}
public void onMessage(final WebSocketMessage message) {
handler.post(new Runnable() {
public void run() {
updateLog(message.getText().trim());
}
});
}
public void onClose() {
updateLog("closed");
}
});
View sendButton = this.findViewById(R.id.sendButton);
sendButton.setOnClickListener(this);
} catch (WebSocketException wse) {
wse.printStackTrace();
} catch (URISyntaxException use) {
use.printStackTrace();
}
}
#Override
public void onResume() {
super.onResume();
try {
websocket.connect();
} catch (WebSocketException wse) {
wse.printStackTrace();
}
}
public void onClick(View view) {
try {
websocket.send(messageEditText.getText().toString());
messageEditText.setText("");
} catch (WebSocketException wse) {
wse.printStackTrace();
}
}
private void updateLog(String message) {
logsTextView.setText("> " + message + "\n" + logsTextView.getText());
}
}
I don't know why it's happened. I added internet permission for sure..
Any suggestion would be OK. Reply it please.
Recent Android version won't allow any network activity on your main/UI thread. You might have a look at AutobahnAndroid - an Android/Java WebSocket implementation that does all networking on background threads.
Disclosure: I am original author of Autobahn and work for Tavendo.
Related
I have to schedule a work to fetch user current location and update to server in a given interval (Even the app is not running).
I am trying to WorkManagerAPI to implement the functionality.
Is it possible to fetch the current location of the user from the doWork() method ?
locationManager.requestLocationUpdates(
provider, timeInterval, travelDistance, locationListener
);
When I request Location updates from the doWork() it throws below error.
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
As per my understanding, when implementing LocationManager.requestLocationUpdates() on a Worker thread, the call is being made on a non-UI, background thread created by WorkManager. LocationManager.requestLocationUpdates() is an asynchronous call possibly on another background thread. To handle the callbacks defined by the LocationListener, the calling thread must stay alive. Thats why the exception says,
Can't create handler inside thread that has not called Looper.prepare()
Check the code snippet below. Please consider this as pseudocode, I haven't tested this piece of code.
public class LocationWorker extends Worker {
String LOG_TAG = "LocationWorker";
private Context mContext;
private MyHandlerThread mHandlerThread;
public LocationWorker(#NonNull Context context, #NonNull WorkerParameters workerParams) {
super(context, workerParams);
mContext = context;
}
#NonNull
#Override
public Result doWork() {
Log.d(LOG_TAG, "doWork");
mHandlerThread = new MyHandlerThread("MY_THREAD");
mHandlerThread.start();
Runnable runnable = new Runnable() {
#Override
public void run() {
LocationManager locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
String bestProvider = locationManager.getBestProvider(new Criteria(), true);
boolean permission = false;
if (PermissionChecker.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED &&
PermissionChecker.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
Log.e(LOG_TAG, "This app requires ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION permissions.");
permission = true;
}
Log.d(LOG_TAG, "permission: "+permission);
Log.d(LOG_TAG, "bestProvider: "+bestProvider);
if (permission && bestProvider != null) {
MyLocationListener locListener = new MyLocationListener();
locationManager.requestLocationUpdates(bestProvider, 500, 1, locListener, mHandlerThread.getLooper());
}
}
};
mHandlerThread.post(runnable);
return Result.success();
}
class MyHandlerThread extends HandlerThread {
Handler mHandler;
MyHandlerThread(String name) {
super(name);
}
#Override
protected void onLooperPrepared() {
Looper looper = getLooper();
if (looper != null)
mHandler = new Handler(looper);
}
void post(Runnable runnable) {
if (mHandler != null)
mHandler.post(runnable);
}
}
class MyLocationListener implements LocationListener
{
#Override
public void onLocationChanged(final Location loc)
{
Log.d(LOG_TAG, "Location changed: " + loc.getLatitude() +","+ loc.getLongitude());
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
Log.d(LOG_TAG, "onStatusChanged");
}
#Override
public void onProviderDisabled(String provider)
{
Log.d(LOG_TAG, "onProviderDisabled");
}
#Override
public void onProviderEnabled(String provider)
{
Log.d(LOG_TAG, "onProviderEnabled");
}
}
}
When clicked on this textview the app get crashed and didn't change the activity it is suppose to switch from main activity to another how to resolve it?
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private EditText etEmail;
private EditText etPassword;
private TextView tvLogin;
private TextView tvSignup;
private Button btnSignin, btMr;
private FirebaseAuth firebaseAuth;
AwesomeValidation awesomeValidation;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
awesomeValidation = new AwesomeValidation(ValidationStyle.BASIC);
updateUI();
firebaseAuth = FirebaseAuth.getInstance();
}
private void updateUI() {
etEmail = (EditText) findViewById(R.id.etEmail);
tvSignup = (TextView) findViewById(R.id.tvSignup);
etPassword = (EditText) findViewById(R.id.etPassword);
tvLogin = (TextView) findViewById(R.id.tvLogin);
btnSignin = (Button) findViewById(R.id.btnLogin);
tvSignup.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
signup();
}
public void signup() {
Intent i = new Intent(MainActivity.this, Registration.class);
startActivity(i);
}
});
Here I used awesome validation for validating my form but while running the app shows the toast message, but do not register the user to fire base it validate my form but do not register
String regexPassword = "(?=.*[a-z])(?=.*[A-Z])(?=.*[\\d])(?=.*[~`!##\\$%\\^&\\*\\(\\)\\-_\\+=\\{\\}\\[\\]\\|\\;:\"<>,./\\?]).{8,}";
awesomeValidation.addValidation(MainActivity.this, R.id.etEmail, android.util.Patterns.EMAIL_ADDRESS, R.string.etEmailerr);
awesomeValidation.addValidation(MainActivity.this, R.id.etPassword, regexPassword, R.string.etPasserr);
btnSignin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (awesomeValidation.validate()) {
Toast.makeText(MainActivity.this, "Data Recieved Successfully", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, "ERROR", Toast.LENGTH_SHORT).show();
}
}
});
}
This part register the user to firebase, but after adding this awesome validation this do not work app shows a toast message from validation and do not register or change activity how can i merge both so that my form get validate and also get register to my firebase auth
public void btnLogin_Click(View v) {
final ProgressDialog progressDialog = ProgressDialog.show(MainActivity.this, "Please Wait....", "Processing...", true);
(firebaseAuth.signInWithEmailAndPassword(etEmail.getText().toString(), etPassword.getText().toString()))
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
progressDialog.dismiss();
if (task.isSuccessful()) {
Toast.makeText(MainActivity.this, "LOGIN SUCCESSFULL", Toast.LENGTH_LONG).show();
Intent signin = new Intent(MainActivity.this, Dashboard.class);
startActivity(signin);
} else {
Log.e("ERROR", task.getException().toString());
Toast.makeText(MainActivity.this, task.getException().getMessage(), Toast.LENGTH_LONG).show();
}
}
});
}
#Override
public void onClick(View view) {
}
}
this is due to the regex function.
the values used in activity1 regex get differ in another activity2 due to which the intent can't switch from one activity to another.
values passed the the regex should be same in all the activity linked.
I'm saying i'm not a programmer but a guy who has been learning to program with java for a while. I hope to find the solution to my problem here. I'm trying to program my home automation system and remote control and to do this, I chose to use Kryonet. My problem is that every time I send the data to the server, the client opens a new connection. It's been 3 weeks since googlo and I try to figure out how to do it but with no results.
Every help is seriously appreciated. This is my code. Thank you.
This code work in my home network.
Sorry for my english...
public class MainActivity extends AppCompatActivity {
Button button;
String IP = "";
EditText editText;
TextView textView;
EditText editText3;
public static String msg_response;
public static String msg_request;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Handler handler = new MyHandler();
button = (Button) findViewById(R.id.button);
editText = (EditText) findViewById(R.id.editText);
editText3 = (EditText) findViewById(R.id.editText3);
textView = (TextView) findViewById(R.id.textView);
int MY_PERMISSIONS_REQUEST_INTERNET = 1;
int MY_PERMISSIONS_REQUEST_ACCESS_NETWORK_STATE = 1;
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.INTERNET},
MY_PERMISSIONS_REQUEST_INTERNET);
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_NETWORK_STATE},
MY_PERMISSIONS_REQUEST_ACCESS_NETWORK_STATE);
int MY_PERMISSIONS_REQUEST_ACCESS_WIFY_STATE = 1;
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_WIFI_STATE},
MY_PERMISSIONS_REQUEST_ACCESS_WIFY_STATE);
textView.setText(msg_response);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
msg_request = valueOf(editText3.getText().toString());
} catch (Exception e) {
e.printStackTrace();
}
MyThread myThread = new MyThread(handler);
myThread.start();
}
});
}
private class MyHandler extends Handler {
#Override
public void handleMessage(Message msg) {
Bundle bundle = msg.getData();
if (bundle.containsKey("msg da server")) {
String msgin = bundle.getString("msg da server");
textView.setText(msgin);
}
}
}
class MyThread extends Thread {
private Handler handler;
public MyThread(Handler handler) {
this.handler = handler;
}
public void run() {
System.out.println("MyThread running");
Client client = new Client();
client.start();
Kryo kryoClient = client.getKryo();
kryoClient.register(SampleRequest.class);
kryoClient.register(SampleResponse.class);
try {
client.connect(5000, "192.168.0.101", 54555, 54666);
} catch (IOException e) {
e.printStackTrace();
}
client.addListener(new Listener() {
public void received(Connection connection, Object object) {
if (object instanceof SampleResponse) {
SampleResponse response = (SampleResponse) object;
System.out.println(response.text);
msg_response = response.text.toString();
invia_activity(msg_response);
}
}
});
SampleRequest request = new SampleRequest();
request.text = msg_request;
client.sendTCP(request);
}
private void invia_activity(String invia) {
Message msg = handler.obtainMessage();
Bundle b = new Bundle();
b.putString("msg da server", "" + invia);
msg.setData(b);
handler.sendMessage(msg);
}
}
}
I dont have an direct solution, but i have an tutorial for it. I used the same one. So there the connections keeps open, and you can send as many packets as you need. Its without audio, but the code works well. After that you can experiment with the code. It works fine for me. This is the tutorial
I hope i can help you with this.
EDIT:
Maybe you can make an
public static Connection conn;
and you could use that object again and again as your connection to the server.
I have implemented simple RxEventBus which starts emitting events, even if there is no subscribers. I want to cache last emitted event, so that if first/next subscriber subscribes, it receive only one (last) item.
I created test class which describes my problem:
public class RxBus {
ApplicationsRxEventBus applicationsRxEventBus;
public RxBus() {
applicationsRxEventBus = new ApplicationsRxEventBus();
}
public static void main(String[] args) {
RxBus rxBus = new RxBus();
rxBus.start();
}
private void start() {
ExecutorService executorService = Executors.newScheduledThreadPool(2);
Runnable runnable0 = () -> {
while (true) {
long currentTime = System.currentTimeMillis();
System.out.println("emiting: " + currentTime);
applicationsRxEventBus.emit(new ApplicationsEvent(currentTime));
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Runnable runnable1 = () -> applicationsRxEventBus
.getBus()
.subscribe(new Subscriber<ApplicationsEvent>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable throwable) {
}
#Override
public void onNext(ApplicationsEvent applicationsEvent) {
System.out.println("runnable 1: " + applicationsEvent.number);
}
});
Runnable runnable2 = () -> applicationsRxEventBus
.getBus()
.subscribe(new Subscriber<ApplicationsEvent>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable throwable) {
}
#Override
public void onNext(ApplicationsEvent applicationsEvent) {
System.out.println("runnable 2: " + applicationsEvent.number);
}
});
executorService.execute(runnable0);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
executorService.execute(runnable1);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
executorService.execute(runnable2);
}
private class ApplicationsRxEventBus {
private final Subject<ApplicationsEvent, ApplicationsEvent> mRxBus;
private final Observable<ApplicationsEvent> mBusObservable;
public ApplicationsRxEventBus() {
mRxBus = new SerializedSubject<>(BehaviorSubject.<ApplicationsEvent>create());
mBusObservable = mRxBus.cache();
}
public void emit(ApplicationsEvent event) {
mRxBus.onNext(event);
}
public Observable<ApplicationsEvent> getBus() {
return mBusObservable;
}
}
private class ApplicationsEvent {
long number;
public ApplicationsEvent(long number) {
this.number = number;
}
}
}
runnable0 is emitting events even if there is no subscribers. runnable1 subscribes after 3 sec, and receives last item (and this is ok). But runnable2 subscribes after 3 sec after runnable1, and receives all items, which runnable1 received. I only need last item to be received for runnable2. I have tried cache events in RxBus:
private class ApplicationsRxEventBus {
private final Subject<ApplicationsEvent, ApplicationsEvent> mRxBus;
private final Observable<ApplicationsEvent> mBusObservable;
private ApplicationsEvent event;
public ApplicationsRxEventBus() {
mRxBus = new SerializedSubject<>(BehaviorSubject.<ApplicationsEvent>create());
mBusObservable = mRxBus;
}
public void emit(ApplicationsEvent event) {
this.event = event;
mRxBus.onNext(event);
}
public Observable<ApplicationsEvent> getBus() {
return mBusObservable.doOnSubscribe(() -> emit(event));
}
}
But problem is, that when runnable2 subscribes, runnable1 receives event twice:
emiting: 1447183225122
runnable 1: 1447183225122
runnable 1: 1447183225122
runnable 2: 1447183225122
emiting: 1447183225627
runnable 1: 1447183225627
runnable 2: 1447183225627
I am sure, that there is RxJava operator for this. How to achieve this?
Your ApplicationsRxEventBus does extra work by reemitting a stored event whenever one Subscribes in addition to all the cached events.
You only need a single BehaviorSubject + toSerialized as it will hold onto the very last event and re-emit it to Subscribers by itself.
You are using the wrong interface. When you susbscribe to a cold Observable you get all of its events. You need to turn it into hot Observable first. This is done by creating a ConnectableObservable from your Observable using its publish method. Your Observers then call connect to start receiving events.
You can also read more about in the Hot and Cold observables section of the tutorial.
I'm developing an android app that requires to make UI changes according to a background thread processing results, I tried the following code at first:
Thread run_time = new Thread (){
public void run(){
ConnectToServer connect = new ConnectToServer(null);
while(true){
String server_response = connect.getServerResponse();
if(!server_response.equals(null)){
setResponse(server_response);
response_received();
}
}
}
};
run_time.start();
but my App crashes because i tried to make a UI changes from that background thread, then I tried that way:
runOnUiThread(new Runnable() {
public void run(){
ConnectToServer connect = new ConnectToServer(null);
while(true){
String server_response = connect.getServerResponse();
if(!server_response.equals(null)){
setResponse(server_response);
response_received();
}
}
}
});
but i got that exception:
01-29 16:42:17.045: ERROR/AndroidRuntime(605): android.os.NetworkOnMainThreadException
01-29 16:42:17.045: ERROR/AndroidRuntime(605): at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1084)
01-29 16:42:17.045: ERROR/AndroidRuntime(605): at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:151)
01-29 16:42:17.045: ERROR/AndroidRuntime(605): at libcore.io.IoBridge.recvfrom(IoBridge.java:503)
01-29 16:42:17.045: ERROR/AndroidRuntime(605): at java.net.PlainSocketImpl.read(PlainSocketImpl.java:488)
01-29 16:42:17.045: ERROR/AndroidRuntime(605): at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:46)
and after search i found that I must run the code as AsyncTask to avoid these problems, but when attempting to use it i found that it's must be used with small tasks only not like a thread that runs in the background all the run_time.
So, what's the best day to run a thread or a task in the background in whole the run_time and also reflect it's changes to the UI.
EDIT:
For Long running network work you have a few options.
First and formost check the android docs on this topic:
http://developer.android.com/training/basics/network-ops/index.html
Next, I generally use Services for this type of thing:
https://developer.android.com/guide/components/services.html
I will point you at the vogella tutorial for this as well:
http://www.vogella.com/tutorials/AndroidServices/article.html
For communication from threads/asynctasks/services to the UI use Handlers:
Use Handlers:
static public class MyThread extends Thread {
#Override
public void run() {
try {
// Simulate a slow network
try {
new Thread().sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
downloadBitmap = downloadBitmap("http://www.devoxx.com/download/attachments/4751369/DV11");
// Updates the user interface
handler.sendEmptyMessage(0);
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
}
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
// cal uiMethods here...
imageView.setImageBitmap(downloadBitmap);
// dialog.dismiss();
}
};
Taken from this tutorial:
http://www.vogella.com/tutorials/AndroidBackgroundProcessing/article.html
You can make this more interesting by defining constant_codes which corespond to the desired action:
private int DO_THIS = 0x0;
private int DO_THAT = 0x1;
// in your UI:
public void handleMessage(Message msg) {
// cal uiMethods here...
switch(msg.what()){
case(DO_THIS):
// do stuff
break;
case(DO_THAT):
// do other stuff
break;
}
}
// in your thread:
Message m = handler.obtainMessage(DO_THIS);
handler.sendMessage(m);
If the thread code (asynch task, service etc...) is separate from the UI you can use Broadcasts to pass the data between the two and then use Handlers from there to act on the UI thread.
you need to use handlers
here is documntation: https://developer.android.com/training/multiple-threads/communicate-ui.html
Use this code - it may contain compile time error you have to do it correct
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Connect connect = new Connect();
connect.execute();
}
class Connect extends AsyncTask<Void, String, Void>
{
#Override
protected Void doInBackground(Void... params)
{
ConnectToServer connect = new ConnectToServer(null);
while(true)
{
String server_response = connect.getServerResponse();
if(!server_response.equals(null))
{
publishProgress(server_response);
//setResponse(server_response);
response_received();
}
}
return null;
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
setResponse(values[0]);
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
}
}
You need "handlers" along with "loopers" for optimization
Example:
public void myMethod(){
Thread background = new Thread(new Runnable(){
#Override
public void run(){
Looper.prepare();
//Do your server process here
Runnable r=new Runnable() {
#Override
public void run() {
//update your UI from here
}
};
handler.post(r);
Looper.loop();
}
});
background.start();
}
And of course this is without using AsyncTask