Xml download from server.Timeout not working - android

I am trying to download some xml files through this code.
Everything works fine when network is available.I have already handled the issue when network is not at all there. But the issue m facing right now is that ,when network is slow ,the download doesnt timeout.
Time out is not at all working ,I think.How to make it work?
URL mUrl = new URL(url[i]);
URLConnection conexion = mUrl.openConnection();
response[i] = new DownloadResponse();
response[i].setSuccessful(false);
conexion.connect();
conexion.setConnectTimeout(10000);
// this will be useful so that you can show a typical 0-100% progress bar
ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
if (outputFile != null) { // one output file specified in constructor
output = new BufferedOutputStream(new FileOutputStream(
outputFile));
} else if (outputFiles != null) { // an array of output files specified
output = new BufferedOutputStream(new FileOutputStream(
outputFiles[i]));
} else {// no output file specified
output = new BufferedOutputStream(outBytes);
}
InputStream input = new BufferedInputStream(mUrl.openStream());
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
output.write(data, 0, count);
}
output.flush();
response[i].setSuccessful(true);
response[i].count = i;
response[i].setResponseText(outBytes.toString());
if (total < 32 && outBytes.toString().indexOf("Invalid") < -1){
response[i].setSuccessful(false);
}
output.close();
input.close();
publishProgress(response[i]);

in onclick whendownload button
define globally in class boolean b = true;
count_Timer = new CountDownTimer(20000, 1000) {
#Override
public void onTick(long arg0) {
// TODO Auto-generated method stub
}
#Override
public void onFinish() {
b = false;
pd.dismiss();
dialog.dismiss();
AlertDialog.Builder builder1 = new AlertDialog.Builder(
AppSetting.this);
builder1.setTitle("appname");
builder1.setMessage("You can't Continue because internet is Very slow.");
builder1.setNeutralButton("OK",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog,
int which) {
}
});
builder1.show();
}
};
on beginning of download task
count_Timer.start();
on last line of doinbackground
count_Timer.cancel();
and on postexecute method
if (pd.isShowing())
pd.dismiss();
if (b) {
dialog.dismiss();
simplealert(result.replace("\"", ""));
} else {
}

Related

programmatically update apk (download&start installation) Android API v26

I read all of the solutions about this problem.Also I know it can be considered as duplicated but it is not.
I see Error: Try Again toast message and I see Update Error log message.
I think at android v26 changed somethings about intent.setDataAndType or I dont know why this is not working.
Also I get the permissions something like this code
ActivityCompat.requestPermissions(Update.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_WRITE_STORAGE);
Problem can not be solved. I just want to do download and install apk file.
AndroidManifest.xml (I added write permission)
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Update.java
package com.my.testapp;
public class Update extends AppCompatActivity {
ProgressDialog bar;
private static String TAG = "Update";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new DownloadNewVersion().execute();
}
class DownloadNewVersion extends AsyncTask<String,Integer,Boolean> {
#Override
protected void onPreExecute() {
super.onPreExecute();
bar = new ProgressDialog(Update.this);
bar.setCancelable(false);
bar.setMessage("Downloading...");
bar.setIndeterminate(true);
bar.setCanceledOnTouchOutside(false);
bar.show();
}
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
bar.setIndeterminate(false);
bar.setMax(100);
bar.setProgress(progress[0]);
String msg = "";
if(progress[0]>99){
msg="Finishing... ";
}else {
msg="Downloading... "+progress[0]+"%";
}
bar.setMessage(msg);
}
#Override
protected void onPostExecute(Boolean result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
bar.dismiss();
if(result){
Toast.makeText(getApplicationContext(),"Update Done",
Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(getApplicationContext(),"Error: Try Again",
Toast.LENGTH_SHORT).show();
}
}
#Override
protected Boolean doInBackground(String... arg0) {
Boolean flag = false;
try {
URL url = new URL("http://mydownloadurl.com/_download/update.apk");
HttpURLConnection c = (HttpURLConnection) url.openConnection();
c.setRequestMethod("GET");
c.setDoOutput(true);
c.connect();
String PATH = Environment.getExternalStorageDirectory()+"/Download/";
File file = new File(PATH);
file.mkdirs();
File outputFile = new File(file,"app-debug.apk");
if(outputFile.exists()){
outputFile.delete();
}
FileOutputStream fos = new FileOutputStream(outputFile);
InputStream is = c.getInputStream();
int total_size = 277962;//size of apk
byte[] buffer = new byte[1024];
int len1 = 0;
int per = 0;
int downloaded=0;
while ((len1 = is.read(buffer)) != -1) {
fos.write(buffer, 0, len1);
downloaded +=len1;
per = (int) (downloaded * 100 / total_size);
publishProgress(per);
}
fos.close();
is.close();
OpenNewVersion(PATH);
flag = true;
} catch (Exception e) {
Log.e(TAG, "Update Error: " + e.getMessage());
flag = false;
}
return flag;
}
}
void OpenNewVersion(String location) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(location + "app-debug.apk")),
"application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
Commonsware thanks a lot, I waste my 2-3 hours to do different ways.
Actually I added this code before but the problem was not solved.
I tried again and it worked, it might be lazy solution but it is working.
This url have more info about the problem ,other solutions can be applied,
but it is enough for me.
if(Build.VERSION.SDK_INT>=24){
try{
Method m = StrictMode.class.getMethod("disableDeathOnFileUriExposure");
m.invoke(null);
}catch(Exception e){
e.printStackTrace();
}
}
It is totally fixed thank you very much again.
Application also need this storage permission.
ActivityCompat.requestPermissions(Update.this,new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE

Double Progress Bars with update via AsyncTask

I am developing an app that downloads files and show 2 progress bars, the first one for the current downloading file, and the 2nd one for total progress based on the number of files.
I am using the DoubleProgressBar library in my app:
I succeeded to update the first ProgressBar, but stuck with the 2nd one.
Here is my code for the AsyncTask class:
private DoubleProgressDialog pDialog;
class DownloadFileFromURL extends AsyncTask<String, Integer, String> {
Context mContext;
public DownloadFileFromURL(Context ctx) {
// TODO Auto-generated constructor stub
this.mContext = ctx;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
showDialog(CUSTOM_PROGRESS_DIALOG);
}
/* Downloading file in background thread */
#Override
protected String doInBackground(String... f_url) {
InputStream input = null;
OutputStream output = null;
HttpURLConnection connection = null;
try {
URL url = new URL(f_url[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
// getting file length
int fileLength = connection.getContentLength();
for (int i = 0; i <= ArrayOfFiles.length; i++){
File f = new File(Environment.getExternalStorageDirectory() + "/Folder/", ArrayOfFiles[i]);
// input stream to read file - with 8k buffer
input = new BufferedInputStream(url.openStream(), 8192);
// Output stream to write file
output = new FileOutputStream(f);
byte data[] = new byte[8192];
long total = 0;
int count;
int EntireProgress = 0;
while ((count = input.read(data)) != -1) {
// allow canceling with back button
if (isCancelled()) {
input.close();
return null;
}
total += count;
// publishing the progress....
if (fileLength > 0) // only if total length is known
publishProgress((int)(total * 100 / fileLength));
output.write(data, 0, count);
/*Here is my trouble, the 2nd ProgressBar is updating as the same of the first one, I need the 2nd one to update itself slowly till all files get downloaded*/
int CurrentProgress = pDialog.getProgress();
pDialog.setSecondaryProgress(CurrentProgress );
publishProgress(CurrentProgress );
}
} catch (Exception e) {
return e.toString();
} finally {
try {
if (output != null)
output.close();
if (input != null)
input.close();
}
} catch (IOException ignored) {
}
if (connection != null)
connection.disconnect();
}
return null;
}
#Override
protected void onPostExecute(String result) {
// dismiss the dialog after the file was downloaded
dismissDialog(CUSTOM_PROGRESS_DIALOG);
if (result != null)
Toast.makeText(mContext,"Download error: " + result, Toast.LENGTH_LONG).show();
else
Toast.makeText(mContext,"File downloaded", Toast.LENGTH_SHORT).show();
}
#Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
// if we get here, length is known, now set indeterminate to false
pDialog.setIndeterminate(false);
pDialog.setMax(100);
pDialog.setProgress(progress[0]);
}
}
I also used this method in my activity class:
#Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case CUSTOM_PROGRESS_DIALOG:
pDialog = new DoubleProgressDialog(NetworkActivity.this);
pDialog.setMessage("Downloading file. Please wait...");
pDialog.setMax(100);
pDialog.setIndeterminate(true);
pDialog.setCancelable(false);
pDialog.setButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.cancel();
}
});
pDialog.show();
return pDialog;
default:
return null;
}
}
Any idea?
First part is to move pDialog.setSecondaryProgress to the onProgressUpdate(Integer... progress) method.
You are also resetting the secondary progress in each download task by setting it to CurrentProgress which is set to pDialog.getProgress();. Hence the second progress will always be reset after the download is finished.
Edit:
// publishing the progress....
if (fileLength > 0) // only if total length is known
publishProgress((int)(total * 100 / fileLength), pDialog.getSecondaryProgress());
(...)
int CurrentProgress = pDialog.getProgress();
// do not update secondary progress here
// pDialog.setSecondaryProgress(CurrentProgress );
int secondaryProgress = (CurrentProgress + 100 * i)/ArrayOfFiles.length;
publishProgress(CurrentProgress, secondaryProgress);
And the onProgressUpdate
#Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
(...)
pDialog.setProgress(progress[0]);
pDialog.setSecondaryProgress(progress[1]);
}
If you are not setting your DownloadFileFromUrl outside your main class I would suggest something like this
int CurrentProgress = pDialog.getProgress();
int secondaryProgress = (CurrentProgress + 100 * id_treated_file)/number_of_files;
// id_treated_file - 0, 1, 2, ... , number_of_files - 1
pDialog.setSecondaryProgress(CurrentProgress);
// secondaryProgress will be progress[1] in your onProgressUpdate method
publishProgress(CurrentProgress, secondaryProgress);
your onProgressUpdate method should look like this :
#Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
// if we get here, length is known, now set indeterminate to false
pDialog.setIndeterminate(false);
pDialog.setMax(100);
pDialog.setProgress(progress[0]);
pDialog.setSecondaryProgress(progress[1]);
}
EDIT
or you can try
pDialog.setSecondaryProgress((progress[0] + 100 * id_treated_file)/number_of_files);

ProgressDialog is not showing when .3gp file converting to a .zip

I am working on Android app.
I need to show a progress dialog box when I click on button.
In that button I am converting video file to .zip file and calculating that file size.
In this process I need to show a ProgressDialog, but it is not showing.
Screen get struck while calculating and after calculation it shows ProgressDialog and then screen navigating to the next screen.
My Code:
save.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MediaCheck.this.runOnUiThread(new Runnable() {
public void run() {
pd = ProgressDialog.show(MediaCheck.this, "",
"Checking the video compatability. Please wait", true);
}
});
video_Path= makeZip(video_Path);
if (video_Path.equalsIgnoreCase("File size is too large")) {
pd.dismiss();
Toast.makeText(getApplicationContext(),
"Large video", Toast.LENGTH_LONG)
.show();
return;
}
pd.dismiss();
// Doing screen navigation here.
}
});
Code to make a zip and know the size
private static String makeZip(String videoPath) {
byte[] buffer = new byte[1024];
String[] videoFileName = videoPath.split("/");
File directory = null;
try {
ContextWrapper cw = new ContextWrapper(context_this);
// path to /data/data/yourapp/app_data/imageDir
directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
FileOutputStream fos = new FileOutputStream(directory
+ "/IRCMS_Video.zip");
ZipOutputStream zos = new ZipOutputStream(fos);
ZipEntry ze = null;
ze = new ZipEntry(videoFileName[5]);
zos.putNextEntry(ze);
FileInputStream in = new FileInputStream(videoPath);
int len;
while ((len = in.read(buffer)) > 0) {
zos.write(buffer, 0, len);
}
File videoZip = new File(directory + "/IRCMS_Video.zip");
videoLength = videoZip.length() / (1024 * 1024);
if (videoLength > 3)
return "File size is too large";
in.close();
zos.closeEntry();
// remember close it
zos.close();
System.out.println("Done");
} catch (IOException ex) {
ex.printStackTrace();
}
return directory.toString() + "/IRCMS_Video.zip";
}
}
Please help...
then you should try ASYNCTASK to easily perform your operation and reduce the complexity of using threads
private class Converter extends AsyncTask<String, Void, Void> { //Converter is class name
protected String doInBackground(String... urls) {
//THIS METHOD WILL BE CALLED AFTER ONPREEXECUTE
//YOUR NETWORK OPERATION HERE
return null;
}
protected void onPreExecute() {
super.onPreExecute();
//THIS METHOD WILL BE CALLED FIRST
//DO OPERATION LIKE SHOWING PROGRESS DIALOG PRIOR TO BEGIN NETWORK OPERATION
}
protected void onPostExecute(String result) {
super.onPostExecute();
//TNIS METHOD WILL BE CALLED AT LAST AFTER DOINBACKGROUND
//DO OPERATION LIKE UPDATING UI HERE
}
}
You are doing calculation on UI thread therfore it hangs your app. Do calculation on background thread. You can resolve this by-
save.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
pd = ProgressDialog.show(MediaCheck.this, "",
"Checking the video compatability. Please wait", true);
Thread background = new Thread(new Runnable() {
public void run() {
// TODO Auto-generated method stub
video_Path= makeZip(video_Path);
MediaCheck.this.runOnUiThread(new Runnable()
{
public void run()
{
if (video_Path.equalsIgnoreCase("File size is too large")) {
pd.dismiss();
Toast.makeText(getApplicationContext(),
"Large video", Toast.LENGTH_LONG)
.show();
pd.dismiss();
return;
}
}
});
}
});
background.start();
// Doing screen navigation here.
}
});

isCancelled() not Working in android Async Task

I want to cancel a downloading file using async task, i tried below code, here isCancelled() method is not working, can any one suggest how can i stop download.
vid1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
down d1=new down();
if(vid1.getText().toString().equals("Start")){
Log.v("Vid 1", "Vid 1");
vid1.setText("Pause");
d1.execute(url1,"one");
}else if(vid1.getText().toString().equals("Pause")){
vid1.setText("Start");
Log.v("Vid 1 Else", "Vid 1 Else");
if(d1!=null && d1.getStatus()!=AsyncTask.Status.FINISHED){
d1.cancel(true);
}
}
}
});
vid2.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.v("Vid 2", "Vid 2");
// TODO Auto-generated method stub
down d2=new down();
if(vid2.getText().toString().equals("Start")){
vid2.setText("Pause");
d2.execute(url2,"two");
}else if(vid2.getText().toString().equals("Pause")){
vid2.setText("Start");
Log.v("Vid 2 Else", "Vid 2 Else ");
d2.cancel(true);
}
}
});
}
private class down extends AsyncTask<String, Void, String>{
RandomAccessFile output ;
boolean cancel=false;
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
Log.v("Pre Execute", "Pre Execute");
}
#Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
File outputFileCache=new File(Environment.getExternalStorageDirectory()+"/pau/"+params[1]+".mp4");
try {
Long download_ok = null ;
int fileLength;
URL url = new URL(params[0]);
HttpURLConnection connection = (HttpURLConnection) url.openConnection() ;
if (outputFileCache.exists())
{
Log.v(">>>>>>", "Exists");
connection.setAllowUserInteraction(true);
connection.setRequestProperty("Range", "bytes=" + outputFileCache.length() + "-");
}
connection.setConnectTimeout(14000);
connection.setReadTimeout(20000);
connection.connect();
if (connection.getResponseCode() / 100 != 2)
throw new Exception("Invalid response code!");
else
{
String connectionField = connection.getHeaderField("content-range");
if (connectionField != null)
{
String[] connectionRanges = connectionField.substring("bytes=".length()).split("-");
download_ok = Long.valueOf(connectionRanges[0]);
Log.v("download ok", ""+download_ok);
}
if (connectionField == null && outputFileCache.exists())
outputFileCache.delete();
if(download_ok==null){
download_ok=(long) 0;
}
fileLength = (int) (connection.getContentLength() + download_ok);
Log.v("file length", ""+fileLength);
input = new BufferedInputStream(connection.getInputStream());
output = new RandomAccessFile(outputFileCache, "rw");
output.seek(download_ok);
byte data[] = new byte[1024];
int count = 0;
int __progress = 0;
while ((count = input.read(data, 0, 1024)) != -1 && __progress!=100)
{
Log.v(">>>>>>>>>>>progress cancelled", "<<<<<<<<<"+isCancelled());
if(isCancelled()){
Log.v(">>>>>>>>>>>>>>>>>>>>>>>>>>>", "<<<<<<<<<"+isCancelled());
break;
}else{
download_ok += count;
output.write(data, 0, count);
__progress = (int) ((download_ok * 100) / fileLength);
}
}
output.close();
input.close();
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
}
Found your problem: You are creating a new instance of the Asynctask with every click, e.g.
down d2=new down();
This means that you are calling cancel on a different AsyncTask object. You need to move this line into your check for the start click and also use a field and not a local variable i.e.
if(vid2.getText().toString().equals("Start")) {
d2 = new down();
vid2.setText("Pause");
d2.execute(url2,"two");
}
where d2 is set in your class. Also note that class names should always start with capital letters, i.e. class Down instead of class down.
EDIT
You can store the Asynctask in a global class array that is equal in length to the number of videos.
Down downTasks[] = new Down[TOTAL VIDEOS];
Then you initialise the Views, similar to what you already did, here shown for one View
vid1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(vid1.getText().toString().equals("Start")){
Log.v("Vid 1", "Vid 1");
vid1.setText("Pause");
downTasks[0] = new down();
downTasks[0].execute(url1,"one");
}
else if(vid1.getText().toString().equals("Pause")){
vid1.setText("Start");
Log.v("Vid 1 Else", "Vid 1 Else");
if(downTasks[0]!=null && downTasks[0].getStatus()!=AsyncTask.Status.FINISHED){
downTasks[0].cancel(true);
}
}
}
});
Note that this code is quite redundant because you rewrite almost exactly the same code for every View, this can be nicely refactored with a for loop, but I leave that as an exercise for you if you feel like it.

Stop on going download on button click android

I am developing an application, which focus mainly on downloading a file from web service and storing it in sd card. Everything went easy until my client needs to cancel the on going download. I tried many ways but i failed. So can any one help me out and post some snippets for cancelling on going download. Intent service will be much preferred.
Edit:
Toast.makeText(ThumbnailView.this, R.string.Download_start, Toast.LENGTH_SHORT).show();
pb.setVisibility(View.VISIBLE);
info_icon.setVisibility(View.INVISIBLE);
langBtn.setVisibility(View.INVISIBLE);
name.setVisibility(View.INVISIBLE );
author.setVisibility(View.INVISIBLE );
lastReading.setVisibility(View.INVISIBLE);
intent = new Intent(ThumbnailView.this,
DownloadAndExtractFiles.class);
Common.isDownloadProgress = true;
intent.putExtra("BEAN", bean);
intent.putExtra("FROM", "library");
intent.putExtra("receiverTag", mReceiver);
startService(intent);
IntentService Class:
try {
File file = new File(path, /* BOOK_ID */filename + fileformat);
if (file.exists())
file.delete();
file.createNewFile();
output = new FileOutputStream(file);
finalpath = path + "/" + filename + fileformat;
Log.d("book UNEXTR path", finalpath);
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
if (Common.downloadChkLogout) {
// Changed on saturday 9th nov
//if (Common.isDownloadProgress) {
if (stopped) {
break;
}
total += count;
Bundle resultData = new Bundle();
resultData.putInt("progress",
(int) (total * 100 / lenghtOfFile));
bean.setProgress((int) (total * 100 / lenghtOfFile));
rec.send(UPDATE_PROGRESS, resultData);
output.write(data, 0, count);
}
}
success = true;
//}
output.flush();
output.close();
input.close();
} catch (Exception ex) {
ex.printStackTrace();
mError = "Download Failed";
System.out.println("Net Disconnect;:" + mError);
Toast.makeText(getApplicationContext(), mError,
Toast.LENGTH_LONG).show();
}
Edit:
public void onClick(DialogInterface dialog,int id) {
Log.i("Aftr before service stopped---->>>>>", "true");
Log.i("Intent obj","Intent check..."+intent);
if(intent!=null)
{
Common.isDownloadProgress = false;
stopService(intent);
This is my cancel click
I have posted my code for starting the service, and downloading part on onHandleIntent
Thanks in advance :)
you need to check whether it's stopped or not from within your service and you are half done on that line
if (stopped)
break;
now make stopped a static boolean and set it to true on button click,
Edit
You are already checks Common.isDowloadProgress but it's commented and I believe you need to break the loop as follows
while ((count = input.read(data)) != -1)
{
if (Common.downloadChkLogout)
{
if (Common.isDownloadProgress)
{
if (stopped)
{ break; }
total += count;
Bundle resultData = new Bundle();
resultData.putInt("progress",
(int) (total * 100 / lenghtOfFile));
bean.setProgress((int) (total * 100 / lenghtOfFile));
rec.send(UPDATE_PROGRESS, resultData);
output.write(data, 0, count);
}
else
{ break; }
}
}
success = true;
I thing you should use AsyncTask for downloading items, It porvide on cancel event as well.
Let say you are using HttpGet to download you file, your task will look like...
public class FileDownloadingTask extends AsyncTask<Void, Void, Void> {
private String url = null;
private String destPath = null;
private HttpGet httpGet = null;
// Constructor
public FileDownloadingTask(String url, String destPath) {
this.url = url;
this.destPath = destPath;
}
// Create a progress dialog in your onPreExecute
// Start downloading in your doInBackground and save to destPath in sd-card
// Proform any thing your want in response to download process in onPostCreate
// Finally...
#Override
protected void onCancelled() {
super.onCancelled();
// Aborting http request
if (httpget != null) {
httpget.abort();
}
}
// Then in your cancel button of progress dialog call this.onCancel();
}
Hope this will give you some hint...:)
Add this on your button click. Modify the if condition to suit your needs. I am uploading a video and when i click on remove, this happens :-
if(processFileUploadTask !=null && processFileUploadTask.getStatus() != AsyncTask.Status.FINISHED){
Thread t = new Thread(new Runnable() {
public void run() {
if(httpost != null ){
httpost.abort();
}
}
});
t.start();

Categories

Resources