How to use two threads in one function? - java

here I have a function of checkupdate() in which my application check updates available for users, so i need to display two progressdialog one when server is under request(Checking process) and other when synchronization process is ongoing and both the process is done on the load of application.
Now problem is I'm unable to display these two progressdialog boxes, here only the first thread checking updates is running and application is terminated.
Waiting for your valuable answers.
public void CheckUpdate()
{
//----------------Process of checking the updates--------------------------
try
{
progressDialog = ProgressDialog.show(this, "Wait", "Checking update...", false, true);
Thread thr1 = new Thread()
{
public void run()
{
int Flag = call.CheckUserUpdate(UsrId);
Update = Flag;
progressDialog.dismiss();
//stop();
interrupt();
}
};
thr1.start();
}
catch(final Exception e)
{
}
//---------------Process of Synchronization----------------------------------------------
try
{
progressDialog1 = ProgressDialog.show(this, "Wait", "Synchronizing...", false, true);
Thread thr2 = new Thread()
{
public void run()
{
if(Update == 1)
{
SyncData();
final int UpdateFlag = 1;
call.UpdateUserUpdate(UsrId, UpdateFlag);
progressDialog1.dismiss();
}
else
{
progressDialog1.dismiss();
}
progressDialog1.dismiss();
}
};
thr2.start();
}
catch(final Exception e)
{
}
}

Starting the new threads causes them to start executing elsewhere. Your program here starts two threads, gets to the end of main() and exits, causing the JVM/OS to kill your newly started threads that never really got a chance to run very far.
You need to add an idle loop (or similar) that yields control on the main thread while the worker threads to their thing, assuming you don't have any work happening on the main thread.

Do I understand correctly what you want?
Your UI activitiy has two progressbars which should be updated based on either
update check process
synchronization process
then you should create a handler in your UI activity and use two separate threads one for update check and the other for synchronization check
Both send their progress info to the main thread like:
mHandler.obtainMessage(Main_screen.MESSAGE_PGROGRESS_CHANGE_UPDATE, state, -1)
.sendToTarget();
in the other you have
mHandler.obtainMessage(Main_screen.MESSAGE_PGROGRESS_CHANGE_SYNCHRINIZATION, state, -1)
.sendToTarget();
In your UI activity you have the handler looking like this...
private final Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
if (DEBUG)
Log.i(this.getClass().getSimpleName(),
"-> "
+ Thread.currentThread().getStackTrace()[2]
.getMethodName());
switch (msg.what) {
case MESSAGE_PGROGRESS_CHANGE_UPDATE:
if (DEBUG)
Log.i(this.getClass().getSimpleName(),
" MESSAGE_PGROGRESS_CHANGE_UPDATE: " + msg.arg1);
// do your update of progressbar or whatever here
break;
case MESSAGE_PGROGRESS_CHANGE_SYNCHRINIZATION:
if (DEBUG)
Log.i(this.getClass().getSimpleName(),
" MESSAGE_PGROGRESS_CHANGE_SYNCHRINIZATION: " + msg.arg1);
// do your update of progressbar or whatever here
break;

Related

How can i keep the job service running when the app is closed from recent task list by user

I am using Job Scheduler API in my app to schedule a job for me after specific time interval. It runs fine when the app is running. But whenever the user closes the app or clears it from the recent task list the app stops and the scheduled job never executes afterwards until you open the app and it is rescheduled again from the time it is opened.
Now i want someone to help me to keep the jobs on executing even if the app is closed or cleared from the recent task list.
If there is any alternative solution please tell me.
i am looking for the solution from the past 3 days. Tried everything said by developers on StackOverFlow and other sites and none of them worked for me.
This is where is schedule the job!
ComponentName componentName = new
ComponentName(getActivity().getBaseContext(),WallpaperJobService.class);
JobInfo jobInfo = new JobInfo.Builder(777,componentName)
.setRequiresCharging(sharedPreferences.getBoolean("Charging",false))
.setRequiredNetworkType(sharedPreferences.getBoolean("Wifi",false) ?
JobInfo.NETWORK_TYPE_UNMETERED : JobInfo.NETWORK_TYPE_ANY)
.setPeriodic(sharedPreferences.getInt("Duration",15) * 60 *
1000)
.setPersisted(true)
.build();
JobScheduler scheduler = (JobScheduler)
getContext().getSystemService(Context.JOB_SCHEDULER_SERVICE);
scheduler.schedule(jobInfo);
My Job Service Class:
public class WallpaperJobService extends JobService {
private boolean jobCancelled;
private SharedPreferences sharedPreferences;
private SharedPreferences.Editor editor;
#Override
public boolean onStartJob(JobParameters params) {
Log.i("WallpaperJobService", "Job started!");
changeWallpaper(params);
return true;
}
private void changeWallpaper(final JobParameters params) {
final ArrayList<Image> images = (ArrayList<Image>)
MainActivity.favoritesRoomDatabase.roomDao().getAllFavoriteWallpapers();
sharedPreferences = getSharedPreferences("GridSize", MODE_PRIVATE);
editor = sharedPreferences.edit();
if (images != null && images.size() != 0) {
if (sharedPreferences.getInt("Index", 0) == images.size()) {
editor.putInt("Index", 0);
editor.commit();
}
Picasso.get().load(Constants.domain +
images.get(sharedPreferences.getInt("Index", 0)).getImage_url()).into(new
Target() {
#Override
public void onBitmapLoaded(final Bitmap bitmap,
Picasso.LoadedFrom from) {
new Thread(new Runnable() {
#Override
public void run() {
if (jobCancelled) {
Log.i("WallpaperJobService","Returned");
return;
}
try {
//Doing some work here
} catch (IOException e) {
e.printStackTrace();
}
Log.i("WallpaperJobService", "Job finished!");
jobFinished(params, false);
}
}).start();
}
#Override
public void onBitmapFailed(Exception e, Drawable errorDrawable)
{
Log.i("WallpaperJobService", "Bitmap load failed " +
e.getMessage());
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
});
} else {
Log.i("WallpaperJobService", "Favorite database is null!");
}
}
#Override
public boolean onStopJob(JobParameters params) {
Log.i("WallpaperJobService", "Job cancelled before completion!");
jobCancelled = true;
return true;
}
}
When doing stuff periodically in the background — JobScheduler, WorkManager, AlarmManager, FCM push messages, etc. — you have to take into account that your process might not be around when it is time for you to do your work. Android will fork a process for you, but it is "starting from scratch". Anything that your UI might have set up in memory, such as a database, would have been for some prior process and might not be set up in the new process.

Updating Notification Continuously

Hello There I am a newbie for Android Development, working to learn it to my own!
I just want to update my notification in a Java Thread in my application (I am just learning and curious about how can I do it).
I have an activity, a simple thread to increment an Integer value. Then, I just want to show it in my Notification whenever the Integer value increments!
My Code is as:
public class MainActivity extends Activity{
private final String LOG_KEY = this.getClass().getSimpleName();
private int c = 0;
private boolean flag = true;
private NotificationCompat.Builder builder;
private NotificationManager notificationManager;
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
builder = new NotificationCompat.Builder(MainActivity.this)
.setSmallIcon(R.mipmap.ic_launcher)
.setAutoCancel(false);
builder.setOngoing(true);
notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
Thread t = new Thread(new MyThread());
t.start();
}//OnCreate ends
#Override
protected void onStop() {
super.onStop();
flag = false;
}//stop ends
#Override
protected void onDestroy() {
super.onDestroy();
flag = false;
}//destroy ends
private class MyThread implements Runnable {
#Override
public void run() {
while (flag) {
c+=1;
showNotification(Integer.toString(c) + " Counts");
}//while ends
}//run ends
private void showNotification(String msg) {
try {
//set the notification
builder.setContentText(msg);
notificationManager.notify(0, builder.build());
} catch (Exception exp) {
Log.e("xmn", exp.toString());
}//try catch ends
}//showNotification ends
}//private class ends
}//MainActivity class ends here
As from my code, the notification appears and updates the value! But the problem is that it freezes the device and application at a sudden!
I just want help for what I am doing wrong as I am a newbie and learning it to my own. Any help and idea will be highly appreciated!
Thanks
You shouldn't be creating a notification and then continuously updating it as fast as you can from a thread. It's really not designed for that.
The closest thing I can think of that would meet your use case is using a notification to display progress. See this link:
Displaying Progress in a Notification
You might want to put some kind a rate limiter in your thread, unless you want your count to reach very high numbers very quickly. Perhaps make the thread sleep for a second between updates.
The problem is that you produce too much notifications more then a device can consume.
For your goal (just learn) you can add a some pause between notifications like that:
private void showNotification(String msg) {
try {
//set the notification
Thread.sleep(1000); //set the pause
builder.setContentText(msg);
notificationManager.notify(0, builder.build());
} catch (Exception exp) {
Log.e("xmn", exp.toString());
}//try catch ends
}//showNotification ends

Cant get ProgressDialog to show up in android

I cant get a progress dialog to show when I need it to. I have tried putting it in my asyncTask the ui class and the its own thread that runs on the ui and none have worked. Can anyone help me?
the method where the progressDialog method is called:
public void shareTest(View view){ //method called to jump to share activity if criteria matched
if(checkInputs()) { //call to check inputs
Share start = new Share();
boolean isConnected=start.connectToServer(); //connectToServer
Intent intent = new Intent(HomeScreen.this, Share.class); //create intent to move to share class from this activity
startProgressDialog();
if (isConnected) { //check to see if isconnected was succesful
if (Share.matchFound ){ //check to see if a match was found
progress.dismiss();
startActivity(intent); //if true jump to share activity
} else {
while (!Share.timedOut) { //While the time has not timedOut
if (Share.matchFound) { //if a share has been found
startActivity(intent); //start share activity
break; //if true then break
}
}
if (Share.timedOut) {
//send an notice that a match wasn't found
sendToast(getString(R.string.noShare)); //if not true then send Toast
}
}
}
else sendToast(getString(R.string.errServCon)); //if connection to server failed then send toast
}
}
this is the method:
void startProgressDialog() {
new Thread(new Runnable() {
#Override
public void run() { //creates a new runnable thread
// Issue command() on a separate thread
while (!Share.matchFound) { //while havent been asked to disconnect //if a new location has been recieved
activity.runOnUiThread(new Runnable() {
#Override
public void run() { //run on the ui thread act
progress.show(); //call the method that does the update
}
});
}
progress.dismiss();
}
}).start();
}
Declare a global variable like this:
ProgressDialog progress;
Wherever you want to show the progress, paste this code:
progress = ProgressDialog.show(this, "Please wait",
"Loading..", true);
When you are done, simply dismiss it:
progress.dismiss();

Stopping Executor service when user presses Back or Home button

I am trying to ensure that the executor service stops when the Back button or Home button is pressed.
Currently I have this code in my onCreate function in the main activity class:
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
final Wifi wifiObject = new Wifi((WifiManager) getSystemService(Context.WIFI_SERVICE));
Runnable periodicTask = new Runnable() {
public void run() {
// For each AP in the database, we will fill the AP's ArrayList with their corresponding RSS values
for (Map.Entry<String, String> entry : AccessPoints.entrySet()) {
int APNoToBeSent = 0;
try {
wifiObject.scanWifi(entry.getKey(), accessPointMeanRSSArrayList, accessPointRSSFrequencyArrayList);
}
catch (Exception e) {
}
++APNoToBeSent;
}
System.out.println("Mean AP0 = " + accessPointMeanRSSArrayList.get(0));
System.out.println("Frqcy AP0 = " + accessPointRSSFrequencyArrayList.get(0));
}
};
executor.scheduleAtFixedRate(periodicTask, 0, 2, TimeUnit.SECONDS);
I've been doing some reading on this but am unsure whether this should be happening in onStop() or onPause() or something completely different?

Listing of the Network Devices in Android

Similar or the same Question has been answered here
I am creating an Android App, which sends a broadcast message to the network and prepares a list of devices responding back.
Now What I did:
I created an Activity Class DeviceManagerWindow.java which calls a thread Sender.java.
Sender.java is responsible for sending the broadcast message.
Then the DeviceManagerWindow.java calls another thread which is responsible for listening to the devices responding back. The devices responding back will be listed in the Activity as soon as the device responds back. For that I have a TableLayout named deviceList.
What code I have written:
DeviceManagerWindow.java This method is called when a button for search is pressed
public void searchDevice(View v) throws IOException, InterruptedException
{
//Log.v("TableLayout:",view.toString());
sendMulticastFlyport = new Thread(new FlyportSender(MAC));
sendMulticastFlyport.start();
new Thread()
{
public void run()
{
MulticastSocket socketComputer=null;
try
{
socketComputer = new MulticastSocket(WifiConstants.COMPUTER_RECV_PORT);
socketComputer.joinGroup(InetAddress.getByName(WifiConstants.COMPUTER_NETWORK_ADDR));
socketComputer.setSoTimeout(1*60*1000);
byte[] inBufComputer = new byte[1024];
DatagramPacket inPacketComputer = new DatagramPacket(inBufComputer, inBufComputer.length);
while(true)
{
System.out.println("Listening...");
socketComputer.receive(inPacketComputer);
System.out.println("Received");
String msg = new String(inBufComputer, 0, inPacketComputer.getLength());
DeviceInformation device = new DeviceInformation(1, msg, inPacketComputer.getAddress().toString());
addDevice(device, false, 1);
Log.v("Received:","Received Computer From :" + inPacketComputer.getAddress() + " Msg : " + msg);
//System.out.write(inPacket.getData(),0,inPacket.getLength());
System.out.println();
Thread.sleep(2000);
}
}
catch(Exception e)
{
Log.v("Exception:","During Receiving Computer: "+e.toString());
try
{
addDevice(null, true, 1);
}
catch (IOException e1)
{
Log.v("Exception:", "Computer End Error: " +e1);
}
}
finally
{
socketComputer.close();
}
}
}.start();
The following code creates a list:
public void addDevice(DeviceInformation device, boolean bool, int type) throws IOException
{
TableLayout tb = (TableLayout) findViewById(R.id.DeviceList);
Log.v("addDevice","Called");
if(bool)
{
LayoutParams layout = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
TableRow tr = new TableRow(getApplicationContext());
TextView tv = new TextView(getApplicationContext());
System.out.println(tb);
tv.setLayoutParams(layout);
tr.setLayoutParams(layout);
String message;
Log.v("addDevice","Device Timeout");
switch(type)
{
case 1:
computerEnd=true;
break;
case 2:
raspberryEnd=true;
break;
case 3:
flyportEnd=true;
break;
}
if(computerEnd && raspberryEnd && flyportEnd)
{
if(rowCounter>0)
{
message = "No More Devices";
}
else
{
message = "No Devices Found";
}
tv.setText(message);
tv.setTextColor(Color.WHITE);
if(rowCounter%2==0)
{
tr.setBackgroundColor(Color.DKGRAY);
}
else
{
tr.setBackgroundColor(Color.GRAY);
}
tv.setVisibility(1);
tr.addView(tv);
tb.addView(tr);
}
}
else
{
LayoutParams layout = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
TableRow tr = new TableRow(getApplicationContext());
TextView tv = new TextView(getApplicationContext());
tv.setLayoutParams(layout);
tr.setLayoutParams(layout);
Log.v("addDevice","Received");
String textToDisplay = device.getDeviceTypeString()+"\n"+device.getIPAddress(); //Write the text to display
tv.setText(textToDisplay);
tv.setTextColor(Color.WHITE);
Drawable img;
if(device.getDeviceType()==1)
{
img = getApplicationContext().getResources().getDrawable(R.drawable.pc);
}
else if(device.getDeviceType()==2)
{
img = getApplicationContext().getResources().getDrawable(R.drawable.raspberry);
}
else
{
img = getApplicationContext().getResources().getDrawable(R.drawable.flyport);
}
img.setBounds(0,0,70,45);
tv.setCompoundDrawables(null, null, img, null);
tv.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
}
});
if(rowCounter%2==0)
{
tr.setBackgroundColor(Color.DKGRAY);
}
else
{
tr.setBackgroundColor(Color.GRAY);
}
rowCounter++;
Log.v("Result","Device Added");
}
}
Now it is showing me an error in the logCat as:
05-11 22:01:10.165: E/AndroidRuntime(13873): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
What I have figured out from this is only the UIThread is allowed to access the Views that is created.
Previously I had tried:
new Thread()
{
public void run()
{
runOnUiThread(){
MulticastSocket socketComputer=null;
try
{
....
....
....
}
}
And that time I received an error:
Main thread cannot access Network
Before that I had tried to use synchronized methods which was called from the Receiving.java Thread File. but It also gave an error of not creating the list.
I have tried all possible ways.
Now what whould I do.?
You figured it out right. Now you can learn to either use a Handler to pass information to the UI thread (see http://www.techotopia.com/index.php/A_Basic_Overview_of_Android_Threads_and_Thread_handlers) or AsyncTask (see http://developer.android.com/reference/android/os/AsyncTask.html).
I personally prefer AsyncTask. You can paste the code which performs the search into the doInBackground() method (not need to use a separate thread, doInBackground() already does that for you) and paste the UI-related code (the list creation code) into the onPostExecute() method. Search for further examples of AsyncTask if it is not sufficiently clear how it works from the link.
EDIT: If you intend your device search code to run indefinitely, then you have to resort to Handler, as AsyncTask expects the doInBackground() method to finish before running onPostExecute(). See which option better suits your needs.

Categories

Resources