UI Thread stops running after random times - java

I've been having this issue for about a month now and I made a different question about it here: https://stackoverflow.com/questions/38005624/activity-stops-after-certain-time?noredirect=1#comment63454873_38005624
The issue appears to be a problem with the UI thread. After a seemingly random time of running, the UI thread appears to stop doing work. Any 'Runnable' objects passed to it with '.post()' or 'runOnUIThead()' do not get run. Even a simple log message. onClickListener objects also do not fire when the issue occurs. I've had runs where it starts happening within 2 seconds of starting, I've had runs where I make it through the entire game with no issue; all on the same code.
Here is my code if you need it:
The Activity:
package edu.rit.jacob.timeturner;
import android.app.ActivityManager;
import android.app.Application;
import android.app.Dialog;
import android.content.Intent;
import android.os.Looper;
import android.provider.ContactsContract;
import android.provider.Settings;
import android.support.annotation.StringRes;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Layout;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.PopupWindow;
import android.widget.ProgressBar;
import android.widget.SeekBar;
import android.widget.TextView;
public class UniverseActivity extends AppCompatActivity {
public static final String TAG = UniverseActivity.class.getSimpleName();
private UniverseThread thread;
public UniverseThread getThread(){ return thread; }
public static int SECTORS_HEIGHT = 3;
public static int SECTORS_WIDTH = 3;
private Galaxy player;
public Galaxy getPlayer() {
return player;
}
//components:
private UniverseView surfaceView;
private ImageView playerSprite;
private ImageView otherSprite;
private TextView testText;
private SeekBar speedBar;
private ProgressBar timebar;
//Pop ups
private Dialog infoPopUp;
private Dialog startScreen;
//other Galaxies
Galaxy[] galaxies = new Galaxy[SECTORS_HEIGHT * SECTORS_WIDTH];
#Override
protected void onCreate(Bundle savedInstanceState) {
//Setup Activity
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_universe);
Runnable init = new Runnable() {
#Override
public void run() {
initInfoPopUp();
initActivityComponents();
initPlayerAndSprites();
initOtherGalaxies();
initStartScreen();
}
};
runOnUiThread(init);
thread = new UniverseThread(surfaceView.getHolder(), surfaceView);
thread.setRunning(true);
thread.start();
startScreen.setTitle("The Beginning...");
startScreen.show();
Log.d(TAG, "App launched with " + ((ActivityManager)getSystemService(ACTIVITY_SERVICE)).getLargeMemoryClass() + "MB max");
}
#Override
protected void onDestroy() {
super.onDestroy();
boolean retry = true;
while(retry){
try{
thread.join();
retry = false;
}
catch (InterruptedException e){
//try again
}
}
}
private void initStartScreen(){
startScreen = new Dialog(this);
startScreen.setContentView(R.layout.new_game_start);
((TextView)startScreen.findViewById(R.id.textView4)).setText(getString(R.string.start_game_info));
startScreen.findViewById(R.id.buttonStart).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
player.setName("" + ((EditText)startScreen.findViewById(R.id.editText)).getText());
startScreen.dismiss();
}
});
}
private void initInfoPopUp(){
infoPopUp = new Dialog(this);
infoPopUp.setContentView(R.layout.info_popup);
Button infoOption1 = (Button) infoPopUp.findViewById(R.id.option1);
Button infoOption2 = (Button) infoPopUp.findViewById(R.id.option2);
infoOption1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d(TAG, "Option 1 clicked");
//player.incrementGas(galaxies[player.getSector() - 1].getGas());
player.merge(galaxies[player.getSector() - 1], true);
galaxies[player.getSector() - 1] = null;
infoPopUp.dismiss();
}
});
infoOption2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d(TAG, "Option 2 clicked");
//player.incrementGas(galaxies[player.getSector() - 1].getGas() / 2);
//galaxies[player.getSector() - 1].incrementGas(-galaxies[player.getSector() - 1].getGas() / 2);
player.merge(galaxies[player.getSector() - 1], false);
infoPopUp.dismiss();
}
});
}
private void initActivityComponents(){
surfaceView = (UniverseView) findViewById(R.id.surfaceView);
testText = (TextView) findViewById(R.id.testText);
speedBar = ((SeekBar)findViewById(R.id.seekBar));
timebar = ((ProgressBar)findViewById(R.id.progressBar));
}
private void initPlayerAndSprites(){
playerSprite = (ImageView) findViewById(R.id.playerGalaxy);
player = new Galaxy("Milky Way", true, new Velocity(), playerSprite, 25.0f, 1, this);
otherSprite = (ImageView) findViewById(R.id.otherGalaxy);
//Tapping on player galaxy
playerSprite.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d(TAG, "Player sprite clicked, stopping time and bringing up window...");
speedBar.setProgress(0);
infoPopUp.setTitle(player.getName());
infoPopUp.findViewById(R.id.infoPicture).setBackgroundResource(R.drawable.random_temp_galaxy_01);
infoPopUp.findViewById(R.id.option1).setVisibility(View.INVISIBLE);
infoPopUp.findViewById(R.id.option2).setVisibility(View.INVISIBLE);
((TextView)infoPopUp.findViewById(R.id.infoText)).setText(player.toString());
infoPopUp.show();
}
});
//Tapping on other galaxy
otherSprite.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(otherSprite.getVisibility() == View.VISIBLE){
Log.d(TAG, "Other sprite clicked, stopping time and bringing up window...");
speedBar.setProgress(0);
infoPopUp.setTitle(galaxies[player.getSector() - 1].getName());
infoPopUp.findViewById(R.id.infoPicture).setBackgroundResource(R.drawable.random_temp_galaxy_01);
infoPopUp.findViewById(R.id.option1).setVisibility(View.INVISIBLE);
infoPopUp.findViewById(R.id.option2).setVisibility(View.INVISIBLE);
((TextView)infoPopUp.findViewById(R.id.infoText)).setText(galaxies[player.getSector() - 1].toString());
infoPopUp.show();
}
}
});
}
private void initOtherGalaxies(){
for(Galaxy g: galaxies) g = null;
int i = 0, galaxiesNum = 0;
Log.d(TAG, "Populating the universe...");
while(i < galaxies.length){
double rand = Math.random();
if(rand <= 0.25){
galaxies[i] = new Galaxy("Random galaxy", new Velocity(0,0), otherSprite, 25.0f, i + 1, (Math.random()), this);
galaxiesNum += 1;
}
i += 1;
}
Log.d(TAG, "Universe populated with " + galaxiesNum + " galaxies.");
}
public int getSpeed(){
return speedBar.getProgress();
}
public void setTimeProgress(int progress){
try {
if (timebar.getProgress() != progress) {
switch (progress) {
case 10:
//((ProgressBar) findViewById(R.id.progressBar)).getProgress()
progress += 1;
//bring up new popup
break;
case 50:
//do stuff
break;
case 100:
//do end game stuff
boolean retry = true;
while (retry) {
try {
thread.join();
retry = false;
} catch (InterruptedException e) {
//try again
}
}
}
timebar.setProgress(progress);
}
}
catch (NullPointerException e){
Log.d(TAG, "Failed to grab progressBar");
e.printStackTrace();
}
}
public void changeBackground(){
Runnable changeBackground = new Runnable() {
#Override
public void run() {
//Set new background
Log.d(TAG, "Changing to background " + player.getSector());
//surfaceView.setBackgroundResource(R.drawable.background01 + (player.getSector() - 1));
testText.setText("Sector: " + player.getSector());
//Check for other galaxy
if(galaxies[player.getSector() - 1] != null){
otherSprite.setVisibility(View.VISIBLE);
}
else{
otherSprite.setVisibility(View.INVISIBLE);
}
synchronized (this) {
this.notify();
}
}
};
Log.d(TAG, "Passing background runnable to the UI thread");
synchronized (changeBackground){
runOnUiThread(changeBackground);
try {
changeBackground.wait();
}
catch (InterruptedException e){
e.printStackTrace();
}
}
}
public void checkForCollision(){
if(playerSprite.getX() + (playerSprite.getWidth() / 2) >= otherSprite.getX() &&
playerSprite.getX() + (playerSprite.getWidth() / 2) <= otherSprite.getX() + otherSprite.getWidth() &&
playerSprite.getY() + (playerSprite.getHeight() / 2) >= otherSprite.getY() &&
playerSprite.getY() + (playerSprite.getHeight() / 2) <= otherSprite.getY() + otherSprite.getHeight()){
if(otherSprite.getVisibility() == View.VISIBLE){
//switch (player.)
Runnable collide = new Runnable() {
#Override
public void run() {
speedBar.setProgress(0);
otherSprite.setVisibility(View.INVISIBLE);
((TextView)infoPopUp.findViewById(R.id.infoText)).setText("");
//infoPopUp.findViewById(R.id.infoPicture).setBackgroundResource(R.drawable.hubble_merger_01);
infoPopUp.findViewById(R.id.option1).setVisibility(View.VISIBLE);
infoPopUp.findViewById(R.id.option2).setVisibility(View.VISIBLE);
infoPopUp.setTitle("Incoming!");
infoPopUp.show();
}
};
runOnUiThread(collide);
}
}
//Set gauge
Runnable setGauge = new Runnable() {
#Override
public void run() {
((GaugeView)findViewById(R.id.gaugeView)).setTargetValue(player.getGas());
}
};
runOnUiThread(setGauge);
}
}
The Thread:
package edu.rit.jacob.timeturner;
import android.content.Context;
import android.graphics.Canvas;
import android.hardware.*;
import android.hardware.SensorManager;
import android.provider.Settings;
import android.util.Log;
import android.view.SurfaceHolder;
import android.widget.ImageView;
public class UniverseThread extends Thread {
public static final String TAG = UniverseThread.class.getSimpleName();
private double time;
public double getTime(){
return time;
}
private double speed;
public double getSpeed(){
return speed;
}
private boolean running;
public void setRunning(boolean running){
this.running = running;
}
public boolean isRunning(){
return running;
}
//Reference to the UniverseActivity
private SurfaceHolder surfaceHolder;
//Reference to the UniverseView that is the background
private UniverseView universeView;
public UniverseThread(SurfaceHolder surfaceHolder, UniverseView universeView){
super();
this.surfaceHolder = surfaceHolder;
this.universeView = universeView;
running = false;
time = 0;
}
public static float x = 0, y = 0, z = 0;
#Override
public void run(){
Log.d(TAG, "Starting Game Loop");
time = 0.0;
speed = 0.0;
//SensorManager gets SENSOR_SERVICE from android
//Accesses gravity sensor
SensorManager sm = (SensorManager) this.universeView.getContext().getSystemService(Context.SENSOR_SERVICE);
sm.registerListener(new SensorEventListener() {
#Override
public void onSensorChanged(SensorEvent event) {
x = event.values[0];
y = event.values[1];
z = event.values[2];
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}, sm.getDefaultSensor(Sensor.TYPE_GRAVITY), SensorManager.SENSOR_DELAY_GAME);
//save player, velocity, and sprite
Galaxy player = ((UniverseActivity)universeView.getContext()).getPlayer();
Velocity vel = player.getVel();
ImageView sprite = player.getSprite();
boolean changeBackground;
float timesRun = 0f;
while(running){
//every 16 milliseconds (~60 Hz)
timesRun += 1;
final String testStr = "Thread has run for " + (timesRun) + " frames.";
Runnable test = new Runnable() {
#Override
public void run() {
Log.d(TAG, testStr);
}
};
if(timesRun % 60 == 0) ((UniverseActivity) universeView.getContext()).runOnUiThread(test);
//increment the time
speed = ((UniverseActivity)universeView.getContext()).getSpeed();
time += (speed / 7200.0);
((UniverseActivity)universeView.getContext()).setTimeProgress((int) time);
//update player's velocity
((UniverseActivity)universeView.getContext()).getPlayer().getVel().incrementXV(-x / 9.81f);
((UniverseActivity)universeView.getContext()).getPlayer().getVel().incrementYV(y / 9.81f);
//update player's position
//move sprite
sprite.setX((float)(sprite.getX() + (vel.getxV() * speed / 400)));
sprite.setY((float)(sprite.getY() + (vel.getyV() * speed / 400)));
changeBackground = false;
//bottom -> top
if (sprite.getY() + (sprite.getHeight() / 2) > universeView.getHeight()) {
sprite.setY(0 - (sprite.getHeight() / 2));
sprite.setX(universeView.getWidth() / 2);
player.updateSector("BOTTOM");
changeBackground = true;
}
//right -> left
if (sprite.getX() + (sprite.getWidth() / 2) > universeView.getWidth()) {
sprite.setY(universeView.getHeight() / 2);
sprite.setX(0 - (sprite.getWidth() / 2));
player.updateSector("RIGHT");
changeBackground = true;
}
//top -> bottom
if (sprite.getY() + (sprite.getHeight() / 2) < 0) {
sprite.setY(universeView.getHeight() - (sprite.getHeight() / 2));
sprite.setX(universeView.getWidth() / 2);
player.updateSector("TOP");
changeBackground = true;
}
//left -> right
if (sprite.getX() + (sprite.getWidth() / 2) < 0) {
sprite.setY(universeView.getHeight() / 2);
sprite.setX(universeView.getWidth() - (sprite.getWidth() / 2));
player.updateSector("LEFT");
changeBackground = true;
}
if(changeBackground)
{((UniverseActivity)universeView.getContext()).changeBackground();}
((UniverseActivity)universeView.getContext()).checkForCollision();
try{
this.sleep(16L);
}
catch (InterruptedException e){
e.printStackTrace();
}
}
Log.d(TAG, "Game Loop terminated");
}
}
To be clear, no exceptions or errors are being thrown during runtime. The only messages in logcat are my own and the system messages for registering a click, for example. The application does not crash and the sprite is still perfectly controllable. The main things that do not work is the changing of backgrounds, checking for a collision, and the onClickListeners.
Has anyone run into something like this before? Any help would be appreciated.

So after having narrowed the problem down to the Runnable objects I was passing to the UI thread, I took steps to minimize the amount of time I called runOnUIThread() at first it didn't seem to have any effect but eventually I stopped having this problem and that's the only thing I can contribute it to. I might eventually do some more testing to be more concrete that that was the problem and respective solution.

Related

How to solve stack memory problems?

iam trying to build an android app which makes users to do some calculation in a time limit. The code worked well until i divided the code into two parts and created another class for doing other task .
I have imported all the corressponding packages and class files to the new class .There were no errors in the code but when i run the app it crashes .I tried changing the code many times but no use. Code works well when i combine all the code into a single class.
the error i get is "java.lang.StackOverflowError: stack size 8MB on line number "
**MainActivity.java**
package e.nani.firstattempt;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Vibrator;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import java.util.Random;
public class MainActivity extends AppCompatActivity {
public int a1;//random num 1
public int a2;//random num 2;
public TextView textview;
public Button b1;
public Button b2;
public Button b3;
public Button b4;
public int option1;
public int option2;
public int option3;
public int option4;
public int score=0;
TextView scoreid;
int numberofquestions=10;
TextView time;
public int answers[]=new int[4];
Logic c=new Logic();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textview=(TextView)findViewById(R.id.sum);
b1=(Button)findViewById(R.id.option1);
b2=(Button)findViewById(R.id.option2);
b3=(Button)findViewById(R.id.option3);
b4=(Button)findViewById(R.id.option4);
time=(TextView)findViewById(R.id.timer);
scoreid=(TextView)findViewById(R.id.scoreid) ;
scoreid.setText((0+"/"+numberofquestions));
c.operatio();
timer.start();
}
public void operation(View V)
{
try{
switch(V.getId()) {
case R.id.option1:
if (b1.getText().equals(Integer.toString(option4))) {
score = score + 1;
c.operatio();
scoreid.setText((score +"/"+ numberofquestions));
} else {
Toast.makeText(this, "wrong answer", Toast.LENGTH_SHORT).show();
Vibrator vibrator=(Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(500);
c.operatio();
}
break;
case R.id.option2:
if (b2.getText().equals(Integer.toString(option4))) {
score = score + 1;
c.operatio();
scoreid.setText(score+"/"+ numberofquestions);
} else
{
Toast.makeText(this, "wrong answer", Toast.LENGTH_SHORT).show();
Vibrator vibrator=(Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(500);
c.operatio();
}
break;
case R.id.option3:
if (b3.getText().equals(Integer.toString(option4))) {
score = score + 1;
c.operatio();
scoreid.setText((score+"/"+ numberofquestions));
} else
{
Toast.makeText(this, "wrong answer", Toast.LENGTH_SHORT).show();
Vibrator vibrator=(Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(500);
c.operatio();
}
break;
case R.id.option4:
if (b4.getText().equals(Integer.toString(option4))) {
score = score + 1;
c.operatio();
scoreid.setText(score+"/"+ numberofquestions);
} else
{
Toast.makeText(this, "wrong answer", Toast.LENGTH_SHORT).show();
Vibrator vibrator=(Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(500);
c.operatio();
}
break;
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
CountDownTimer timer=new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
time.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
time.setText("done!");
}
};
}
Logic.java
package e.nani.firstattempt;
import java.util.Random;
class Logic {
MainActivity s=new MainActivity();
public void operatio() {
try {
Random n = new Random();
int n1 = n.nextInt(4);
int n2 = n.nextInt(4);
int n3 = n.nextInt(4);
int n4 = n.nextInt(4);
s.a1 = n.nextInt(51);
s.a2 = n.nextInt(35);
s.option1 = n.nextInt((s.a1 + s.a2) + 1);
s.option2 = n.nextInt((s.a1 + s.a2) + 1);
s.option3 = n.nextInt((s.a1 + s.a2) + 1);
s.option4 = s.a1 + s.a2;
s.answers[n1] = s.option1;
while (n2 == n1) {
n2 = n.nextInt(4);
}
while (s.option2 == s.option1 || s.option2 == s.option4) {
s.option2 = n.nextInt((s.a1 + s.a2) + 1);
}
s.answers[n2] = s.option2;
while (s.option3 == s.option2 || s.option3 == s.option1 || s.option3 == s.option4)
{
s.option3 = n.nextInt((s.a1 + s.a2) + 1);
}
while (n3 == n2 || n3 == n1)
{
n3 = n.nextInt(4);
}
s.answers[n3] = s.option3;
while (n4 == n2 || n4 == n1 || n4 == n3) {
n4 = n.nextInt(4);
}
s.answers[n4] = s.option4;
s.b1.setText(Integer.toString(s.answers[0]));
s.b2.setText(Integer.toString(s.answers[1]));
s.b3.setText(Integer.toString(s.answers[2]));
s.b4.setText(Integer.toString(s.answers[3]));
s.textview.setText(s.a1 + "+" + s.a2);
} catch (Exception e) {
e.printStackTrace();
}
}
}
The main question here is ,why is the app working fine when the code is only in main class but not working when some code is written in other class ?
ThankYou.
In your MainActivity you have a variable c with type Logic which is instantiated.
But in your Logic class has MainActivity type variable which try to instantiate MainActivity class. In a nutshell in a class A you instantiate class B which instatieates class A and so on...
By the way you cannot instantiate AppCompatActivity classes directly.
So remove MainActivity s=new MainActivity(); in your Logic.class.
Hope I could help you.

textureview is not updating after coming back from another activity in onResume

I am trying to play some rtsp video on custom textureview.Video is playing for the first time but when I go to second activity where the same video is played (not reinstantiated,same session but with different textureview) there it is playing and coming back to first activity where I am setting the sureface again in onResume textureview is still showing the content where it was left for the first time.Interesting fact is like video is still playing, just it is not visible in the textureview and if I go to second screen like before it is showing.I tried both releasing the surfacetexture and not releasing, tried also releasing the surface which I am holding a reference in the first activity for future use, not any of those seems to work.What can be the possible reason?
in onResume I am checking if app is coming back from app drawer or full screen activity.Where making the app go to background by clicking home button and coming back to app from app drawer video is playing.Only when coming back from full screen it's not working.
StreamingActivity.java
package com.wiznsystems.android.activities;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.SurfaceTexture;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.TextureView;
import android.view.View;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ProgressBar;
import android.widget.Toast;
import com.myeglu.android.R;
import com.myeglu.zoomview.ZoomTextureView;
import com.wiznsystems.android.App;
import com.wiznsystems.android.data.objects.FFMPEG;
import com.wiznsystems.android.utils.Constants;
import com.wiznsystems.android.utils.Events;
import com.wiznsystems.android.utils.FFMPEGPlayer;
import java.io.File;
import de.greenrobot.event.EventBus;
import hugo.weaving.DebugLog;
import timber.log.Timber;
/**
* An example full-screen activity that shows and hides the system UI (i.e.
* status bar and navigation/system bar) with user interaction.
*/
#SuppressWarnings("JniMissingFunction")
public class StreamingActivity extends Fragment implements TextureView.SurfaceTextureListener{
private static boolean loadedLibraries;
private boolean comingFromAppDrawer;
private boolean isComingFromFullScreen;
boolean anotherVideo=false;
boolean shouldTextureUpdate=false;
Surface surface;
public StreamingActivity(){
}
public static ZoomTextureView surfaceView;
private ProgressBar progressBar;
public static boolean isPlaying;
private int isInitialized;
public static int isFullScreenDisplayed=0;
private String url;
public boolean isFirstTime;
private FFMPEG ffmpeg;
private FrameLayout frameLayout;
private final String TAG=StreamingActivity.class.getSimpleName();
int w=0,h=0;
private boolean isFirstTimeForFullscreen=true;
private Button fullScreenButton;
FFMPEGPlayer ffmpegPlayer;
String buttonText="";
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EventBus.getDefault().register(this);
url=getArguments().getString("url");
Log.d("ANURAN",url);
//getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
ffmpegPlayer=App.getFFMPEG();
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.activity_streaming,null,false);
surfaceView = (ZoomTextureView) view.findViewById(R.id.textureView);
frameLayout=(FrameLayout)view.findViewById(R.id.streaming_framelayout);
progressBar = ((ProgressBar)view.findViewById(R.id.progressBar));
fullScreenButton=(Button)view.findViewById(R.id.fullScreenButton);
fullScreenButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
isFullScreenDisplayed = 1;
isComingFromFullScreen = true;
shouldTextureUpdate=true;
if (isFirstTimeForFullscreen) {
//ffmpegPlayer.libSetSurface(null);
isFirstTimeForFullscreen = false;
}
//surfaceView.getSurfaceTexture().release();
//surface.release();
progressBar.setVisibility(View.INVISIBLE);
goFullScreen();
} catch (Exception throwable) {
throwable.printStackTrace();
}
}
});
progressBar.setVisibility(View.VISIBLE);
Log.d("ANURAN","onCreateView called");
surfaceView.setSurfaceTextureListener(this);
return view;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//Log.d(TAG,url);
}
#DebugLog
private void postInit() {
Events.PlayButtonBGChanger playButtonBGChanger=new Events.PlayButtonBGChanger();
if (isInitialized==0) {
playButtonBGChanger.setShouldChange(true);
initPlay();
progressBar.setVisibility(View.GONE);
} else if(isInitialized==-999){
playButtonBGChanger.setShouldChange(false);
progressBar.setVisibility(View.INVISIBLE);
Snackbar.make(frameLayout,"Please make sure you have stopped other playing videos before playing this one.",Snackbar.LENGTH_LONG).show();
}
else {
playButtonBGChanger.setShouldChange(false);
Snackbar.make(frameLayout,"Something went wrong while live streaming.Please try again later.",Snackbar.LENGTH_LONG).show();
}
EventBus.getDefault().post(playButtonBGChanger);
}
private void initPlay() {
try {
int[] res = ffmpegPlayer.libGetVideoRes();
Log.d("ANURAN", "res width " + res[0] + ": height " + res[1]);
if (res[0] <= 0) {
res[0] = 480;
}
if (res[1] <= 0) {
res[1] = 320;
}
int[] screenRes = getScreenRes();
int width, height;
float widthScaledRatio = screenRes[0] * 1.0f / res[0];
float heightScaledRatio = screenRes[1] * 1.0f / res[1];
if (widthScaledRatio > heightScaledRatio) {
//use heightScaledRatio
width = (int) (res[0] * heightScaledRatio);
height = screenRes[1];
} else {
//use widthScaledRatio
width = screenRes[0];
height = (int) (res[1] * widthScaledRatio);
}
Log.d(TAG, "width " + width + ",height:" + height);
w=width;
h=height;
updateSurfaceView(width, height);
try{
ffmpegPlayer.libSetup(width,height);
if(this.surface == null){
Log.d("ANURAN","surface is null");
}
if(anotherVideo)
ffmpegPlayer.libSetSurface(null);
ffmpegPlayer.libSetSurface(surface);
Log.d("ANURAN","libsetsurface set initPlay()");
}catch (Exception throwable){
Toast.makeText(getActivity(),"Something went wrong while live streaming.Try again",Toast.LENGTH_SHORT).show();
}
playMedia();
}catch (Exception throwable){
throwable.printStackTrace();
}
}
public FFMPEGPlayer getFFMPEGPlayer(){
return this.ffmpegPlayer;
}
private void playMedia() {
if(progressBar.getVisibility()==View.VISIBLE){
progressBar.setVisibility(View.GONE);
}
try{
ffmpegPlayer.libPlay();
}catch (Exception throwable){
Toast.makeText(getActivity(),"Something went wrong while live streaming.Try again",Toast.LENGTH_SHORT).show();
}
isPlaying = true;
CamerasActivity.isPlaying=true;
}
#DebugLog
private void updateSurfaceView(int pWidth, int pHeight) {
//update surfaceview dimension, this will cause the native window to change
Log.d("ANURAN UPDATE SURFACE", "width " + pWidth + ",height:" + pHeight);
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) surfaceView.getLayoutParams();
params.width = pWidth;
params.height = pHeight;
surfaceView.setLayoutParams(params);
surfaceView.requestLayout();
}
#DebugLog
#SuppressLint("NewApi")
private int[] getScreenRes() {
int[] res = new int[2];
Display display = getActivity().getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
res[0] = size.x;
res[1] = size.y;
return res;
}
public void stopPlaying() {
isPlaying = false;
try{
ffmpegPlayer.libStop();
// ffmpegPlayer.libSetSurface(null);
// surfaceView.getSurfaceTexture().release();
// surfaceView.getSurfaceTexture().detachFromGLContext();
}catch (Exception throwable){
}
}
#Override
public void onStop() {
// Toast.makeText(getActivity(),"onStop called",Toast.LENGTH_SHORT).show();
// stopPlaying();
comingFromAppDrawer=true;
// if(surfaceView.getSurfaceTexture() !=null){
// surfaceView.getSurfaceTexture().release();
//
// }
// if(surface !=null){
// surface.release();
// surface=null;
// }
// if(isFullScreenDisplayed==0){
// stopPlaying();
// }
Log.d("ANURAN onStop",surface.isValid()+"");
super.onStop();
}
#Override
public void onPause() {
// Toast.makeText(getActivity(),"onStop called",Toast.LENGTH_SHORT).show();
// stopPlaying();
isComingFromFullScreen=true;
super.onPause();
}
#Override
public void onResume() {
super.onResume();
if(isComingFromFullScreen){
progressBar.setVisibility(View.INVISIBLE);
if(surface !=null){
ffmpegPlayer.libSetSurface(null);
Log.d("ANURAN onResume","value of surface "+surface.isValid());
ffmpegPlayer.libSetSurface(surface);
}
}
else if(comingFromAppDrawer){
//stopPlaying();
progressBar.setVisibility(View.INVISIBLE);
if(surface !=null){
ffmpegPlayer.libSetSurface(null);
//ffmpegPlayer.libSetup(w,h);
ffmpegPlayer.libSetSurface(surface);
}
}
}
#Override
public void onDestroy() {
super.onDestroy();
stopPlaying();
}
#Override
public void onStart() {
super.onStart();
}
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
if(this.surface !=null) {
this.surface.release();
this.surface=null;
}
this.surface=new Surface(surface);
Log.d("ANURAN","surfacetexture available streaming activity");
new PlayVideo().execute();
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
Log.d("ANURAN","surfacetexturesize changed streaming activity");
try{
w=width;
h=height;
this.surface.release();
this.surface=null;
this.surface=new Surface(surface);
if(isComingFromFullScreen){
//surfaceView.getHolder().getSurface().release();
updateSurfaceView(width, height);
ffmpegPlayer.libSetup(width,height);
ffmpegPlayer.libSetSurface(this.surface);
}
}catch (Exception throwable){
Toast.makeText(getActivity(),"Something went wrong while live streaming.Try again",Toast.LENGTH_SHORT).show();
}
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
Log.d("ANURAN","surfacetexture destroyed streaming activity");
// surfaceView.getSurfaceTexture().release();
// if(this.surface !=null){
// this.surface.release();
// this.surface=null;
// }
return false;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
Log.d("ANURAN","surfacetexture updated streaming activity");
if(this.surface !=null){
this.surface.release();
this.surface=null;
this.surface=new Surface(surface);
}else{
this.surface=new Surface(surface);
}
}
public class PlayVideo extends AsyncTask<Void,Void,Void>{
#Override
protected Void doInBackground(Void... voids) {
try{
isInitialized=ffmpegPlayer.libInit(url);
}catch (Exception e){
e.printStackTrace();
Snackbar.make(frameLayout,"Exception Occured",Snackbar.LENGTH_SHORT).show();
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
isFirstTime=false;
postInit();
this.cancel(true);
}
}
public void onEvent(FFMPEG ffmpeg){
url = ffmpeg.getUrl();
progressBar.setVisibility(View.VISIBLE);
//stopPlaying();
anotherVideo=true;
new PlayVideo().execute();
}
public void onEvent(Events.UpdateUrl newurl){
url=newurl.getUrl();
}
public void onEvent(Events.StopPlayback event){
stopPlaying();
}
public void onEvent(Events.NotifyPlayer notifyPlayer){
Snackbar.make(frameLayout,"Please stop any running video before playing another one",Toast.LENGTH_SHORT).show();
}
private void goFullScreen(){
Intent intent=new Intent(getContext(),FullScreenActivity.class);
Bundle bundle=new Bundle();
bundle.putString("url",url);
intent.putExtras(bundle);
getActivity().startActivity(intent);
}
}
FullScreenActivity.java
package com.wiznsystems.android.activities;
import android.annotation.SuppressLint;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.RectF;
import android.graphics.SurfaceTexture;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Display;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.Toast;
import com.myeglu.android.R;
import com.myeglu.zoomview.AngleView;
import com.myeglu.zoomview.MatrixChangeListener;
import com.myeglu.zoomview.ZoomTextureView;
import com.wiznsystems.android.App;
import com.wiznsystems.android.data.objects.FFMPEG;
import com.wiznsystems.android.utils.FFMPEGPlayer;
import uk.copywitchshame.senab.photoview.gestures.PhotoViewAttacher;
import hugo.weaving.DebugLog;
/**
* Created by anuran on 9/3/18.
*/
#SuppressWarnings("JniMissingFunction")
public class FullScreenActivity extends AppCompatActivity implements TextureView.SurfaceTextureListener, PhotoViewAttacher.OnMatrixChangedListener {
private ZoomTextureView surfaceView;
public static AngleView angleView;
private ProgressBar progressBar;
private PhotoViewAttacher photoViewAttacher;
public static boolean isPlaying;
private boolean isInitialized;
private String url;
private FrameLayout frameLayout;
Surface surface;
private final String TAG=StreamingActivity.class.getSimpleName();
public int backCounter=0;
FFMPEGPlayer ffmpegPlayer;
boolean fromADorSL=false;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().requestFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_fullscreen);
surfaceView = (ZoomTextureView) findViewById(R.id.textureView);
angleView=(AngleView)findViewById(R.id.render_angle_view);
surfaceView.setSurfaceTextureListener(this);
frameLayout=(FrameLayout)findViewById(R.id.streaming_framelayout);
progressBar = ((ProgressBar)findViewById(R.id.progressBar));
progressBar.setVisibility(View.VISIBLE);
url=getIntent().getExtras().getString("url");
//new PlayVideo().execute();
ffmpegPlayer= App.getFFMPEG();
Log.d("ANURAN","fullscreen onCreate");
}
// #DebugLog
// private void postInit() {
// if (isInitialized) {
// initPlay();
// progressBar.setVisibility(View.GONE);
// } else {
// finish();
// }
// }
// private void initPlay() {
//
// try{
// int[] res = FFMPEGPlayer.libGetVideoRes();
// Log.d("ANURAN", "res width " + res[0] + ": height " + res[1]);
// if (res[0] <= 0) {
// res[0] = 480;
// }
// if (res[1] <= 0) {
// res[1] = 320;
// }
// int[] screenRes = getScreenRes();
// int width, height;
// float widthScaledRatio = screenRes[0] * 1.0f / res[0];
// float heightScaledRatio = screenRes[1] * 1.0f / res[1];
// if (widthScaledRatio > heightScaledRatio) {
// //use heightScaledRatio
// width = (int) (res[0] * heightScaledRatio);
// height = screenRes[1];
// } else {
// //use widthScaledRatio
// width = screenRes[0];
// height = (int) (res[1] * widthScaledRatio);
// }
// Log.d(TAG, "width " + width + ",height:" + height);
// updateSurfaceView(width, height);
// FFMPEGPlayer.libSetup(width, height);
// playMedia();
//
// photoViewAttacher = new PhotoViewAttacher(surfaceView, width, height);
// photoViewAttacher.setScaleType(ImageView.ScaleType.CENTER_CROP);
// photoViewAttacher.setOnMatrixChangeListener(this);
// photoViewAttacher.update();
// }catch (Exception e){
//
// }
// }
// private void playMedia() {
//
// try{
// if(progressBar.getVisibility()==View.VISIBLE){
// progressBar.setVisibility(View.GONE);
// }
// FFMPEGPlayer.libPlay();
// isPlaying = true;
// CamerasActivity.isPlaying=true;
// }catch (Exception e){
//
// }
// }
// #DebugLog
// private void updateSurfaceView(int pWidth, int pHeight) {
// //update surfaceview dimension, this will cause the native window to change
// Log.d("ANURAN UPDATE SURFACE", "width " + pWidth + ",height:" + pHeight);
// FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) surfaceView.getLayoutParams();
// params.width = pWidth;
// params.height = pHeight;
// surfaceView.setLayoutParams(params);
// }
#Override
public void onBackPressed() {
if(backCounter==1){
super.onBackPressed();
}else{
//surface.release();
StreamingActivity.isFullScreenDisplayed=0;
surfaceView.getSurfaceTexture().release();
//ffmpegPlayer.libSetSurface(null);
if(this.surface !=null){
this.surface.release();
this.surface=null;
}
backCounter++;
Toast.makeText(FullScreenActivity.this,"Press back again to quit full screen",Toast.LENGTH_SHORT).show();
}
}
#DebugLog
#SuppressLint("NewApi")
private int[] getScreenRes() {
int[] res = new int[2];
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
res[0] = size.x;
res[1] = size.y;
return res;
}
private void stopPlaying() {
isPlaying = false;
try{
ffmpegPlayer.libStop();
}catch (Exception e){
}
}
#Override
public void onStop() {
super.onStop();
fromADorSL=true;
}
#Override
public void onResume() {
super.onResume();
if(fromADorSL){
ffmpegPlayer.libSetSurface(null);
ffmpegPlayer.libSetSurface(this.surface);
}
}
#Override
public void onStart() {
super.onStart();
}
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
//Toast.makeText(FullScreenActivity.this,"SurfaceTexture available",Toast.LENGTH_SHORT).show();
//updateSurfaceView(width, height);
try{
this.surface=new Surface(surface);
ffmpegPlayer.libSetup(width, height);
ffmpegPlayer.libSetSurface(this.surface);
photoViewAttacher = new PhotoViewAttacher(surfaceView, width, height);
photoViewAttacher.setScaleType(ImageView.ScaleType.CENTER_CROP);
photoViewAttacher.setOnMatrixChangeListener(this);
photoViewAttacher.update();
progressBar.setVisibility(View.INVISIBLE);
angleView.setVisibility(View.VISIBLE);
}catch (Exception e){
}
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
try{
Toast.makeText(FullScreenActivity.this,"SurfaceTexture changed",Toast.LENGTH_SHORT).show();
if (photoViewAttacher != null ) {
photoViewAttacher.update ();
}
if(this.surface !=null){
this.surface.release();
}
this.surface=null;
this.surface=new Surface(surface);
ffmpegPlayer.libSetup(width,height);
ffmpegPlayer.libSetSurface(this.surface);
}catch (Exception e){
}
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
try{
// this.surface.release();
// this.surface=null;
surfaceView.getSurfaceTexture().release();
if(this.surface !=null){
this.surface.release();
this.surface=null;
}
//ffmpegPlayer.libSetSurface(null);
}catch (Exception e){
}
return true;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
if(this.surface !=null){
this.surface.release();
this.surface=null;
this.surface=new Surface(surface);
}
}
#Override
public void onMatrixChanged(Matrix matrix, RectF rectF) {
float maxMovement = (rectF.width() - surfaceView.getWidth());
float middle = surfaceView.getWidth() * 0.5f + surfaceView.getLeft();
float currentMiddle = rectF.width() * 0.5f + rectF.left;
float angle=(-(int) ((currentMiddle - middle) * 100 / maxMovement));
Log.d("ANURAN",angle+"");
angleView.setCurrentProgress((int)angle);
}
// public class PlayVideo extends AsyncTask<Void,Void,Void> {
//
// #Override
// protected Void doInBackground(Void... voids) {
// try{
// isInitialized=(FFMPEGPlayer.libInit(url)==0);
// }catch (Exception e){
// e.printStackTrace();
// }
// return null;
// }
//
// #Override
// protected void onPostExecute(Void aVoid) {
// super.onPostExecute(aVoid);
// postInit();
// this.cancel(true);
// }
// }
}

Why does this code loop around with "Socket setup caught IOexception"

I am trying to troubleshoot an Android server/client set of software which appears to be logging vast amounts of logcat messages containing "Socket setup caught IOexception", so Im guessing its in a loop.
For troubleshooting purposes I installed the server and client on the same physical device and experience the same problem.
Reading the code I cant work out why this would be, I have added comments starting //STACKEXCHANGE where I see the three logcat messages getting logged. Could anyone give me some pointers, Im not a java programmer, just an enthusiastic techie trying to get this working..
The logcat logs the messages in the following order
ControlLooop starting
Socket setup caught IOexception
Socket Established
Socket Closing
controlLoopEnding
And here is the code for the client software.
package com.jrbowling.robotclient;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.util.Log;
import android.widget.ToggleButton;
import android.widget.SeekBar;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.Toast;
import android.widget.EditText;
import android.widget.ImageView;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.view.Window;
import android.view.WindowManager;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.net.SocketTimeoutException;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.WifiLock;
import android.net.wifi.WifiInfo;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.view.View.OnTouchListener;
import android.view.MotionEvent;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.net.SocketTimeoutException;
import android.app.AlertDialog;
import android.content.DialogInterface;
import java.net.SocketAddress;
import java.net.InetSocketAddress;
import android.os.Handler;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
public class MainActivity extends Activity {
Thread vidThread = null;
Thread clientThread = null;
private Socket s;
private static final String TAG = "RobotClient";
//private ToggleButton tb;
private ImageButton forward_button;
private ImageButton reverse_button;
private ImageButton right_button;
private ImageButton left_button;
private SeekBar throttle;
private ImageView imageWindow;
private ImageView connectedLED;
private ImageView signalStrengthIndicator;
private Boolean stayConnected = false;
String vidURL = "";
private String robotIP = "";
String direction = "stop";
Integer speed = 100;
Boolean robotEnabled = true;
Boolean robotConnected = false;
private Handler GUIUpdateHandler = new Handler();
private Integer signalStrength = 0;
private SharedPreferences pref;
private long timeLastPress = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//set fullscreeen, black
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_main);
setActivityBackgroundColor(0xff000000);
Log.i(TAG, "Robot client started");
initGUIComponents();
//get Robot IP from user, kick off threads and GUI updater
showIPAlert();
}
#Override
protected void onDestroy() {
Log.d(TAG,"onDestroy() called");
stayConnected = false;
socketCleanup();
super.onDestroy();
}
//#Override
//protected void onPause() {
// Log.d(TAG,"onPause() called");
// stayConnected = false;
// socketCleanup();
// super.onDestroy();
// }
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public void onBackPressed() {
//on back button, prompt user to press it again within 2 seconds to exit
Toast onBackPressedToast = Toast.makeText(this, "Press again within 2 seconds to confirm exit", Toast.LENGTH_SHORT);
long currentTime = System.currentTimeMillis();
if (currentTime - timeLastPress > 2000) {
onBackPressedToast.show();
timeLastPress = currentTime;
} else {
onBackPressedToast.cancel();
super.onBackPressed();
}
}
private void initGUIComponents()
{
imageWindow = (ImageView) findViewById(R.id.imageView1);
connectedLED = (ImageView) findViewById(R.id.imageViewConnectStatus);
signalStrengthIndicator = (ImageView) findViewById(R.id.ImageViewSignalStrength);
forward_button = (ImageButton) findViewById(R.id.forwardButton);
reverse_button = (ImageButton) findViewById(R.id.reverseButton);
right_button = (ImageButton) findViewById(R.id.rightButton);
left_button = (ImageButton) findViewById(R.id.leftButton);
throttle = (SeekBar)findViewById(R.id.throttleSeekbar);
throttle.setProgress(75);
forward_button.setOnTouchListener(forwardButtonListener);
reverse_button.setOnTouchListener(reverseButtonListener);
right_button.setOnTouchListener(rightButtonListener);
left_button.setOnTouchListener(leftButtonListener);
}
private void showIPAlert() {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("Please enter robot IP address");
alert.setMessage("Example: 192.168.1.100");
final EditText input = new EditText(this);
alert.setView(input);
input.setText(loadIP().toString());
alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
robotIP = input.getText().toString();
Log.i(TAG, "User entered IP " + robotIP);
saveIP(robotIP);
//Handler launches GUIUpdater every 1000 ms. Launch when user clicks ok.
updateGUI();
//start network thread
stayConnected = true;
//launch network thread
clientThread = new Thread(new ClientThread());
clientThread.start();
vidURL = "http://"+robotIP+":8082/shot.jpg";
vidLoop();
}
});
alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
appExit();
}
});
alert.show();
}
private void appExit()
{
Log.i(TAG, "Exit requested by user");
this.finish();
}
private OnTouchListener forwardButtonListener = new OnTouchListener(){
public boolean onTouch(View v, MotionEvent event) {
switch ( event.getAction() ) {
case MotionEvent.ACTION_DOWN:
//setActivityBackgroundColor(0xffff0000);
direction = "forward";
break;
case MotionEvent.ACTION_UP:
//setActivityBackgroundColor(0xff000000);
direction = "stop";
break;
}
return false;
}
};
private OnTouchListener reverseButtonListener = new OnTouchListener(){
public boolean onTouch(View v, MotionEvent event) {
switch ( event.getAction() ) {
case MotionEvent.ACTION_DOWN:
//setActivityBackgroundColor(0xffff0000);
direction = "reverse";
break;
case MotionEvent.ACTION_UP:
//setActivityBackgroundColor(0xff000000);
direction = "stop";
break;
}
return false;
}
};
private OnTouchListener rightButtonListener = new OnTouchListener(){
public boolean onTouch(View v, MotionEvent event) {
switch ( event.getAction() ) {
case MotionEvent.ACTION_DOWN:
//setActivityBackgroundColor(0xffff0000);
direction = "rotateRight";
break;
case MotionEvent.ACTION_UP:
//setActivityBackgroundColor(0xff000000);
direction = "stop";
break;
}
return false;
}
};
private OnTouchListener leftButtonListener = new OnTouchListener(){
public boolean onTouch(View v, MotionEvent event) {
switch ( event.getAction() ) {
case MotionEvent.ACTION_DOWN:
//setActivityBackgroundColor(0xffff0000);
direction = "rotateLeft";
break;
case MotionEvent.ACTION_UP:
//setActivityBackgroundColor(0xff000000);
direction = "stop";
break;
}
return false;
}
};
//save and retrieve IP address using the shared preferences framework
private void saveIP(String IP)
{
//set up shared preferences editor
pref = getApplicationContext().getSharedPreferences("RobotClient", 0);
Editor editor = pref.edit();
editor.putString("robotIP", IP);
editor.commit();
}
private String loadIP()
{
String result;
pref = getApplicationContext().getSharedPreferences("RobotClient", 0);
Editor editor = pref.edit();
result = pref.getString("robotIP", "10.20.30.43");
return result;
}
private void setActivityBackgroundColor(int color) {
//0xff00ff00 first two are transparency, then rgb
View view = this.getWindow().getDecorView();
view.setBackgroundColor(color);
}
//periodically run updater to set connection status and wifi signal strength from robot
private void updateGUI()
{
GUIUpdateHandler.postDelayed(GUIUpdater, 1000);
}
private Runnable GUIUpdater = new Runnable(){
public void run() {
//Periodically update GUI elements from sensor and other data
Log.d(TAG,"Connected is: " + robotConnected.toString());
//update connection status
if (robotConnected)
{
connectedLED.setImageResource(R.drawable.led_green);
//update the wifi signal strength indicator
if ((signalStrength == 5) || (signalStrength==4))
signalStrengthIndicator.setImageResource(R.drawable.wifi4);
if (signalStrength == 3)
signalStrengthIndicator.setImageResource(R.drawable.wifi3);
if (signalStrength == 2)
signalStrengthIndicator.setImageResource(R.drawable.wifi2);
if (signalStrength == 1)
signalStrengthIndicator.setImageResource(R.drawable.wifi1);
if (signalStrength == 0)
signalStrengthIndicator.setImageResource(R.drawable.wifi0);
}
else
{
connectedLED.setImageResource(R.drawable.led_red);
signalStrengthIndicator.setImageResource(R.drawable.wifi0);
}
if (stayConnected)
updateGUI();
}
};
public void setConnected(boolean connected) {
robotConnected = connected;
}
public void socketCleanup()
{
try {
Log.d("clientThread","Socket Closing");
if (s != null)
s.close();
setConnected(false);
} catch (IOException e) {
Log.d(TAG, "Client comm thread got IOException in socketCleanup().");
}
}
private void vidLoop() //started from GUI alert, then kept going with call me from asynctask
{
if (stayConnected)
{
ImageDownloader id = new ImageDownloader();
id.execute(vidURL);
}
}
//this very useful chunk of code is from http://www.peachpit.com/articles/article.aspx?p=1823692&seqNum=3
private class ImageDownloader extends AsyncTask<String, Integer, Bitmap>{
protected void onPreExecute(){
}
#Override
protected Bitmap doInBackground(String... params) {
//TODO Auto-generated method stub
try{
URL url = new URL(params[0]);
HttpURLConnection httpCon =
(HttpURLConnection)url.openConnection();
if(httpCon.getResponseCode() != 200)
throw new Exception("Failed to connect");
InputStream is = httpCon.getInputStream();
return BitmapFactory.decodeStream(is);
}catch(Exception e){
Log.e("Image","Failed to load image",e);
}
return null;
}
protected void onProgressUpdate(Integer... params){
//Update a progress bar here, or ignore it, it's up to you
}
protected void onPostExecute(Bitmap img){
ImageView iv = (ImageView)findViewById(R.id.imageView1);
if(iv!=null && img !=null){
iv.setImageBitmap(img);
//start next image grab
vidLoop();
}
}
protected void onCancelled(){
}
}
class ClientThread implements Runnable {
private static final int SERVERPORT = 8082;
public void run() {
Log.d("clientThread","clientThread started");
setConnected(false);
while ((!Thread.currentThread().isInterrupted()) && stayConnected)
{
controlLoop();
}
//user requested disconnect
Log.d("clientThread","clientThread ending");
}
void controlLoop()
{
BufferedReader s_input = null;
PrintWriter s_output = null;
String inputString = null;
String outputString = null;
Boolean continueLoop = true;
Log.d("clientThread","controlLoop starting");
//protocol:
//Java boolean: enabled or disabled
//Directions: stop, rotateRight, rotateLeft, forward, reverse
//Client sends: robotEnabled,direction,servoPanValue
//Server replies: sensor1,sensor2...
continueLoop = true;
try {
InetAddress serverAddr = InetAddress.getByName(robotIP);
Socket s = new Socket();
//int timeout = 2000; // DEFAULT milliseconds
int timeout = 6000; // milliseconds
SocketAddress sockaddr = new InetSocketAddress(serverAddr, SERVERPORT);
s.connect(sockaddr, timeout);
s_input = new BufferedReader(new InputStreamReader(s.getInputStream()));
s_output = new PrintWriter(s.getOutputStream(), true);
} catch (UnknownHostException e1) {
e1.printStackTrace();
Log.d("clientThread","Got invalid IP string in client thread");
continueLoop = false;
} catch (IOException e) {
Log.d("clientThread","Socket setup caught IOexception");
continueLoop = false;
//STACKEXCHANGE - THIS SEEMS TO BE WHERE THE CODE REPEATEDLY LOOPS AROUND TRYING TO CONNECT**********************************************************************************************
}
//STACKEXCHANGE - Loop starts below again and then logging "controlloop ending"
Log.d("clientThread","Socket Established");
setConnected(true);
try {
while ((stayConnected) && (continueLoop)) {
speed = throttle.getProgress();
if (stayConnected)
outputString = robotEnabled.toString() + "," + direction.toString() + "," + speed.toString();
else
outputString = "quit";
s_output.println(outputString);
if (!s_output.checkError())
{
inputString = s_input.readLine();
if (inputString == null)
{
continueLoop = false;
Log.d("clientThread","Unexpected disconnection.");
}
else
{
Log.d("clientThread","Client got: " + inputString.toString());
//parse returned string, which is just an integer containing the signal strength
try {
signalStrength = Integer.parseInt(inputString);
} catch(NumberFormatException nfe) {
Log.d(TAG,"Got invalid signal strength from client");
}
}
}
else
{
//printwriter.checkError returned true, something bad happened network-wise
continueLoop = false;
Log.d("clientThread","Printwriter.checkError() returned true, likely network problem");
}
}
socketCleanup();
Log.d("clientThread","controlLoop ending");
//STACKEXCHANGE - This is also logged in the catlog at the end of repetitive loop
} catch (IOException e) {
//this happens if the connection times out.
Log.d("clientThread", "Client comm thread got IOException in control loop.");
socketCleanup();
}
}//end control loop
} //end client thread
}
It's because you don't modify stayConnected.
You continually call
while ((!Thread.currentThread().isInterrupted()) && stayConnected)
{
controlLoop();
}
and get an exception each time with your call. Only modifying continueLoop to false. You should break your while on that condition or interrupt your thread as well for your intended behavior; or some other approach would work.

Change image and text after click

Hello guys I'm working on simple application, which basically has an button function, which when pressed, displays the progress bar and then switch the image. I have problem, that this code switched the image immediately after clicked the button. I need to switch the image at the end of progress bar.
This is the code I have so far:
package com.example.testapp;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.view.View;
import android.view.View.OnClickListener;
public class MainActivity extends Activity {
ImageView image;
Button btnStartProgress;
ProgressDialog progressBar;
private int progressBarStatus = 0;
private Handler progressBarHandler = new Handler();
private long fileSize = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
addListenerOnButton();
}
public void addListenerOnButton() {
image = (ImageView) findViewById(R.id.imageView1);
btnStartProgress = (Button) findViewById(R.id.button1);
btnStartProgress.setOnClickListener(
new OnClickListener() {
#Override
public void onClick(View v) {
progressBar = new ProgressDialog(v.getContext());
progressBar.setCancelable(true);
progressBar.setMessage("Scanning ...");
progressBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressBar.setProgress(0);
progressBar.setMax(100);
progressBar.show();
progressBarStatus = 0;
fileSize = 0;
new Thread(new Runnable() {
public void run() {
while (progressBarStatus < 100) {
progressBarStatus = doSomeTasks();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Update the progress bar
progressBarHandler.post(new Runnable() {
public void run() {
TextView textView = (TextView) findViewById(R.id.textView1);
textView.setText("Completed!");
textView.setTextColor(0xFF00FF00);
image.setImageResource(R.drawable.yes_small);
progressBar.setProgress(progressBarStatus);
}
});
}
if (progressBarStatus >= 100) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
progressBar.dismiss();
}
}
}).start();
}
});
}
public int doSomeTasks() {
while (fileSize <= 1000000) {
fileSize++;
if (fileSize == 100000) {
return 10;
} else if (fileSize == 200000) {
return 20;
} else if (fileSize == 300000) {
return 30;
} else if (fileSize == 400000) {
return 40;
} else if (fileSize == 500000) {
return 50;
} else if (fileSize == 600000) {
return 60;
} else if (fileSize == 700000) {
return 70;
} else if (fileSize == 800000) {
return 80;
} else if (fileSize == 900000) {
return 90;
}
}
return 100;
}
}
The problem, I suspect, is in the logic of doSomeTasks(). You are looking for some really specific sizes here. What if the size fileSize is not an exact match to any of the values in your if-else ladder ?
Try changing the logic there and see if that makes a difference :)
Move the textView.set... code into the if (progressBarStatus >= 100) block. You are currently updating the text to "Completed!" every time the progress bar updates to any value.

My Android app's gameLoop thread crashes at exit

The problem is that when I'm in the game, and click the Home button, the gameLoop thread (I guess) gets messed up and then it pops up "Unfortunately, 'app name' has stopped."
I've made a very simple program where this problem occurs. All this program does is showing a number on the screen, and increasing it when you touch the screen.
When I comment out view.onDraw(c) in GameLoopThread, everything seems to run nicely.
Error message:
FATAL EXEPTION: Thread-23207
java.lang.NullPointerExeption
at com.example.crashtest.GameView.onDraw(GameView.java:61)
at com.example.crashtest.GameLoopThread.run(GameLoopThread.java:34)
Here's the code:
MainActivity.java
package com.example.crashtest;
import android.os.Bundle;
import android.app.Activity;
import android.content.res.Configuration;
import android.view.KeyEvent;
import android.view.Window;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(new GameView(this));
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
return true;
case KeyEvent.KEYCODE_MENU:
return true;
case KeyEvent.KEYCODE_VOLUME_UP:
return true;
case KeyEvent.KEYCODE_VOLUME_DOWN:
return true;
default:
return false;
}
}
}
GameView.java
package com.example.crashtest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class GameView extends SurfaceView {
private SurfaceHolder holder;
private GameLoopThread gameLoopThread;
private int num = 0;
public GameView(final Context context) {
super(context);
holder = getHolder();
holder.addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
gameLoopThread.setRunning(false);
while (retry) {
try {
gameLoopThread.join();
retry = false;
} catch (InterruptedException e) {}
}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
makeThread();
gameLoopThread.start();
gameLoopThread.setRunning(true);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
});
}
private void makeThread() {
gameLoopThread = new GameLoopThread(this);
}
#SuppressLint({ "WrongCall", "DrawAllocation" })
#Override
protected void onDraw(Canvas canvas) {
// Draw black background - Write variable 'num' on the screen
canvas.drawColor(Color.BLACK);
Paint paint = new Paint();
paint.setARGB(255, 0, 255, 0);
paint.setTextSize(50);
paint.setTextAlign(Align.CENTER);
canvas.drawText(Integer.toString(num), getWidth() / 2, getHeight() / 2, paint);
}
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN) {
// Increase 'num' with 1 every touch
num++;
}
return super.onTouchEvent(event);
}
}
GameLoopThread.java
package com.example.crashtest;
import android.annotation.SuppressLint;
import android.graphics.Canvas;
public class GameLoopThread extends Thread {
static final long FPS = 10;
private GameView view;
public boolean running = false;
public boolean pause = false;
public GameLoopThread(GameView view) {
this.view = view;
}
public void setRunning(boolean run) {
running = run;
}
#SuppressLint("WrongCall")
#Override
public void run() {
long ticksPS = 1000 / FPS;
long startTime = 0;
long sleepTime = 0;
while (running) {
Canvas c = null;
startTime = System.currentTimeMillis();
try {
c = view.getHolder().lockCanvas();
synchronized (view.getHolder()) {
view.onDraw(c);
}
} finally {
if (c != null) {
view.getHolder().unlockCanvasAndPost(c);
}
}
sleepTime = ticksPS-(System.currentTimeMillis() - startTime);
try {
if (sleepTime > 0)
sleep(sleepTime);
else
sleep(10);
} catch (Exception e) {}
}
}
}
Look what you need when you close the Activity you need to stop your thread from my code implemented before see it :
GameView gameView ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
gameView = new GameView(this);
setContentView(gameView);
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
gameView.StopView();
}
and you need to implement method called StopView() in your GameView like this
public void StopView() {
if (gameLoopThread != null) {
gameLoopThread.setRunning(false);
}
}
the problem because you still call the run method in thread after you try to block the thread and so you need to stop it before to block it using join.
i tested your code with new implementation and it work well with me , feed me back

Categories

Resources