I try to refresh TextView in Android. I am using ExecutorService in my code. When I pushed the "Start refresh" button, after several seconds my app has been stopped by Android system. I have read several topics in stackoverflow.com, but I still cannot understand what I am doing wrong. Here is my code:
MainActivity.java:
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class MainActivity extends Activity {
private static ExecutorService exec;
private static TextView textView;
private static Calendar cal;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.text_field);
cal = new GregorianCalendar();
exec = Executors.newSingleThreadExecutor();
}
private static class Task implements Runnable {
#Override
public void run() {
try {
while(!Thread.currentThread().isInterrupted()) {
textView.setText(cal.getTime().toString());
TimeUnit.SECONDS.sleep(1);
}
}
catch (InterruptedException e) {
return;
}
}
}
public void finish_refresh(View view) {
exec.shutdownNow();
}
public void start_refresh(View view) {
exec.submit(new Task());
}
}
activity_main.xml:
<LinearLayout 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"
tools:context=".MainActivity"
android:orientation="vertical">
<Button android:layout_width="200dp"
android:layout_height="50dp"
android:text="#string/start_refresh"
android:onClick="start_refresh"/>
<Button android:layout_width="200dp"
android:layout_height="50dp"
android:text="#string/finish_refresh"
android:onClick="finish_refresh"/>
<TextView android:layout_height="200dp"
android:layout_width="200dp"
android:layout_marginTop="10dp"
android:id="#+id/text_field" />
</LinearLayout>
You need to use runOnUiThread()
Add following code in your onCreate() method:
Thread t = new Thread() {
#Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(1000);
runOnUiThread(new Runnable() {
#Override
public void run() {
// update TextView here!
textView.setText(cal.getTime().toString());
}
});
}
} catch (InterruptedException e) { }
}
};
t.start();
Related
I am trying to stream mp3 file from the internet. App successfully started but showing unexpected behavior. The playback doesn't play sound, the play button doesn't changes its icon. The playback stops after showing "please wait message" when it is expected to play the file on clicking the play icon.
Here's my code:
MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.media.MediaPlayer;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.TextView;
import java.util.concurrent.TimeUnit;
import dyanamitechetan.vusikview.VusikView;
public class MainActivity extends AppCompatActivity implements MediaPlayer.OnBufferingUpdateListener, MediaPlayer.OnCompletionListener {
ImageButton imageButton;
SeekBar seekBar;
TextView textView;
VusikView musicView;
MediaPlayer mediaPlayer;
int mediaFileLength;
int realTimeLength;
final Handler handler = new Handler();
#SuppressLint("ClickableViewAccessibility")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
musicView = findViewById(R.id.musicView);
seekBar = findViewById(R.id.seekbar);
seekBar.setMax(99);
seekBar.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if(mediaPlayer.isPlaying()){
SeekBar seekBar = (SeekBar) view;
int playPosition = (mediaFileLength/100)*seekBar.getProgress();
mediaPlayer.seekTo(playPosition);
}
return false;
}
});
imageButton = findViewById(R.id.btn_play_pause);
imageButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
final ProgressDialog mDialog = new ProgressDialog(MainActivity.this);
AsyncTask<String,String,String>mp3Play = new AsyncTask<String, String, String>() {
#Override
protected void onPreExecute(){
mDialog.setMessage("Please wait");
mDialog.show();
}
#Override
protected String doInBackground(String... strings) {
try {
mediaPlayer.setDataSource(strings[0]);
mediaPlayer.prepare();
}
catch (Exception ex){
}
return "";
}
#Override
protected void onPostExecute(String s) {
mediaFileLength = mediaPlayer.getDuration();
realTimeLength = mediaFileLength;
if(!mediaPlayer.isPlaying()){
mediaPlayer.start();
imageButton.setImageResource(R.drawable.ic_pause);
} else {
mediaPlayer.pause();
imageButton.setImageResource(R.drawable.ic_play);
}
updateSeekBar();
mDialog.dismiss();
}
};
mp3Play.execute("https://soundcloud.com/theastonshuffle/nasa-feat-kanye-west-santogold-lykke-li-gifted-aston-shuffle-long-mix");
musicView.start();
}
});
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnBufferingUpdateListener(this);
mediaPlayer.setOnCompletionListener(this);
}
private void updateSeekBar() {
seekBar.setProgress((int)((float)mediaPlayer.getCurrentPosition() / mediaFileLength*100));
if(mediaPlayer.isPlaying()){
Runnable updater = new Runnable() {
#Override
public void run() {
updateSeekBar();
realTimeLength-=1000;
textView.setText(String.format("%d:%d", TimeUnit.MILLISECONDS.toMinutes(realTimeLength),
TimeUnit.MILLISECONDS.toSeconds(realTimeLength) -
TimeUnit.MILLISECONDS.toSeconds(TimeUnit.MILLISECONDS.toMinutes(realTimeLength))));
}
};
handler.postDelayed(updater,1000);
}
}
#Override
public void onBufferingUpdate(MediaPlayer mediaPlayer, int i) {
seekBar.setSecondaryProgress(i);
}
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
imageButton.setImageResource(R.drawable.ic_play);
musicView.stopNotesFall();
}
}
activity_main.xml
<dyanamitechetan.vusikview.VusikView
android:id="#+id/musicView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<RelativeLayout
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/textTimer"
android:layout_centerHorizontal="true"
android:text="00:00"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ImageButton
android:layout_below="#id/textTimer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/btn_play_pause"
android:src="#drawable/ic_play"/>
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/btn_play_pause"
android:id="#+id/seekbar"/>
</RelativeLayout>
you APP connect Internet ?
please check manifest is add internet permission
You can use the mediaplay.setdataSource (url);method directly to load
And setmediaplay.prepareAsync (); use asynchronous method to load music
No need to use AsyncTask
I am trying get the image of the camera and process it continuous, so, I am using CameraKit package:
package com.example.alex.tfmobile;
import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.HandlerThread;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import com.camerakit.CameraKitView;
import java.io.InputStream;
public class MainActivity extends AppCompatActivity {
private HandlerThread backgroundThread;
private Handler backgroundHandler;
private final Object lock = new Object();
private boolean runClassifier = false;
private static final String HANDLE_THREAD_NAME = "CameraBackground";
TextView resultView;
private CameraKitView cameraView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
cameraView = (CameraKitView) findViewById(R.id.camera);
resultView = (TextView) findViewById(R.id.results);
startBackgroundThread();
}
#Override
protected void onResume() {
super.onResume();
cameraView.onResume();
startBackgroundThread();
}
#Override
protected void onPause() {
cameraView.onPause();
stopBackgroundThread();
super.onPause();
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
cameraView.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
private void startBackgroundThread() {
backgroundThread = new HandlerThread(HANDLE_THREAD_NAME);
backgroundThread.start();
backgroundHandler = new Handler(backgroundThread.getLooper());
synchronized (lock) {
runClassifier = true;
}
backgroundHandler.post(periodicClassify);
}
private Runnable periodicClassify =
new Runnable() {
#Override
public void run() {
synchronized (lock) {
if (runClassifier) {
classifyFrame();
}
}
backgroundHandler.post(periodicClassify);
}
};
private void classifyFrame() {
cameraView.captureImage(new CameraKitView.ImageCallback() {
#Override
public void onImage(CameraKitView cameraKitView, final byte[] picture) {
Bitmap bitmap = BitmapFactory.decodeByteArray(picture, 0, picture.length);
}
});
}
private void stopBackgroundThread() {
backgroundThread.quitSafely();
try {
backgroundThread.join();
backgroundThread = null;
backgroundHandler = null;
synchronized (lock) {
runClassifier = false;
}
} catch (InterruptedException e) {
Log.e("TfMobile", "Interrupted when stopping background thread", e);
}
}
}
Layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.camerakit.CameraKitView
android:id="#+id/camera"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:camera_facing="back"/>
<TextView
android:id="#+id/results"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
But the problem is in classifyFrame method, when I try to access the variable cameraView, it thrown an exception of Null pointer. I would like to know how can I use the camera with a thread to process the frames.
The error:
Process: com.example.alex.tfmobile, PID: 26659
java.lang.NullPointerException: Attempt to invoke virtual method 'int com.camerakit.CameraKitView$Size.getWidth()' on a null object reference
at com.camerakit.CameraKitView$Camera2$1$7.run(CameraKitView.java:1844)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.os.HandlerThread.run(HandlerThread.java:61)
10-06 02:07:29.848 26659-26659/? E/ViewRootImpl#3b4860a[MainActivity]: ViewRootImpl #2 Surface is not valid.
It looks you are trying to access it before surface prepare, You could try to comment out startBackgroundThread(); from onCreate. You are already calling it from onResume. Hope it should work or you can wait till surface prepared.
I was wondering how I can change the position of an ImageButton every second. I want the position to be random each time. I do not know where to start to accomplish this. Any suggestions?
Maybe this will give you some idea
activity_main.xml
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageButton
android:id="#+id/button"
android:layout_width="50dp"
android:layout_height="50dp"
android:text="I am button"/>
</RelativeLayout>
MainActivity.java
package com.com.randombutton;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.ImageButton;
import android.widget.RelativeLayout;
import java.util.Random;
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ImageButton button = (ImageButton) findViewById(R.id.button);
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
Random rand = new Random();
while (true) {
Log.e("TAG", "thread");
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) button.getLayoutParams();
params.setMargins(rand.nextInt(500), rand.nextInt(500), 0, 0);
try {
Thread.sleep(1000);
} catch (Exception e) {
}
button.post(new Runnable() {
#Override
public void run() {
button.requestLayout(); //has to be called in UI thread
}
});
}
}
});
thread.start();
}
}
The idea is pretty simple. Make a thread, move a view and put it to sleep for 1 second. Probably there are better ways to move the view itself.
I am new to java and andriod and i think that i did something wrong with thread
Program starts without any errors.
I have inserted one button just for test and it shows without problem. Text view doesnt even displays "Hello world" default string.
Here is the code
package com.example.studentservis;
import android.R.string;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.view.Menu;
import android.widget.TextView;
import java.net.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.io.*;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.w3c.dom.Text;
public class MainActivity extends Activity {
StringHandler stringHandler = new StringHandler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
thread.run();
TextView txtView = (TextView)this.findViewById(R.id.textView1);
txtView.setText(stringHandler.getString());
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
Thread thread = new Thread(){
public void run(){
try {
stringHandler.setString(webRequest());
} catch (Exception e) {
// TODO Auto-generated catch block
stringHandler.setString(e.getMessage());
}
}
};
public String webRequest() throws Exception{
String servisURL = "http://www.sczg.unizg.hr/student-servis/";
Document doc = Jsoup.connect(servisURL).get();
Elements jobNode = doc.select("div.jobBox");
return jobNode.get(0).text();
}
public class StringHandler
{
public String str = "test";
public void setString(String s)
{
str = s;
}
public String getString()
{
return str;
}
}
}
When you start a new Thread, the UI thread won't wait until the new thread is complete. That is the purpose of the Threads.
Here :
thread.run();
When you a start the new thread to update the stringHandler, the UI thread tries to process the next command which is :
txtView.setText(stringHandler.getString());
When the UI thread gets to this, the stringHandler hasn't updated yet, so It's null and thus it will show nothing in the textview.
All you should do is to try to update the textview from the new Thread when it's finished.
Try this:
Thread thread = new Thread(){
public void run(){
try {
stringHandler.setString(webRequest());
} catch (Exception e) {
// TODO Auto-generated catch block
stringHandler.setString(e.getMessage());
}
runOnUiThread(new Runnable() {
#Override
public void run() {
TextView txtView = (TextView)this.findViewById(R.id.textView1);
txtView.setText(stringHandler.getString());
}
});
}
};
You can use a handler or a asyctask for this purpose. Asynctask is easier.
http://developer.android.com/reference/android/os/AsyncTask.html
You can create your own thread but remember to update ui on the ui thread.
activity_main.xml
<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"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="166dp"
android:text="Loading..." />
</RelativeLayout>
MainActivity.java
Removed StringHandler cause i felt it was unnecessary in this context.
public class MainActivity extends Activity {
TextView txtView ;
String s;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txtView = (TextView)this.findViewById(R.id.textView1); // initialize textview
//txtView.setText(stringHandler.getString());
new Thread(new Runnable() { // thread
#Override
public void run(){
try {
s = webRequest(); // get string
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
runOnUiThread(new Runnable() //run on ui threa
{
public void run()
{
txtView.setText(s); // update ui on the ui thread.
}
});
}
}).start();
}
public String webRequest() throws Exception{ // web request
String servisURL = "http://www.sczg.unizg.hr/student-servis/";
Document doc = Jsoup.connect(servisURL).get();
Elements jobNode = doc.select("div.jobBox");
return jobNode.get(0).text();
}
}
Resulting snap shot
This part of your code : txtView.setText(stringHandler.getString());
should be put after the thread finished.
thread.run(); <------ Start running thread in background
TextView txtView = (TextView)this.findViewById(R.id.textView1);
txtView.setText(stringHandler.getString());
// the textView was set without knowing whether the Thread is finished or not.
// thus, textView is shown as empty, because stringHandler.getString() still has empty string
My suggestion is that you implement it inside an asyncTask, so that you can set the text within onPostExecute()
Good luck ^^
EDIT :
here's some example AsyncTask
private class StringSet extends AsyncTask <Void,Void,Void> {
#Override
protected void doInBackground(Void... params) {
try {
stringHandler.setString(webRequest());
} catch (Exception e) {
stringHandler.setString(e.getMessage());
}
}
#Override
protected void onPostExecute(Void... results) {
txtView.setText(stringHandler.getString());
}
}
And replace your thread.run() with new StringSet().execute();
I just need to know how to play this below link in android...i tried it in emulator its working but not on device why.....Help is appreciated......
http://stream.radiosai.net:8002/
Already i have implemented play streaming audio in my app.Directly i paste this code here .Remove unnecessary data and use it.i have tested your link in it ,is working for me.
import java.io.IOException;
import android.app.Activity;
import android.app.ProgressDialog;
import android.graphics.drawable.AnimationDrawable;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnInfoListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ImageView;
import android.widget.ToggleButton;
public class StreamAudio extends Activity implements OnPreparedListener,
OnErrorListener {
MediaPlayer mp;
private ToggleButton btn;
private ImageView img;
private boolean flag = false;
AnimationDrawable frameAnimation;
ProgressDialog progress;
String url="http://stream.radiosai.net:8002/";
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
btn = (ToggleButton) findViewById(R.id.play);
img = (ImageView) findViewById(R.id.radio_image);
img.setBackgroundResource(R.drawable.frames);
frameAnimation = (AnimationDrawable) img.getBackground();
mp = new MediaPlayer();
progress=ProgressDialog.show(this, null ,"Loading...",false,true);
Runnable r=new Runnable() {
#Override
public void run() {
setPlayBack();
}
};
Thread th=new Thread(r);
th.start();
mp.setOnPreparedListener(this);
//mp.setOnBufferingUpdateListener(this);
mp.setOnErrorListener(this);
// mp.setOnInfoListener(this);
btn.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(flag)
{
if(!isChecked)
{
btn.setBackgroundResource(R.drawable.btn_stop);
mp.start();
frameAnimation.start();
}
else
{
btn.setBackgroundResource(R.drawable.btn_play);
frameAnimation.stop();
mp.stop();
mp.reset();
flag=false;
}
}
else
{
btn.setChecked(false);
progress=ProgressDialog.show(StreamAudio.this, null ,"Loading...",false,false);
Runnable r=new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
setPlayBack();
}
};
Thread th=new Thread(r);
th.start();
}
}
});
}
#Override
protected void onDestroy() {
super.onDestroy();
mp.release();
}
#Override
public void onPrepared(MediaPlayer mp) {
flag = true;
handler.sendEmptyMessage(0);
}
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
mp.release();
return false;
}
private void setPlayBack()
{
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
mp.setDataSource(url);
} catch (IllegalArgumentException e1) {
e1.printStackTrace();
} catch (IllegalStateException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
mp.prepareAsync();
}
private Handler handler=new Handler(){
#Override
public void handleMessage(Message msg) {
progress.dismiss();
btn.setBackgroundResource(R.drawable.btn_stop);
frameAnimation.start();
mp.start();
}
};
}
main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout android:layout_alignParentBottom="true"
android:gravity="center" android:layout_width="fill_parent"
android:background="#drawable/bottom_bar" android:layout_height="wrap_content">
<ToggleButton android:background="#drawable/btn_stop" android:checked="false" android:id="#+id/play" android:textOff="" android:textOn=""
android:layout_width="wrap_content" android:layout_height="wrap_content"></ToggleButton>
</LinearLayout>
<ImageView android:id="#+id/radio_image"
android:layout_height="wrap_content" android:layout_width="wrap_content"
android:layout_centerInParent="true"></ImageView>
</RelativeLayout>