I'm writing an app that allows me to send a command through TCP/IP by clicking a button. However when I click to the button in the emulator it comes back with a message saying the button has stopped working. I was wondering if anyone could spot the error in my code.
CODE:
package button.test;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
public class ButtonActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
public void onClick(View view) throws UnknownHostException, IOException
{
Socket socket = new Socket("192.168.2.92", 60128);
try{
dataOutputStream.Object BUFFER = null;
write(BUFFER);
String buffer="ISCP000000100000000701000000!1PWR010D";
OutputStream os=socket.getOutputStream();
os.write(buffer.getBytes());
} catch(IOException e)
{
//error code
}
}
private void write(Object BUFFER) {
// TODO Auto-generated method stub
}
}
1. You missed declaring the button, and initializing it...
Eg:
public class ButtonActivity extends Activity {
Button mbutt;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mbutt = (Button)findViewById(R.id.Button_Click);
}
- Make a note that you must initialize the views only after the setContentView(), else your views won't get the id and will make your App to crash.
2. Its always advisable to keep the UI work on UI thread, and Non-UI work on Non-UI thread, but that became a law with the arrival of HoneyComb android version.
3. You can use Thread with a Handler to sync UI and Non-UI thread.
4. AsyncTask which is known as Painless Threading was introduced specially in android for this.
See this link for tutorials on Threads, Handlers and AsyncTask:
http://www.vogella.com/articles/AndroidPerformance/article.html
It looks like the socket connection work is taking a long time. Suggest putting this functionality inside an AsyncTask.
You haven't declared your button in onCreate()
You don't need to declare the button if you are inflating an xml.
Your problem is that you run a Network connectivity on a main Thread which is not allowed since api 11. Use a asynctask or a thread for this.
e.g.
new Thread() {
public void run() {
Socket socket = new Socket("192.168.2.92", 60128);
try{
dataOutputStream.Object BUFFER = null;
write(BUFFER);
String buffer="ISCP000000100000000701000000!1PWR010D";
OutputStream os=socket.getOutputStream();
os.write(buffer.getBytes());
} catch(IOException e)
{
//error code
}
}
}.start();
Related
I've been running into this bug and I can't seem to figure out how to fix it as I'm fairly new to java and android development so I would really appreciate any help I could get with this!
The bug I'm running into is that when I'm using .setText() to update a TextView element periodically the text displayed on screen never actually changes.
I believe this is due to the while(true) loop in the startCrunching() method I'm using to run the main calculation process as before I start that method the screen updates fine with the test data I'm feeding it.
I also know that when the while loop starts the updateScreen() method is only being called from the while loop and not the repeating handler I have as the handler stops posting logs to the logcat when the method starts but then the while loop logs start being posted.
What I want to achieve is the while(true) loop running as quickly as possible while every so often (as a variable of time and not cycles of the while loop) updating the screen with information regarding the process in the while loop.
I know the while loop is running and the updateScreen() method is being called.
Full source below:
package com.example.android.collatzconjecturepathcruncher;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import java.math.BigInteger;
import java.util.concurrent.TimeUnit;
public class MainActivity extends AppCompatActivity {
TextView longestPathDisplay;
TextView longestPathSeedDisplay;
TextView currentSeedDisplay;
EditText startingNumberDisplay;
BigInteger longestPathSeed= BigInteger.ONE;
int longestPath=0;
BigInteger currentSeed=BigInteger.ZERO;
int currentPath=0;
BigInteger workingSeed=BigInteger.ONE;
boolean run;
int temp =0;
private Handler mHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
longestPathDisplay = findViewById(R.id.longest_path);
longestPathSeedDisplay = findViewById(R.id.longest_path_seed);
currentSeedDisplay = findViewById(R.id.current_seed_display);
startingNumberDisplay = findViewById(R.id.starting_number_display);
longestPathDisplay.setText(getString(R.string.longest_path_display,longestPath));
longestPathSeedDisplay.setText(getString(R.string.longest_path_seed_display,longestPathSeed));
currentSeedDisplay.setText(getString(R.string.current_seed_display,currentSeed));
mHandler = new Handler();
startRepeatingTask();
}
#Override
public void onDestroy(){
super.onDestroy();
stopRepeatingTask();
}
public void startCrunching(View view){
String value = startingNumberDisplay.getText().toString();
currentSeed = new BigInteger(value);
workingSeed=currentSeed;
run=true;
while(run){
if(workingSeed.compareTo(BigInteger.ONE)==0){
if(currentPath>longestPath){
longestPath=currentPath;
longestPathSeed=currentSeed;
}
currentSeed= currentSeed.add(BigInteger.ONE);
workingSeed=currentSeed;
Log.d("end", "startCrunching: Finished "+(currentSeed.subtract(BigInteger.ONE))+" at "+currentPath+". Starting "+currentSeed);
currentPath=0;
updateScreen();
}
if (workingSeed.mod(new BigInteger("2")).compareTo(BigInteger.ZERO)==0){
workingSeed=workingSeed.divide(new BigInteger("2"));
}else{
workingSeed=(workingSeed.multiply(new BigInteger("3"))).add(BigInteger.ONE);
}
currentPath++;
}
}
public void updateScreen() {
//longestPathDisplay.setText(getString(R.string.longest_path_display, longestPath));
//longestPathSeedDisplay.setText(getString(R.string.longest_path_seed_display, longestPathSeed));
//currentSeedDisplay.setText(getString(R.string.current_seed_display, currentSeed));
longestPathDisplay.setText(getString(R.string.longest_path_display, temp));
longestPathSeedDisplay.setText(getString(R.string.longest_path_seed_display, temp));
currentSeedDisplay.setText(getString(R.string.current_seed_display, temp));
Log.d("update","requested screen update. Temp currently: "+temp);
temp++;
}
Runnable mStatusChecker = new Runnable() {
#Override
public void run() {
try{
updateScreen();
Log.d("repeat","Tried Updating Screen");
}finally {
mHandler.postDelayed(mStatusChecker,5000);
}
}
};
void startRepeatingTask(){
mStatusChecker.run();
}
void stopRepeatingTask() {
mHandler.removeCallbacks(mStatusChecker);
}
}
Thanks in advance!
-Michael
Maybe I missed it, but I Don't see where you actual call your crunchnumber method.
startCrunching() this method is never called. I guess you need to change you execution sequence
I am making an app using aide app,when using thread in it & install it then the smart manager of Samsung device shows that the app contains malware.
My codes are for MainActivity.java
package com.mycompany.staticgk;
import android.app.*;
import android.content.*;
import android.os.*;
public class MainActivity extends Activity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final Intent i = new Intent(this,SplashActivity.class);
Thread timer= new Thread (){
public void run(){
try {
try
{
sleep(3000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
finally {
startActivity(i);
finish();
}
}
};
timer.start();
}
}
while for SplashActivity.java
package com.mycompany.staticgk;
import android.app.*;
import android.os.*;
public class SplashActivity extends Activity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.home);
}
}
Please,correct me if anywhere i am wrong.
Is not error on your code.its security based problem .dont install apk with unauthorized app they may be hack your phone informations
Best Use Android Studio [The official Android IDE] to develope code and generate apk with signature key then only
mobile allows to install apk on device.All the native app are developed through android studio only.
otherwise enable Unknown source in your device it may be install on device.
Settings>>Lock screen and security>> tap on toggle button of Unknown Sources.
There are a lot of ways to go to MainActivity from SplashActivity one way could be :
new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(3000);
startActivity(new Intent(MainActivity.class,SplashActivity.class););
finish();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
Also I see something weird with that double try catch block put just one.
Happy coding
I had issues with a previous question where I was unsure whether my code had a memory leak. A few answers were concerned with it being run on the UI thread and so blocking. It is true, it runs on the UI thread and doesn't spawn a new one..
So to solve it I use Thread instead of Handler to spawn a new thread outside of UI. The problem now is that I can't manage to delay it like I did with the one ran in the UI thread.
This is my previous question where my original UI thread code is: Is this Runnable safe from memory leak? and the following is the updated code which spawns a new thread:
package com.example.helloworld;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.widget.TextView;
import android.util.Log;
import java.lang.ref.WeakReference;
public class HelloWorldActivity extends Activity
{
private static TextView txtview;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
txtview = (TextView) findViewById(R.id.mainview);
Thread t = new Thread(new WeakRunnable(txtview));
t.start();
}
private static final class WeakRunnable implements Runnable {
private final WeakReference<TextView> mtextview;
protected WeakRunnable(TextView textview){
mtextview = new WeakReference<TextView>(textview);
}
#Override
public void run() {
TextView textview = mtextview.get();
if (textview != null) {
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
int test = 5*5;
txtview.setText("Hola Mundo"+test);
}
Log.d("com.example.helloworld", "" + Thread.currentThread().getName()); // Outputs "Thread-<num>" if not running on UI thread
}
}
}
It just sets the view text and appends the result of 5*5.
As soon as I start the app it quits itself and I don't get why. Something tells me I'm delaying it the wrong way or using runOnUiThread wrong. Even changing txtview.setText("Hola Mundo"+test); to runOnUiThread( txtview.setText("Hola Mundo"+test) ); doesn't compile giving error: 'void' type not allowed here.
In a nutshell: Computation (5*5 in this case) should be done on a separate thread to avoid blocking the main (UI) thread, and the text should be set on the UI taking the computated item from the separate thread. A simple example of your own would be fine too.
UPDATE
I have posted an answer to my own question implementing AsyncTask.
Use postDelayed method found in the Handler class and Views
change,
Thread t = new Thread(new WeakRunnable(txtview));
t.start();
to :
txtview.postDelayed(new WeakRunnable(txtview), 1500);
Then remove the following sleep clause in your runnable as it is no longer needed
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
You can use condition until it is met instead of using thread.sleep();
Condition.wait(new Callable<Boolean>() {
#Override
public Boolean call() throws Exception {
return textview != null;
}
});
As #Axxiss said, this case is better suited to AsyncTask. I updated my code to use AsyncTask with a WeakReference to avoid memory leaks:
package com.example.helloworld;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.AsyncTask;
import android.widget.TextView;
import android.util.Log;
import java.lang.ref.WeakReference;
public class HelloWorldActivity extends Activity
{
private static TextView txtview;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
txtview = (TextView) findViewById(R.id.mainview);
SimpleTask objSimpleTask=new SimpleTask();
objSimpleTask.execute();
}
private static class SimpleTask extends AsyncTask<Void,Void,String> {
private WeakReference<TextView> mtextview = new WeakReference<TextView>(txtview);
#Override
protected String doInBackground(Void... params) {
Log.d("com.example.helloworld", "" + Thread.currentThread().getName());
try{
Thread.sleep(1500);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
return "Hola Mundo";
}
#Override
protected void onPostExecute(String result) {
TextView mtxtview = mtextview.get();
mtxtview.setText(result);
}
}
}
doInBackground executes the code in a separate thread, while you can later catch the result with onPostExecute and execute it in the main (UI) thread without any frills.
So, I have a login screen. Upon pressing the 'Login' Button a JDBC Connection is made to check the username and password and then move onto the next Activity if the details are correct. As a result of this, the UI hangs for approximately 5 second. I assumed that this was because the connection was created in the same Thread, so I created a new one. I then created a Handler to interact with the UI depending on what happened with this connection.
The trouble is, the UI still hangs. Below is where the new Runnable is declared in the Activity (h is the custom Handler reference belonging to this Activity);
logInButton.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
progress.setVisibility(ProgressBar.VISIBLE);
new LoginProcessor(h).run(); // HERE!
}});
Below is the run() method from the LoginProcessor Runnable which includes the code that is causing the hang. The MicroManager class contains simple JDBC database interactions and makes the connection (nothing exciting in there really and I am trying to keep this as short as possible);
public void run() {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
try{
MicroManager manager = new MicroManager(); // THIS LINE, AND THE LINE BELOW, ARE CAUSING THE HANG!!!!
if(manager.getEmployeeId(h.getLoginName(), h.getPassword())!= 0){
h.sendEmptyMessage(0);
}
}catch(Exception ex){
ex.printStackTrace();
h.sendEmptyMessage(1);
}
}
In the above, there is no direct interaction with the UI. Information is simply sent to the Handler so that it can do it on the UI thread. Lastly, here are the methods of my custom Handler called LogInHandler;
#Override
public void handleMessage(Message msg){
if(msg.what == 0){
activity.startActivity(new Intent(activity, AdvisorsPanelActivity.class));
activity.finish();
}else{
AlertDialog alertDialog = new AlertDialog.Builder(activity).create();
alertDialog.setTitle("Not Working");
alertDialog.show();
activity.setProgressVisible(ProgressBar.GONE);
}
}
public String getLoginName(){
return activity.getLoginName();
}
public String getPassword(){
return activity.getPassword();
}
Sorry to dump so much code on your guys, but I didn't think a complete picture was possible without all the above. I've trimmed it down as much as I can. I've only recently started working with Threading AND Android, so please be gentle with me.
Based on my experience: Use AsyncTask for JDBC and you shall torture no more.
EDIT :
This is a neat example of implementing AsyncTask:
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.Settings.System;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.view.View.OnClickListener;
public class AsyncTaskActivity extends Activity implements OnClickListener {
Button btn;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn = (Button) findViewById(R.id.button1);
// because we implement OnClickListener we only have to pass "this"
// (much easier)
btn.setOnClickListener(this);
}
public void onClick(View view) {
// detect the view that was "clicked"
switch (view.getId()) {
case R.id.button1:
new LongOperation().execute("");
break;
}
}
private class LongOperation extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return "Executed";
}
#Override
protected void onPostExecute(String result) {
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed"); // txt.setText(result);
// might want to change "executed" for the returned string passed
// into onPostExecute() but that is upto you
}
#Override
protected void onPreExecute() {}
#Override
protected void onProgressUpdate(Void... values) {}
}
}
You may want to create and handle your JDBC connection in
doInBackground(String... params) part of your code.
Good Luck.
I am using below code.
import android.app.Activity;
import android.os.Bundle;
import android.provider.ContactsContract.Data;
import android.util.Log;
public class ActivityDemoActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new Thread(new Runnable() {
#Override
public void run() {
int i=0;
while(true){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.i("DATA", "Data.CONTENT_TYPE......"+(i++));
}
}
}).start();
}
#Override
public void onBackPressed(){
finish();
}
}
When I press Back button of device still thread is working in background.
My questions are...
when thread will stop?
Then why we required services in android?
Thank You.
Answers:
1 - it will stop after 100 milliseconds
2 - you need something to work in the background like a service that wakes up and
performs a function without there being a user to initiate it. Or you want to have
a progressDialog that tells the user some work is happening rather than let the user
assume the UI is frozen. Without the background service, your UI is left with an app
that doesn't respond while the work is happening.
Services are basically used for performing long-running application on the background.If you are using any network operations or playing musing or something like that, services are very much helpful..