UI-Thread getting blocked when Thread.sleep() called in another thread - java

I am trying to read a text file from SD-Card in a Runnable called PcmDataReader and updating a TextView statusTextView , accordingly in the UI-Thread.
I am using a handler to pass the messages from PcmDataReader to the UI-Thread.
In order to be able to observe the change of statusTextView I have put a Thread.sleep(5000) in PcmDataReader.
The issue is that the UI-Thread is blocked until the file i/o & the sleep are finished & the final update i.e. "File Reading Complete.." is only shown on statusTextview.
What am I missing here ? Following is my code:
MainActivity.java:
package com.example.pcmreader;
import android.Manifest;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import android.widget.Button;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private TextView statusTextView ;
priavte Button updateButton;
private PcmDataReader pcmData = new PcmDataReader();
private static Handler handler;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
handler = new Handler()
{
#Override
public void handleMessage (Message message)
{
String msg = (String) message.obj;
if (statusTextView != null)
statusTextView.setText(msg);
}
};
setContentView(R.layout.main);
statusTextView= (TextView) findViewById(R.id.statusTextView);
ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.READ_EXTERNAL_STORAGE }, 100);
updateButton.setOnClickListener(this);
}
#Override
public void onClick(View view)
{
statusTextView.setText("Initiating Read .. ");
pcmData.run();
}
public static Handler getHandler ()
{
return handler;
}
}
PcmDataReader.java:
package com.example.pcmreader;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.util.Log;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class PcmDataReader implements Runnable
{
private int [] samples = new int[6000];
private int i;
private boolean completedReading;
private File sdcard = Environment.getExternalStorageDirectory();
private File file = new File(sdcard,"rishav_log.txt");
#Override
public void run()
{
i=0;
completedReading = false;
try
{
BufferedReader br = new BufferedReader(new FileReader(file));
String line;
Handler uiHandler= MainActivity.getHandler();
Message msg = uiHandler.obtainMessage();
msg.obj="File openned, Reading data..";
uiHandler.sendMessage(msg);
while ((line = br.readLine()) != null)
samples[i++]=Integer.parseInt(line);
Thread.sleep(5000); //dummy sleep to observe the update of textView in UI thead
br.close();
completedReading = true;
msg = uiHandler.obtainMessage();
msg.obj="File Reading Complete..";
uiHandler.sendMessage(msg);
}
catch (IOException e)
{
Log.i("file read",e.getMessage());
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}

Calling runnable should be in separate thread.
Replace
pcmData.run();
to
Thread t1 =new Thread(pcmData);
t1.start();

The UI thread freezes because you call the Thread.sleep() in the same thread:
#Override
public void onClick(View view) {
statusTextView.setText("Initiating Read .. ");
pcmData.run(); // PcmDataReader.run() will happen in the UI thread
}
The fix is relatively easy:
#Override
public void onClick(View view) {
statusTextView.setText("Initiating Read .. ");
ExecutorService executor = Executors.newSingleThreadExecutor(); // this can come from somplace else.
// Actually, it better comes from someplac else.
executor.submit(pcmData); // this is how to run in in a background thread.
// executor.shutdown(); // this is necessary only if you create the executor in the same method.
// Otherwise, creating and killing background threads is a matter of your apps strategy.
}

Related

why android client new socket command is not working

I wrote simple android java client , main activity with socketTask and and a handler in mainactivity. and it doesn't working .
I used debuger and found that the problem is in this line :
this.socket = new Socket(IP_ADDRESS, PORT);
I also had this error massage in the studio :
An unexpected packet was received before the handshake
the server is ok and responding to any other program .
Can some one advice what is the problem . I attaching mainactivity and socket task .
thanks a lot .
main activity
package com.example.app24;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import org.json.JSONObject;
public class MainActivity extends AppCompatActivity implements View.OnClickListener
{
Button btnSend ;
TextView tvFromServer;
EditText etToSend;
String strToSend,strFromServer;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnSend = (Button) findViewById(R.id.btnSend);
btnSend.setOnClickListener(this);
etToSend = (EditText) findViewById(R.id.etToSend);
tvFromServer = (TextView) findViewById(R.id.tvFromServer);
tvFromServer = (TextView) findViewById(R.id.tvFromServer);
}
#Override
public void onClick(View v)
{
if (v == btnSend)
{
strToSend = etToSend.getText().toString();
new Thread(new Runnable() {
#Override
public void run() {
SocketTask send1 = new SocketTask(strToSend);
strFromServer=send1.sendReceive();
runOnUiThread(new Runnable() {
public void run() {
tvFromServer.setText(strFromServer);
}
});
}
}).start();
}
}
}
'''
SocketTask.
```
package com.example.newproj;
import android.os.AsyncTask;
import android.os.Build;
import android.util.Log;
import androidx.annotation.RequiresApi;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
public class SocketTask
{
//private final static String IP_ADDRESS = "172.19.16.179";
private final static String IP_ADDRESS = "192.168.1.124";
private final static int PORT = 8821; // HTTP port
private final static int PACKET_SIZE = 1024; // standard 1kb packet size
private Socket socket;
private String sendingStr="";
private String receivingStr="";
BufferedReader reader;
public SocketTask(String str1)
{
this.sendingStr = str1;
}
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
private void send()
{
try {
OutputStreamWriter writer = new OutputStreamWriter(this.socket.getOutputStream(), StandardCharsets.UTF_8); // outputStreamWriter creating
writer.write(this.sendingStr);
writer.flush();
Log.d("Result", "sent");
}
catch (Exception e) {
Log.e("Exception", e.toString());
}
}
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
private void receive() {
try {
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
char[] charBuffer = new char[1024];
StringBuilder stringBuilder = new StringBuilder();
reader.read(charBuffer);
stringBuilder.append(charBuffer);
reader.close();
receivingStr = stringBuilder.toString();
}
catch (IOException e)
{
Log.e("Exception", e.toString());
}
}
public String sendReceive()
{
try {
this.socket = new Socket(IP_ADDRESS, PORT);
send();
receive();
this.socket.close();
} catch (Exception e) {
Log.e("Exception", e.toString());
}
return this.receivingStr;
}
}
```

Handler does not delay - Android Studio Java

I am working on a project. My program shows a video by videoview and get values from an excel file. I am having difficulty in showing the values one by one. I am trying to use some delay methods. I have used Thread.sleep and SystemClock.sleep methods but they freeze the entire app and phone. Now I am trying to use handler method. I don't receive any error but there is no delay. I am putting my code below.
If anyone can help me with this delay, I will be very happy.
package com.example.exceldeneme;
import androidx.appcompat.app.AppCompatActivity;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.widget.MediaController;
import android.widget.VideoView;
import android.os.SystemClock;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.lang.String;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.List;
public class MainActivity<number_cars> extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
VideoView videoView = findViewById(R.id.video_view);
Button button = findViewById(R.id.button);
TextView text_cars = findViewById(R.id.textEmpty);
TextView text_total_lots = findViewById(R.id.textTotalLots);
readData();
int number_of_park = 100;
text_total_lots.setText(String.valueOf(number_of_park));
int counter = 0;
String videoPath = "android.resource://" + getPackageName() + "/" + R.raw.camera_out;
Uri uri = Uri.parse(videoPath);
videoView.setVideoURI(uri);
MediaController mediaController = new MediaController(this);
videoView.setMediaController(mediaController);
mediaController.setAnchorView(videoView);
for (String i : number_of_cars.get(0)){
counter = counter + 1 ;
}
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
int counter = 0;
for (String i : number_of_cars.get(0)){
counter = counter + 1 ;
}
for (int i = 1; i < counter-1;i= i +1){
String count_park = number_of_cars.get(0)[i];
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
#Override
public void run() {
text_cars.setText(count_park);
}
}, 1000);
//SystemClock.sleep(1000); //ms
Log.d("Selam","SORUN YOK");
}
}
});
}
private ArrayList<String[]> number_of_cars = new ArrayList<String[]>();
private void readData() {
InputStream is = getResources().openRawResource(R.raw.numberofcars);
BufferedReader reader = new BufferedReader(
new InputStreamReader(is, Charset.forName("UTF-8"))
);
String line = "";
try {
while(((line = reader.readLine()) != null)) {
String[] tokens = line.split(",");
number_of_cars.add(tokens);
Log.d("MyActivity","Just created"+ Arrays.toString(tokens));
}
}
catch (IOException e) {
Log.wtf("MyActivity","Error reading data file on line" + line, e);
e.printStackTrace();
}
}
}
for the isolated issue you probably want :
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
#Override
public void run() {
text_cars.setText(count_park);
}
}, 1000 * i);
But you should really have a single instance Handler and post all Runnable objects to it, with a way to remove all pending Runnable, if any when ui is destroyed using : Handler::removeCallbacksAnMessages(null) in the relevant hook method like onDestroy.

Why is my service getting destroyed while mediaplayers are looping?

In my App's MainActivity I am playing some sounds using MediaPlayers and in The onPause() in that activity I realease the players and I am starting a service to continue playing these sounds by creating them again and I send the resourcesNames and the Volume of every player from the activity to the service , I am using setLooping() to make these sounds loop and I am running the service in a new thread (outside the main thread) uding Handler and HandlerThread.
when the activity gets paused the service starts and the sounds are playing but the problem is that they just loop for 3 times and then the service is getting destroyed without stopService() or stopSelf() are being called and also without exiting from the app(the app still in the recent apps)?
Here the sevice's code :
package com.example.naturesounds;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.Process;
import android.util.Log;
import androidx.annotation.NonNull;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
public class SoundSPlayingService extends Service implements MediaPlayer.OnPreparedListener
{
private static final String PACKAGE_NAME = "com.example.naturesounds";
private float playerVolume = 0.0f;
serviceHandler serviceHandler;
Looper serviceLooper;
HandlerThread thread;
Intent intent;
Bundle playersVolume = new Bundle() ;
ArrayList<String> runningResourceNames = new ArrayList<>();
HashMap<String, MediaPlayer> playersMap = new HashMap<>();
#Override
public void onCreate() {
thread = new HandlerThread("ServiceThread", Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
serviceLooper = thread.getLooper();
serviceHandler = new serviceHandler(serviceLooper);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Message message = serviceHandler.obtainMessage();
message.obj = intent;
serviceHandler.sendMessage(message);
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent)
{
return null;
}
#Override
public void onDestroy() {
releasePlayers();
Log.d("serviceLifeCycle","onDestroy() is running");
}
public void createPlayer(String resourceName)
{
playersMap.put(resourceName,new MediaPlayer());
try {
playersMap.get(resourceName).setDataSource(getApplicationContext(),
Uri.parse("android.resource://com.example.naturesounds/raw/" + resourceName));
playersMap.get(resourceName).setOnPreparedListener(this);
playersMap.get(resourceName).prepareAsync();
playersMap.get(resourceName).setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
setPlayerLooping(resourceName);
setPlayerVolume(resourceName);
}
catch (IOException e1)
{
e1.printStackTrace();
}
catch (IllegalArgumentException e2)
{
e2.printStackTrace();
}
}
public void releasePlayers()
{
for(int i=0 ; i<runningResourceNames.size(); i++)
{
String resourceName = runningResourceNames.get(i);
if(playersMap.get(resourceName) != null)
{
playersMap.get(resourceName).release();
playersMap.put(resourceName,null);
}
}
}
public void setPlayerVolume(String resourceName)
{
playerVolume = playersVolume.getFloat(resourceName);
Log.d("playerVolume",String.valueOf(playerVolume));
playersMap.get(resourceName).setVolume(playerVolume,playerVolume);
}
public void setPlayerLooping(String resourceName)
{
playersMap.get(resourceName).setLooping(true);
}
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
class serviceHandler extends Handler
{
public serviceHandler(Looper looper)
{
super(looper);
}
#Override
public void handleMessage(#NonNull Message msg) {
Log.d("serviceHandlerChecking","handleMessage() is executing");
intent = (Intent) msg.obj;
runningResourceNames = intent.getStringArrayListExtra(PACKAGE_NAME + ".MainActivity.runningResourceNames");
playersVolume = intent.getBundleExtra(PACKAGE_NAME + ".MainActivity.playersVolume");
for(int i=0; i<runningResourceNames.size(); i++)
{
String resourceName = runningResourceNames.get(i);
createPlayer(resourceName);
}
}
}
}

Stop App On Incomming Phone Call?

How would I stop music playing so call the OnPause if there is a incoming or outgoing call?
So once there is a call or they make a call it will stop the music by calling OnPause.
package com.beanie.samples.streaming;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import com.beanie.samples.streaming.R;
import com.beanie.samples.streaming.MyService;
import android.app.Activity;
import android.app.IntentService;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.Toast;
;
public class HomeActivity extends Activity implements OnClickListener {
private static final String TAG = "MyServices";
private final static String RADIO_STATION_URL = "http://195.154.237.162:8936/";
private static final String START_STICKY = null;
Button buttonPlay, buttonStopPlay;
/** Called when the activity is first created.
* Keep this here all the application will stop working */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
initializeUIElements();
initializeMediaPlayer();
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
buttonPlay = (Button) findViewById(R.id.buttonPlay);
buttonStopPlay = (Button) findViewById(R.id.buttonStopPlay);
buttonPlay.setOnClickListener(this);
buttonStopPlay.setOnClickListener(this);
}
private ProgressBar playSeekBar;
private MediaPlayer player;
private InputStream recordingStream;
private RecorderThread recorderThread;
private boolean isRecording = false;
private void initializeUIElements() {
playSeekBar = (ProgressBar) findViewById(R.id.progressBar1);
playSeekBar.setMax(100);
playSeekBar.setVisibility(View.INVISIBLE);
buttonPlay = (Button) findViewById(R.id.buttonPlay);
buttonPlay.setOnClickListener(this);
buttonStopPlay = (Button) findViewById(R.id.buttonStopPlay);
buttonStopPlay.setEnabled(false);
buttonStopPlay.setOnClickListener(this);
}
public void getTelephonyOverview(final TelephonyManager telMgr)
{
int callState = telMgr.getCallState();
String callStateString = "NA";
switch (callState) {
case TelephonyManager.CALL_STATE_IDLE:
getLastCallLogEntry(Appinfo.this);
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.i("Call","started");
break;
case TelephonyManager.CALL_STATE_RINGING:
Log.i("Call","ringing");
break;
}
}
public void startPlaying() {
buttonStopPlay.setEnabled(true);
buttonPlay.setEnabled(false);
playSeekBar.setVisibility(View.VISIBLE);
player.prepareAsync();
player.setOnPreparedListener(new OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
player.start();
}
});
}
private void onBufferingUpdate(MediaPlayer mp, int percent) {
playSeekBar.setSecondaryProgress(percent);
Toast.makeText(this, "Buffering ", percent).show();
Log.i("Buffering", "" + percent);
}
public void onClick(View v) {
if (v == buttonPlay) {
onBufferingUpdate(player, 0);
Log.d(TAG, "onClick: starting srvice");
startPlaying();
player.setLooping(false); // Set looping
}
else if (v == buttonStopPlay) {
Log.d(TAG, "onClick: stopping srvice");
stopPlaying();
}
}
private void stopPlaying() {
if (player.isPlaying()) {
player.stop();
player.release();
initializeMediaPlayer();
}
buttonPlay.setEnabled(true);
buttonStopPlay.setEnabled(false);
playSeekBar.setVisibility(View.INVISIBLE);
stopRecording();
}
private void initializeMediaPlayer() {
player = new MediaPlayer();
try {
player.setDataSource(RADIO_STATION_URL);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void startRecording() {
BufferedOutputStream writer = null;
try {
URL url = new URL(RADIO_STATION_URL);
URLConnection connection = url.openConnection();
final String FOLDER_PATH = Environment.getExternalStorageDirectory().getAbsolutePath()
+ File.separator + "Songs";
File folder = new File(FOLDER_PATH);
if (!folder.exists()) {
folder.mkdir();
}
writer = new BufferedOutputStream(new FileOutputStream(new File(FOLDER_PATH
+ File.separator + "sample.mp3")));
recordingStream = connection.getInputStream();
final int BUFFER_SIZE = 100;
byte[] buffer = new byte[BUFFER_SIZE];
while (recordingStream.read(buffer, 0, BUFFER_SIZE) != -1 && isRecording) {
writer.write(buffer, 0, BUFFER_SIZE);
writer.flush();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
recordingStream.close();
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void stopRecording() {
try {
isRecording = false;
if (recordingStream != null) {
recordingStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private class RecorderThread extends Thread {
#Override
public void run() {
isRecording = true;
startRecording();
}
};
}
how would I stop music playing so call the OnPause
onPause() and onStop() are lifecycle methods that will be called automatically; you do not call them manually. You should override them and add your code that would stop the music.
You don't need to do anything in your lifecycle methods to stop the music. Android provides you with a mechanism to handle these cases.
The mechanism is called Audio Focus. Apps request Audio Focus when they want to play audio (or video!). When another app needs audio, it requests the Audio Focus. And the subscribed parties receive a broadcast saying: Hey, you've lost the audio focus. If the focus was only temporarily lost (like when a notification comes and it plays a short audio beep) then the Broadcast says: Hey, you've lost the audio focus but duck the audio, I'll give it back in a moment.
The idea in that case is that you lower (duck) your volume to 0.1 (for example) to let the other sound (beep) be louder.
After the "beep" from the notification is done, the broadcast says: hey, here's the audio focus you had earlier.
At this point if you're still playing, you'd restore the volume to what it was before.
That's the concept behind audio focus. It's perfectly explained in the Android Docs (and the Android Samples) albeit the Google code is rather messy and inconsistent, it does work out of the box. They do a lot of crappy abstraction and some strange code practices but irregardless of that, the code works fine.
The same goes for a phone call, you subscribe to it and tell your service to pause/resume the sound when there's a call in progress. Not when your app goes to the background (onpause) because that's unreliable and doesn't mean at all that you app went to the background.
Here's the Android Official Docs for Audio Focus.

Android - Threads not executing

So yeah, my thread isn't executing, or doing the code within it. I just wanted to run a shell script from my sdcard, and show a "loading" circles or "progress" circle or whatever you want to call it. When I click the button to run the thread, I get the progress/loading bar/circle, but it just sits there and does nothing. I've looked at some examples but still cannot figure out what I did wrong. Here's my code:
package com.cydeon.plasmamodz;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.TimeoutException;
import com.stericson.RootTools.*;
import com.stericson.RootTools.exceptions.RootDeniedException;
import com.stericson.RootTools.execution.CommandCapture;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.res.AssetManager;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class Install extends Activity{
private static ProgressDialog progressDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.install);
Button bInstall = (Button) findViewById(R.id.bInstallTheme);
bInstall.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
showDialog();
}
});
}
public void showDialog(){
progressDialog = ProgressDialog.show(Install.this, "", "Installing Theme", true);
Thread thread = new Thread();
thread.start();
}
public void run(){
try{
Thread.sleep(1000);
CommandCapture command = new CommandCapture(0, "su", "sh /sdcard/plasma/scripts/install.sh");
try {
RootTools.getShell(true).add(command).waitForFinish();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
} catch (RootDeniedException e) {
e.printStackTrace();
}
}catch (InterruptedException e){
e.printStackTrace();
}
handler.sendEmptyMessage(0);
}
private static Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
progressDialog.dismiss();
}
};
}
So, am I doing something wrong? Why won't it run my code? Thanks!
The thread doesn't know what to run. Change
public class Install extends Activity{
to
public class Install extends Activity implements Runnable {
and change
Thread thread = new Thread();
to
Thread thread = new Thread(this);

Categories

Resources