My MainActivity has a Thread that generates RSA keys and returns the amount of time in milliseconds that it took to generate them.
While I run this Thread, the app goes to a second Activity.
I need the second Activity to receive that time in milliseconds.
As I understand, once you call startActivity(), the parent Activity goes to sleep. So how can I run both simultaneously?
Thanks!
You can use LocalBroadcastReceiver.
public class SecondActivity extends AppCompatActivity {
private BroadcastReceiver mRsaReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
ArrayList<String> rsaList = intent.getStringArrayListExtra("rsaList");
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity);
LocalBroadcastManager.getInstance(this).registerReceiver(mRsaReceiver, new IntentFilter("RSA"));
}
#Override
protected void onDestroy() {
super.onDestroy();
LocalBroadcastManager.getInstance(this).unregisterReceiver(mRsaReceiver);
}
}
From Your rsa thread
Intent rsaIntent = new Intent("RSA");
rsaIntent.putExtra("rsaList", rsaArrayList);
LocalBroadcastManager.getInstance(context).sendBroadcast(rsaIntent);
As I understand, once you startActivity(), the parent activity goes to sleep. So how can I run both simultaneously
You do not. And you do not need to. Since you generate your RSA keys on a separate thread that code should be fully independent from your activities (aside from being started in MainActivity). So all you need to know is when your background task finished - and for that you can use either in-app broadcasts or use Event Bus like GreenRobot's EventBus library or use RxJava.
Related
I am trying to implement beacon functionality in my Android application.
Unfortunately there are a few strange behaviours I couldn't solve yet.
I am using the Android Beacon Library in Version 2.15 and Android 6.0.1.
I have an Activity
class MainActivity extends AppCompatActivity implements BeaconConsumer
where I want to search for nearby beacons. I initialize the BeaconManager like
private BeaconManager m_beaconManager;
[...]
m_beaconManager = BeaconManager.getInstanceForApplication(this);
m_beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout(BeaconParser.EDDYSTONE_URL_LAYOUT));
m_beaconManager.bind(this);
in the onCreate() method.
The way I search for beacons
#Override
public void onBeaconServiceConnect() {
m_beaconManager.addRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> collection, Region region) {
// do something
}
});
try {
m_beaconManager.startRangingBeaconsInRegion(m_region);
} catch(RemoteException e) {
e.printStackTrace();
}
}
works perfectly fine.
In my application I want to display these beacons in a list and if I click onto one of them I want to start a new activity with more informations about the beacon (MAC address, distance etc.).
My current approach is to unbind my BeaconManager in the onPause() method and create a whole new BeaconManager in my new Activity. This also works flawless.
But a soon as I finish() my second activity it does not stop searching for beacons. I also unbind my BeaconManager like so
#Override
public void onPause() {
super.onPause();
m_beaconManager.unbind(this);
}
#Override
public void onDestroy() {
super.onDestroy();
m_beaconManager.unbind(this);
}
#Override
public void onStop() {
super.onStop();
m_beaconManager.unbind(this);
}
but back in my MainActivity I get 2 searches for beacons. One from my MainActivity and the other one from my already finished second activity.
Furthermore if I click on another item of my list which means I create my second activity again, it looks for the beacon from the first start and the new one. Each new click on the list adds a new search to the existing ones.
I already searched for known Bugs but there is nothing similar.
What am I doing wrong?
In order to prevent duplicate callbacks, in addition to unbinding, you should call (a) stopRangingBeaconsInRegion(...) and (b) removeRangeNotifier(...). To remove the notifier you will need to keep a reference to your callback class.
I've made an app that is receiving some data from a TCP Client to my TCP Server that store the data in SQlite DB, and actually i've made a recyclerView where to visualize all that data but now my issue is what i'm trying like 2 weeks to refresh the recyclerView in real Time, i mean if a TCP Client will send a new package to my TCP Server and if i'm in the activity with the recyclerView the data have to be added dynamically.
I will also accept any type of tips and suggestions on how to improve my app.
Actually it's my 1st app i've ever created in Android.
HERE you can find my Server(TCPServer),RecyclerViewAdapter,Adapter(constructor),allert.java(class where i invoke the RecyclerViewAdapter.
Hope someone will be able to help me and ill be very grateful.
Try sending broadcast method. Here are the steps :
Make a inner class that extends BroadcastReceiver in your activity.
private class ExampleBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//do stuffs here, e.g. getting extras from intent
}
Declare a instance of the class outside any methods.
public class MainActivity extends AppCompatActivity {
private ExampleBroadcastReceiver exampleBroadcastReceiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
//stuffs
}
}
Override onResume method. Initialize the instance you just made in this method. Then, register it with a intent-filter. This will make sure that your broadcast receiver ready when user open the activity.
#Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter();
filter.addAction("com.example.MainActivity");
exampleBroadcastReceiver = new ExampleBroadcastReceiver();
LocalBroadcastManager.getInstance(this).registerReceiver(exampleBroadcastReceiver, filter);
}
Override onPause method and unregister your receiver.
#Override
protected void onPause() {
super.onPause();
try {
LocalBroadcastManager.getInstance(this).unregisterReceiver(exampleBroadcastReceiver);
} catch (IllegalArgumentException e) {
if (!e.getMessage().contains("Receiver not registered")) {
// unexpected, re-throw
throw e;
}
Make sure you use ArrayList for dynamic data.
Whenever you receive data from server, after you store them in your database, send a broadcast with extras contains data you want to display in your activity.
EDITED
I registered the receiver using an instance of LocalBroadcastManager.
I have a GCMListenerService that will be used for push notifications from my server to my client. I need this listener to interrupt a thread that is running in the Presenter (my project is structured using the MVP pattern). However, I do not know how to pass a result receiver to the Service because I don't think I can overrride onStartCommand(). The other option would be a LocalBroadCast Manager, but I'd like the message to go through even when the activity is paused, so I don't think a local broadcast manager would work.
create abstract BroadcastReceiver as follows :
public abstract class DataReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
onDataRefresh(intent);
}
protected abstract void onDataRefresh(Intent intent);
}
and use it in the activity as follow:
class Acb extends Activity{
onCreate(){
DataReceiver data = new DataReceiver(
#Override
protected void onMenuItemUpdate(Intent intent) {
});
}
}
whatever the data you passed using sendBroadcast(intent); ,that data you can access here .
Right now I have a Timer starting an AsyncTask in a Fragments onCreate method (with a timer interval of 1 minute). So that is not a good idea I believe because if there is a configuration change the fragment will call the onCreate method again and I will have 2 running Timer AsyncTasks right?
So I need some way to put the AsyncTask where it's only started once during the whole lifecycle of the app.
no need of Asynctask for simple timer, try this -
class MyFragment extends Fragment{
private int currentTime;
private void startTimer(){
new Handler().
postDelayed(new Runnable(){
#Override
public void run()
{
onTick();
startTimer();
}
},1000*60);
}
private void onTick()
{
currentTime++;
}
#Override
public void onSaveInstanceState(Bundle outState)
{
outState.putInt("currentTime", currentTime);
super.onSaveInstanceState(outState);
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if (savedInstanceState != null)
{
currentTime=savedInstanceState.getInt("currentTime",0);
startTimer();
}
}
You could use a Countdown Timer and cancel it in onDestroy(). That would guarantee that you only have a single one running at any time.
As for starting it exactly only once you will have to persist that knowledge somewhere depending on your needs. Maybe storing a boolean in onSaveInstanceState and reading it in onCreate() would do the trick?
And, as #marcin_j has pointed out, AsyncTasks are executed in sequence (unless specifically started differently), so using one will block every other Async task in your app (like downloading stuff etc).
if there is a configuration change the activity gets destroyed and re-created so no you will not have 2 timers running
I have an Activity , that initiates an IntentService to get some work done . When the work is done , the IntentService broadcast's and announces success.
The broadcast receiver is inside the same activity that initiates the IntentService.
The psuedo of this situation
Activity A
{
private BroadcastReceiver receiver = new BroadcastReceiver()
{
#override
public void onReceive(Context context, Intent intent)
{
//handle
}
}
protected void onCreate(Bundle savedInstanceState)
{
//initiate IntentService
}
}
IntentService
{
//Launch spaceshuttle . and broadcast success
}
Now what happens is that sometimes the launching the spaceshuttle takes some times , and the cellphone goes to sleep. As a result of which the broadcast receiver i believe needs to acquire a partial lock perhaps as far as I understand .
But the exact technique to do so has been evading me .
Please help .
The simplest solutions are either for you to:
Use my WakefulIntentService, or
Use the WakefulBroadcastReceiver from the Android Support package
Both will manage the WakeLock for you. My WakefulIntentService is probably a more natural fit for the code as you have shown it, but both should work.