7

I have a newbie question about Class/Task/Activity. I'm coming from C so I don't know if it's a good approach to do what I need.

I've created a class:

public class UDPServer {

    private MyDatagramReceiver myDatagramReceiver = null;

    private static int MAX_UDP_DATAGRAM_LEN = 1024;
    private static int UDP_SERVER_PORT = 5000;

    public void start() {
        myDatagramReceiver = new MyDatagramReceiver();
        myDatagramReceiver.start();
    }

    public void kill() {
        myDatagramReceiver.kill();
    }

    private class MyDatagramReceiver extends Thread {
        private boolean bKeepRunning = true;
        private String lastMessage = "";

        public void run() {
            String message;
            byte[] lmessage = new byte[MAX_UDP_DATAGRAM_LEN];
            DatagramPacket packet = new DatagramPacket(lmessage, lmessage.length);
            DatagramSocket socket = null;

            try
            {
                socket = new DatagramSocket(UDP_SERVER_PORT);

                while(bKeepRunning)
                {
                    socket.receive(packet);
                    message = new String(lmessage, 0, packet.getLength());
                    lastMessage = message;

                    //Here should call activity method

                });
                }

            }
            catch (Throwable e)
            {
                e.printStackTrace();
            }
            finally
            {
                if (socket != null)
                {
                    socket.close();
                }
            }
        }

        public void kill() {
            bKeepRunning = false;
        }
    }
}

Inside my Activity I've:

@Override
public void onResume() {
    super.onResume();

    mUDPServer = new UDPServer();
    mUDPServer.start();
}

@Override
public void onPause() {
    super.onPause();

    mUDPServer.kill();
}

Now, every time I received a packet I want that this thread/class pass received packet to an Activity method that elaborate(do some calculation or update some UI ecc..) this incoming data. But I can't figure how to do this, maybe my approach is not correct. I can place thread code inside Activity but it seems to make code less readable.

Suggestion how to do this?

@Anshul Jain CODE UPDATE:

    public class Main_activity extends Activity implements Interface_UDPServer{
    TextView recived_message;

    UDPServer mUDPServer;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        recived_message = (TextView)findViewById(R.id.recived_message);
    }

    @Override
    public void onResume() {
        super.onResume();

        mUDPServer = new UDPServer(this);
        mUDPServer.start();
    }

    @Override
    public void onPause() {
        super.onPause();

        mUDPServer.kill();
    }

    public void sendData(final String str){
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                recived_message.setText(str);
            }
        });
    }

}

XML file

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_below="@+id/linearLayout"
        android:layout_alignLeft="@+id/linearLayout"
        android:layout_alignStart="@+id/linearLayout">
    <TextView
        android:id="@+id/recived_message"
        android:layout_width="200dp"
        android:layout_height="35dp"
        android:textColor="#444444"
        android:textSize="20dp" />
    </LinearLayout>
</RelativeLayout>
Farya
  • 277
  • 3
  • 14
Singee
  • 523
  • 2
  • 6
  • 16

7 Answers7

9

You can use Callback for this purpose.

Define some interface like

public interface MyCustomInterface(){
    public void sendData(String str);
}

Now let your Activity implement this interface.

public class MyActivity implements MyCustomInterface {

@Override
public void sendData(String str){

Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
  @Override
  public void run() {
    recived_message.setText(str);
  }
});
}
}

Now in UDPServer.java, write the following code

public class UDPServer {

private MyCustomInterface interface;

UDPServer(MyCustomInterface interface){
 this.interface = interface; 
}

}

Now whenever you have some data available lets say a string, you can send it like this

interface.sendData(str);
Shadman Akhtar
  • 99
  • 2
  • 11
thedarkpassenger
  • 7,158
  • 3
  • 37
  • 61
  • 1
    I've tryed your code and corrected this: "public class MyCustomInterface(){" to "public interface MyCustomInterface(){" and this "private MyCustomInterface interface;" to "private MyCustomInterface otherNameInterface;" becouse Android IDE taked interface name as definition. – Singee Jan 25 '16 at 16:00
  • Still not, I've debugged and I can correctly recive packet and transfer to Activity. But when I run an example "recived_message.setText(str);" it doesn't update my ViewText. Also tried with runOnUiThread(new Runnable() { @Override public void run() { recived_message.setText(str); } }); but nothing – Singee Jan 25 '16 at 16:52
  • if you are able to get the data on UI activity, then there is no reason that the Textview is not getting updated. You must be missing something. Can you put your latest code ? – thedarkpassenger Jan 25 '16 at 16:53
  • I have updated the code inside sendData function, see if its works – thedarkpassenger Jan 25 '16 at 17:16
  • Thanks, now works. Can you kindly explain me why previously was not working although I was using "runOnUiThread(new Runnable() {" ? also, I've read about Handler method too without use of interface, what are main differences? – Singee Jan 25 '16 at 17:33
  • 1
    http://stackoverflow.com/questions/13974661/runonuithread-vs-looper-getmainlooper-post-in-android. Go through this answer. And please accept the answer if your issue is resolved. – thedarkpassenger Jan 25 '16 at 17:39
  • Actually runOnUIThread(new Runnable) should also do the job because it is meant for the same purpose. I tried to run your code but it was throwing some errors. Therefore I suggested the other way. – thedarkpassenger Jan 25 '16 at 17:43
2

You have an A activity and B one, when you finish actions on B activity side you need it to effect A side when you come back.

  1. Create an Instance Class and a method that u type u need, let's say;

    public interface SelectedBirthday {
    
        void onSelectedData(String date);
    }
    
  2. Now we are on B side, Create an instance of your Interface Class

    private SelectedBirthday mCallback;
    
  3. Override

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
    
        try {
            mCallback = (SelectedBirthday) activity;
        } catch (ClassCastException e) {
            Log.d("MyDialog", "Activity doesn't implement the ISelectedData interface");
        }
    }
    
  4. Now upload the value you needed

    String userBirth = (day + " " + month + " " + year);
    
    mCallback.onSelectedData(userBirth);
    
  5. Ok let's go to A side

Implement our Interface Class

implements SelectedBirthday

it will warn you for its method and you implemented it

     @Override
        public void onSelectedData(String date) {
            if (!date.equals("")) {
                txt_poup_age.setText(date);
//now you are free to do what you want with the value you received automaticaly
            }
        }
iUser
  • 1,075
  • 3
  • 20
  • 49
Samir
  • 6,405
  • 5
  • 39
  • 42
1

In android 4 option to do this

  • In android you can send data through Intent or Intent followed by Bundle.Like Intent i = new Intent(current_class.this, linked_class.class); i.putextra("Key", value);

And get the value(suppose string value) in another class like:

 String value = getIntent.getExtra("String key which you used when send value");
  • option 2

    class A{

    public static String _utfValue = "";

    void sendValue(){ _utfValue = "some value"; } }

And fetch this value in your java class like:

String value = A._utfValue ;
  • You can use SharedPreference to save the value and get it from other class.
  • You can use a static method with some return value and fetch the method in your java class through class name.
vishal jangid
  • 2,967
  • 16
  • 22
1

I am sharing the code as suggested by @Shadman Akhtar and reply by @Singee which worked . As soon as the button is clicked the Textview value is set with the value you want to send to MainActivity from retrivedata.java .I haved used Button to simulate the Asynchronous methods which can be inside retrivedata.java

MainActivity.java

package com.example.interfacetesting;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements MyCustomInterface {
    TextView tv1;
    Button btn1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv1=(TextView)findViewById(R.id.tv1);
        btn1=(Button)findViewById(R.id.btn1);
        btn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                retrivedata rd=new retrivedata(MainActivity.this);
                rd.recievedataa();
            }
        });

    }

    @Override
    public void sendData(String str){

        Handler handler = new Handler(Looper.getMainLooper());
        handler.post(new Runnable() {
            @Override
            public void run() {
                tv1.setText(str);
            }
        });
    }
}

MyCustomInterface.java //this is interface

package com.example.interfacetesting;

public interface MyCustomInterface{
    public void sendData(String str);
}

retrivedata.java //class from which data will be sent to MainActivity.

package com.example.interfacetesting;
public class retrivedata{

    private MyCustomInterface otherNameInterface;
    retrivedata(MyCustomInterface otherNameInterface){
        this.otherNameInterface = otherNameInterface;
    }
   void recievedataa()
   {
       otherNameInterface.sendData("---any string you want to send to mainactivity-------");
   }
}
MDNSRF
  • 31
  • 3
0

Maybe you could use a Handler, load it with some data, and then read those data from your activity. Check more infos here about handlers

You'd just pass an handler from your activity to your class, use handler.sendMessage("") inside your run method, and analyse what you receive inside your activity.

Jorel Amthor
  • 1,264
  • 13
  • 38
0

In your case I would use activity as interface. The interface is stored as a static parameter inside Application class.

Vyacheslav
  • 26,359
  • 19
  • 112
  • 194
0

there are many ways you can achieve this following are some

  1. you can use interfaces as explained in one of the answers
  2. you can create a IntentServce instead of your class and use Result Receiver to communicate the data.
  3. you can use handlers and messages as well
  4. you can also create a service and use IBinders (Bound Service)

you can Google out more about these methods and chose what suits you better

Avinash Joshi
  • 1,307
  • 8
  • 25