I want to update my text view on the receivers side as soon as I receive the message. I have the following code which creates the instance of main activity and uses it in the Broadcast receiver to update UI. But the text view isn't getting updated??
public class Mainactivity extends activity{
private static MainActivity ins;
public static MainActivity getInst()
{
return ins;
}
protected void onCreate(Bundle savedInstanceState) {
ins=this;}
public void updateUI(final String s)
{
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
TextView textView=(TextView) findViewById(R.id.textView);
textView.setText(s);
}
});
}
In the smsreceiver class
public class smsreceiver extends BroadcastReceiver
{
try{
if (MainActivity.getInst()!=null)
MainActivity.getInst().updateUI(str);
}
catch(Exception e){
e.printStackTrace();
}
}
Please help me out!!
What if you try like below:
public class Mainactivity extends activity{
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.your_layout);
//register your receiver
}
protected void onDestroy() {
//unregister your receiver
super.onDestroy();
}
public void updateUI(final String s)
{
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
TextView textView=(TextView) findViewById(R.id.textView);
textView.setText(s);
}
});
}
private class smsreceiver extends BroadcastReceiver
{
try{
updateUI(str)
}
catch(Exception e){
e.printStackTrace();
}
}
}
this is my code base you code it can work
public class MainActivity extends Activity
{
private static MainActivity ins;
private Button mButton;
public static MainActivity getInst()
{
return ins;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ins = this;
mButton = (Button) findViewById(R.id.but_send);
mButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent inten = new Intent(MainActivity.this, SmsReceiver.class);
inten.setAction("com.example.demo.action.info");
sendBroadcast(inten);
}
});
}
public void updateUI(final String s)
{
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
TextView textView=(TextView) findViewById(R.id.tv_info);
textView.setText(s);
}
});
}
}
public class SmsReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent) {
try {
if (MainActivity.getInst() != null)
MainActivity.getInst().updateUI("Hello World");
} catch (Exception e) {
e.printStackTrace();
}
}
}
<receiver android:name="com.example.demoexample.SmsReceiver" >
<intent-filter>
<action android:name="com.example.demo.action.info" />
</intent-filter>
</receiver>
Related
Below is my test code. I let the thread sleep on purpose. I tried to simulate the heavy IO task.
I tried to use static inner class. And also used the WeakReference. I think I must miss some very important part. I test the code is still leaking after the activity finished. Can anyone provide some hints? Thanks.
public class Main2Activity extends AppCompatActivity {
TextView textView;
MyAsyn myAsyn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
textView=findViewById(R.id.test_view);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
finish();
}
});
myAsyn=new MyAsyn(textView);
myAsyn.execute();
}
#Override
protected void onDestroy() {
super.onDestroy();
if (myAsyn!=null){
myAsyn.cancel(true);
}
}
static class MyAsyn extends AsyncTask {
WeakReference<TextView> textViewWeakReference;
public MyAsyn(TextView textView) {
this.textViewWeakReference = new WeakReference<>(textView);
}
#Override
protected Object doInBackground(Object[] objects) {
t(textViewWeakReference);
try {
Thread.sleep(10000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Object o) {
super.onPostExecute(o);
TextView textView= textViewWeakReference.get();
if (textView!=null) {
textView.setText("DONE");
}
}
}
public static void t( WeakReference<TextView> textViewWeakReference){
final TextView textView=textViewWeakReference.get();
new Thread(){
#Override
public void run() {
super.run();
try {
Thread.sleep(500000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (textView!=null) {
String a = textView.getText().toString();
String b = a + a;
}
}
}.run();
}
}
I have a fragment with a thread inside it, starting in its onCreate method.
After thread finishes his work i need to send a message to the activity (myActivity) through the "clickButtonOperation".
This is the onCreate() method of my fragment:
public class HolderFragment extends My_Fragment{
private Thread myThread;
.
.
.
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
printf("MyActivity attached is: "+myActivity);
myThread=new Thread(new Runnable(){
#Override
public void run() {
int i=0;
while (i<3){
printf("Working...");
try {
Thread.sleep(2000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
i++;
}
myActivity.clickButtonOperation(new Object[]{
HolderFragment.this.toString()
});
}
});
myThread.start();
}
onCreateView returns NULL.
My question is:
Is it guaranteed that my "clickButonOperation" gets called after the new activity has been attached? or could this method be called before this process?
TEMPORARY SOLUTION:
I created a custom Thread class:
public abstract class My_Thread extends Thread {
private boolean runnable=true;
private boolean paused=false;
private Object[] arguments;
private My_ThreadHolder myHolder;
protected void onPostExecute(Object[] arguments){
while(paused);
runnable=false;
}
protected abstract void execute(Object[] arguments);
protected void notifyUpdate(){
while (paused);
}
protected boolean isRunnable(){
return runnable;
}
public void setArguments(Object[] arguments){
this.arguments=arguments;
}
public Object[] getArguments() {
return arguments;
}
public final void run(){
while (runnable){
execute(arguments);
onPostExecute(arguments);
}
}
public void attach(My_ThreadHolder holder){
myHolder=holder;
}
public My_ThreadHolder getHolder() {
return myHolder;
}
public void startThread(){
runnable=true;
start();
}
public void stopThread(){
runnable=false;
}
public void pauseThread(){
paused=true;
printf("Thread paused");
}
public void resumeThread(){
paused=false;
printf("Thread resumed");
}
}
And created these two:
public class My_ThreadHolder extends My_Fragment{
private TestThread myThread;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
printf("MyActivity attached is: "+myActivity);
myThread=new TestThread();
myThread.attach(this);
myThread.startThread();
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (myThread!=null)myThread.resumeThread();
}
#Override
public void onDetach() {
super.onDetach();
myThread.pauseThread();
}
protected void onNotifyUpdateReceived(Object[] arguments){
myActivity.clickButtonOperation(arguments);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {return null;}
#Override
protected void setGraphics(View view, Bundle savedInstanceState) {}
}
class TestThread extends My_Thread{
#Override
protected void onPostExecute(Object[] arguments) {
super.onPostExecute(arguments);
printf("Thread finished");
}
#Override
protected void execute(Object[] arguments) {
int i=0;
while(i<3){
printf("Working...");
try {
Thread.sleep(2000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
i++;
Object[] myArguments= new Object[2];
myArguments[0]=0;
myArguments[1]=i;
setArguments(myArguments);
notifyUpdate();
}
}
#Override
protected void notifyUpdate() {
super.notifyUpdate();
getHolder().onNotifyUpdateReceived(getArguments());
}
}
You cannot touch the UI from a background thread.. you need to use runOnUiThread method from Activity class, something like this
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
printf("MyActivity attached is: "+myActivity);
myThread = new Thread(new Runnable() {
#Override
public void run() {
int i = 0;
while (i < 3) {
printf("Working...");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
i++;
}
myActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
myActivity.clickButtonOperation(new Object[]{
HolderFragment.this.toString()
});
}
});
}
});
myThread.start();
}
I want to start IntentService from an activity but didn't running. I have tried tested it by using toast or Log but still didn't give any reaction.
Is there i have gone wrong ?
This is my activity:
public class backgroundApplication extends Activity
{
#Override
protected void onCreate(Bundle savedInstanceState) {
findViewById(R.id.cmdServiceIA).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent msgIntent = new Intent(backgroundApplication.this, Service2.class);
startService(msgIntent);
}
});
This is my intentService :
public class Service extends IntentService{
#Override
protected void onHandleIntent(Intent intent) {
mHandler.post(new DisplayToast(this, "Service Start!"));
}
public class DisplayToast implements Runnable {
private final Context mContext;
String mText;
public DisplayToast(Context mContext, String text){
this.mContext = mContext;
mText = text;
}
public void run(){
Toast.makeText(mContext, mText, Toast.LENGTH_SHORT).show();
}
}
Any ideas ?
I know there are already quite a number of discussions about this, but none of what I found could clear my confusion.
I'm using the Android SDK for the first time and my Java Skills are rather average.
I have the following Problem:
From my MainActivity - OnCreate() fct. I start a thread (Receiver), receiving data from a SocketStream. This thread shall refresh a TextView-Element on the GUI when new data was read from the stream.
What is a simple but proper way to do so? I read something about ASyncTask, but did not understand how to implement it.
public class MainActivity extends Activity
{
ExecutorService myExecutor;
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
System.out.println("this is a test"); System.out.flush();
try
{
myExecutor = Executors.newCachedThreadPool();
myExecutor.execute(Receiver.getInstance());
}
catch (IOException e)
{
e.printStackTrace();
}
}
...
public class Receiver implements Runnable
{
[...]
public void run()
{
while (true)
{
//blocking system-io-call to read data from socket..
//extract information
// *** update textView *** ??
}
}
}
You can implement handler in GUI thread to change GUI (in MainActivity in your case):
public Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
//refresh textview
}
};
and than call it from another threads
activity.handler.sendEmptyMessage(what);
You can write your own constructor for Receiver:
public class Receiver implements Runnable
{
[...]
MainActivity activity;
public Receiver(MainActivity activity){
this.activity = activity;
}
public void run()
{
while (true)
{
//blocking system-io-call to read data from socket..
//extract information
// *** update textView *** ??
activity.handler.sendEmptyMessage(0);
}
}
}
You can use runOnUiThread
public class Receiver implements Runnable
{
[...]
public void run()
{
while (true)
{
//blocking system-io-call to read data from socket..
//extract information
runOnUiThread(new Runnable() {
public void run() {
// *** update textView *** ??
}
});
}
}
}
this is a example:
create Counter class :
public class Counter implements Runnable
{
private ICounterEvents listener;
public static Thread OBJ_THREAD = null;
public Counter()
{
OBJ_THREAD = new Thread(this);
}
public void setCountListener(ICounterEvents listener)
{
this.listener = listener;
}
public void start()
{
OBJ_THREAD.start();
}
#Override
public void run()
{
for(int i = 0; i < 100; i++)
{
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
Message msg = Message.obtain();
msg.obj = i;
this.handler.sendMessage(msg);
}
}
private Handler handler =
new Handler()
{
#Override
public void handleMessage(Message msg)
{
if(Counter.this.listener != null)
{
int value = (Integer)msg.obj;
Counter.this.listener.countChanged(value);
}
}
};
}
and create a interface class:
public interface ICounterEvents
{
public void countChanged(int value);
}
and than in your main layout create a textview and a button,
and use this code in onCreate method in MainActivity:
public class MainActivity extends Activity implements ICounterEvents, OnClickListener
{
private TextView txtCounter;
private Button btnStart;
private Counter counter;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.setupViews();
}
private void setupViews()
{
this.counter = new Counter();
this.counter.setCountListener(this);
this.txtCounter = (TextView)findViewById(R.id.txtCount);
this.btnStart = (Button)findViewById(R.id.btnStart);
this.btnStart.setOnClickListener(this);
}
#Override
public void onClick(View v)
{
this.counter.start();
}
public void countChanged(int value)
{
try
{
this.txtCounter.setText(value + "");
}
catch (Exception e)
{
}
}
}
This is my service class in that i increment the i value based on time...
public class BackService extends Service {
int i=0;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
pollForUpdates();
super.onCreate();
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
}
private void pollForUpdates() {
Timer timer=new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
Log.v("Service class called", "service class called "+i);
getRunningApps();
i++;
}
},0,1000);
}
private void getRunningApps()
{
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
I want to append the i value to the TextView. i.e the TextView value is dynamically change based on i value...
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
startService(new Intent(this, BackService.class));
TextView tx=(TextView)findViewById(R.id.textView1);
}}
how to append the i value to tx...
Thank you in advance..
You will need to register Broadcast receiver for Sending data back from Service to Activity.see these usefull example for communication between Activity to service :
http://androidexperinz.wordpress.com/2012/02/14/communication-between-service-and-activity-part-1/
http://androidexperinz.wordpress.com/2012/02/21/communication-between-service-and-activity-part-2/
http://blog.philippheckel.com/2012/06/10/android-example-communication-between-activity-and-service-using-messaging/
Use this
public class MainActivity extends Activity {
TextView tx;
RefreshBroadcastReciver mBroadCastReciver;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
startService(new Intent(this, BackService.class));
tx =(TextView)findViewById(R.id.textView1);
}
#Override
protected void onResume() {
super.onResume();
mBroadCastReciver = new RefreshBroadcastReciver();
registerReceiver(mBroadCastReciver, new IntentFilter("sendData"));
}
private class RefreshBroadcastReciver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
tx.setText(intent.getIntExtra("i", 0)+"");
}
}
#Override
protected void onStop() {
super.onStop();
if(mBroadCastReciver!=null)
unregisterReceiver(mBroadCastReciver);
}
}
and your service is here
public class BackService extends Service {
int i=0;
Intent intent1;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
pollForUpdates();
super.onCreate();
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
intent1=new Intent("sendData");
}
private void pollForUpdates() {
Timer timer=new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
Log.v("Service class called", "service class called "+i);
getRunningApps();
i++;
Message msg=new Message();
msg.arg1=i;
handler.sendMessage(msg);
}
},0,1000);
}
private void getRunningApps()
{
}
#Override
public void onDestroy() {
super.onDestroy();
}
protected Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
intent1.putExtra("i", msg.arg1);
sendBroadcast(intent1);
}
};
}