So what i want to do basically is to scroll the scroll view as the client app sends the command. The method handleScrolling() works in the onCreate() but whenever i call it from the Thread, it doesn't scroll. I think that calling it from the Thread is the problem.
public class TeleprompterActivity extends Activity {
static ScrollView mScrollView;
TextView teleprompterTextView;
String message;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_teleprompter);
teleprompterTextView = findViewById(R.id.teleprompter_text_view);
teleprompterTextView.setText(MainActivity.contents);
mScrollView = findViewById(R.id.scroll);
Thread mThread = new Thread(new ServerClass());
mThread.start();
handleScrolling(3, true);
Log.e("TELE", "handleScrolling at start onCrete");
}
void handleScrolling(final int numLines, final boolean next) {
mScrollView.post(new Runnable() {
public void run() {
int currPosition = mScrollView.getScrollY();
int textSize = (int) teleprompterTextView.getTextSize();
if (next) {
int newPos = currPosition + (textSize * numLines);
mScrollView.smoothScrollTo(0, newPos);
}
if (!next) {
int newPos = currPosition - (textSize * numLines);
if (newPos < 0) {
newPos = 0;
}
mScrollView.scrollTo(0, newPos);
}
}
});
}
void handleMessage(String message) {
if (message.contains("NEXT:")) {
try {
int numLine = Integer.parseInt(message.substring(5));
handleScrolling(numLine, true);
return;
} catch (NumberFormatException nFE) {
nFE.printStackTrace();
Toast.makeText(TeleprompterActivity.this, "Number Format Exception", Toast.LENGTH_SHORT).show();
}
}
if (message.contains("BACK:")) {
try {
int numLine = Integer.parseInt(message.substring(5));
handleScrolling(numLine, false);
} catch (NumberFormatException nFE) {
nFE.printStackTrace();
Toast.makeText(TeleprompterActivity.this, "Number Format Exception", Toast.LENGTH_SHORT).show();
}
}
}
public class ServerClass implements Runnable {
ServerSocket serverSocket;
Socket socket;
DataInputStream dataInputStream;
String receivedData;
Handler handler = new Handler();
#Override
public void run() {
try {
serverSocket = new ServerSocket(8080);
Log.e("TELE", "WAITIN FOR CLIENT");
while (true) {
socket = serverSocket.accept();
dataInputStream = new DataInputStream(socket.getInputStream());
receivedData = dataInputStream.readUTF();
handler.post(new Runnable() {
#Override
public void run() {
message = receivedData;
handleMessage(message);
}
});
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
The handleScrolling() method works perfectly when called outside the Thread. Is it any problem of reference or something like that.
Thanks..
Never update UI components from a thread directly ,call Activity's runOnUiThread so you can use code construct like below:
public class TeleprompterActivity extends Activity {
static ScrollView mScrollView;
TextView teleprompterTextView;
String message;
Activity thisActivity;//<--- used for saving reference to this Activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_teleprompter);
teleprompterTextView = findViewById(R.id.teleprompter_text_view);
teleprompterTextView.setText(MainActivity.contents);
mScrollView = findViewById(R.id.scroll);
thisActivity = this;//<---- saving a reference to this activity
Thread mThread = new Thread(new ServerClass());
mThread.start();
handleScrolling(3, true);
Log.e("TELE", "handleScrolling at start onCrete");
}
void handleScrolling(final int numLines, final boolean next) {
thisActivity.runOnUiThread(new Runnable()//<--used thisActivity.runOnUiThread here
{
public void run() {
int currPosition = mScrollView.getScrollY();
int textSize = (int) teleprompterTextView.getTextSize();
if (next) {
int newPos = currPosition + (textSize * numLines);
mScrollView.smoothScrollTo(0, newPos);
}
if (!next) {
int newPos = currPosition - (textSize * numLines);
if (newPos < 0) {
newPos = 0;
}
mScrollView.scrollTo(0, newPos);
}
}
});
}
Related
So I developed an Android application which acts as a server for my Android game(two separated apps), both applications were written in Java.
Previously I got messages on the Log like: "Skipped 2000 frames. The main thread could be overworking".
This is the code of my app, it's made of only the MainActivity:
I tried to introduce concurrent Threads in order to make the main thread lighter. Now the skipped n frames message isn't showed anymore but messages such like the followings are shown anyways.
"Alloc concurrent copying GC freed", "Starting a blocking GC alloc", "Waiting for a blocking GC alloc", "WaitForGcToComplete blocked alloc on HeapTrim" and all of this ends with
Throwing OutOfMemoryError "Failed to allocate a 32 byte allocation with 15604408 free bytes and 14MB until OOM, target footprint 268435456, growth limit 268435456; failed due to fragmentation (largest possible contiguous allocation 0 bytes)" (VmSize 5539048 kB).
I tried to deallocate some objects (lines of code which contains "x = null") but it didn't solve. Furthermore I checked with a log if there is some sort of endless loop but it doesn't seem to be the case.
public class MainActivity extends AppCompatActivity {
private static ActivityMainBinding binding;
private WSocServer server;
private int port = 8080;
private boolean isOnline = false;
private static ArrayList<String> logs = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbar);
binding.openConnection.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(!isOnline) {
isOnline = true;
server = new WSocServer(port);
server.start();
Toast toast = Toast.makeText(view.getContext(),"Server is on", Toast.LENGTH_LONG);
toast.show();
Log.i("WebSocket Server", "Started on port " + server.getPort());
}
else{
Snackbar snack = Snackbar.make(view ,"We are already online!", Snackbar.LENGTH_INDEFINITE);
snack.setAction("Got it", new View.OnClickListener() {
#Override
public void onClick(View view) {
snack.dismiss();
}
});
snack.show();
}
}
});
binding.closeConnection.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(isOnline) {
isOnline = false;
logs.clear();
Toast toast = Toast.makeText(view.getContext(),"Server is off", Toast.LENGTH_LONG);
toast.show();
try {
server.stop();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
else{
Snackbar snack = Snackbar.make(view ,"We are already offline!", Snackbar.LENGTH_INDEFINITE);
snack.setAction("Got it", new View.OnClickListener() {
#Override
public void onClick(View view) {
snack.dismiss();
}
});
snack.show();
}
}
});
}
private static void addOnView(){
ConstraintLayout cl = binding.logsView;
Handler h = new Handler(Looper.getMainLooper());
for(int i = 0; i < logs.size(); i++){
TextView tv = new TextView(binding.getRoot().getContext());
tv.setTextSize(16);
tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
tv.setPadding(40,180*(i+1),40,0);
tv.setText(logs.get(i));
Runnable r = new Runnable() {
#Override
public void run() {
cl.addView(tv);
}
};
h.post(r);
}
}
#Override
protected void onDestroy() {
super.onDestroy();
try {
server.stop();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static class WSocServer extends WebSocketServer {
private List<String> matchUsers;
private Integer timerSeconds;
private UUID matchId;
//a key represents a match to which an array of extracted numbers is associated
private Hashtable<String,Integer[]> matchExtractedNumbers = new Hashtable<>();
private Hashtable<String, Collection<WebSocket>> matchClients = new Hashtable<>();
private Hashtable<String,Hashtable<String,ArrayList<String>>> users_scorePerMatch = new Hashtable<>();
private Hashtable<String,WebSocket> clientConnection = new Hashtable<>();
private void initTimer(){
timerSeconds = 60;
Timer timer = new Timer();
TimerTask task = new TimerTask() {
public void run() {
if(timerSeconds > 0) timerSeconds--;
else {
timerSeconds = 60; timer.cancel(); timer.purge();
}
}
};
timer.schedule(task,0L,1000L);
}
private String UsersListToString(List list){
return list.toString().replace("[","").replace("]","");
}
private Integer[] generateExtractedNumbers(){
Integer[] callerBoard = new Integer[90];
List<Integer> boardPool = new ArrayList<>();
boardPool.addAll(Arrays.asList(IntStream.rangeClosed(1,90).boxed().toArray(Integer[]::new)));
for(int i = 0; i < 90; i++){
int rng = ThreadLocalRandom.current().nextInt(0,90-i);
callerBoard[i] = boardPool.remove(rng);
}
return callerBoard;
}
private void initMatch(){
matchId = UUID.randomUUID();
Integer[] matchBoard = generateExtractedNumbers();
matchExtractedNumbers.put(matchId.toString(),matchBoard);
matchClients.put(matchId.toString(),clientConnection.values());
Hashtable<String,ArrayList<String>> matchData = new Hashtable<>();
for(String user: matchUsers) matchData.put(user,new ArrayList<>());
users_scorePerMatch.put(matchId.toString(), matchData);
}
private Integer getExtractedNumber(String match, Integer turn){
if(turn >= 90) return -1;
Integer[] thisMatchExtractedNumbers = matchExtractedNumbers.get(match);
Integer returning = thisMatchExtractedNumbers[turn];
thisMatchExtractedNumbers = null;
return returning;
}
public WSocServer(int port){
super(new InetSocketAddress(port));
}
public WSocServer(InetSocketAddress address) {
super(address);
}
#Override
public void onOpen(WebSocket conn, ClientHandshake handshake) {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
Log.i("WebSocket(open)", conn.getRemoteSocketAddress().getAddress().getHostAddress() + " entered the room!");
logs.add(conn.getRemoteSocketAddress().getAddress().getHostAddress() + " entered the room!");
matchUsers = new ArrayList<>();
matchUsers.addAll(Arrays.asList("user1","user2","user3","user4","user5"));
}
});
thread.start();
}
#Override
public void onClose(WebSocket conn, int code, String reason, boolean remote) {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
Log.i("WebSocket(close)", conn + " has left the room! Reason: " + reason);
logs.add(conn + " has left the room!");
}
});
thread.start();
}
#Override
public void onMessage(WebSocket conn, String message) {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
logs.add(message + " from " + conn.getRemoteSocketAddress().getAddress().getHostAddress());
Log.i("WebSocket(message)", conn + ": " + message);
MainActivity.addOnView();
if(message.startsWith("username")){
if(matchUsers.size() < 6){
String user = message.replace("username;","");
if(!matchUsers.contains(user)) {
matchUsers.add(user);
clientConnection.put(user,conn);
}
String sending = "matchUsers;" + UsersListToString(matchUsers);
conn.send(sending);
}
else conn.send("errorUsername");
}
else if(message.equals("timerStart")){
initTimer();
if(matchUsers.size() < 6){
String sending = "timeStarter;" + timerSeconds.toString();
conn.send(sending);
}
else conn.send("errorTimer");
}
else if(message.equals("getMatchId")){
if(!matchUsers.isEmpty()){
initMatch();
matchUsers.clear();
}
String sending = "matchId;" + matchId.toString();
conn.send(sending);
}
else if(message.startsWith("inGame")){
String[] fields = message.split(";");
String matchId = fields[1].split("=")[1];
int turn = Integer.parseInt(fields[2].split("=")[1]);
Integer extraction = getExtractedNumber(matchId,turn);
fields = null;
conn.send("extracted=" + extraction.toString());
}
else if(message.startsWith("score")){
String matchId = message.split(";")[1].split("=")[1];
String score = message.split(";")[0].split("=")[1];
WebSocket[] clients = matchClients.get(matchId).toArray(new WebSocket[0]);
String user = "";
Enumeration<String> keys = clientConnection.keys();
String key = keys.nextElement();
while(!key.isEmpty()){
if(clientConnection.get(key) == conn) {
user = key;
break;
}
key = keys.nextElement();
}
keys = null;
Hashtable<String,ArrayList<String>> tmp = users_scorePerMatch.get(matchId);
ArrayList<String> tmp_list = tmp.get(user);
tmp_list.add(score);
tmp.replace(user,tmp_list);
users_scorePerMatch.replace(matchId,tmp);
for(int i = 0; i < clients.length; i++){
clients[i].send("statement;" + user + " got " + score + " with");
}
clients = null;
}
else if(message.startsWith("endMatchData")){
String matchId = message.split(";")[1].split("=")[1];
Hashtable<String,ArrayList<String>> users_ofMatch = users_scorePerMatch.get(matchId);
ArrayList<String> users = new ArrayList<>();
Enumeration<String> e = users_ofMatch.keys();
while(e.hasMoreElements()){
Log.e("endmatchdata","a");
users.add(e.nextElement());
}
e = null;
String sending = "matchEndData;";
for(String user: users) sending += user + "=" + UsersListToString(users_ofMatch.get(user)) + ":";
users_ofMatch = null;
conn.send(sending);
}
else if(message.startsWith("totalEnd")){
String matchId = message.split(";")[1].split("=")[1];
if(matchClients.get(matchId)!=null) {
WebSocket[] clients = matchClients.get(matchId).toArray(new WebSocket[0]);
for (WebSocket client : clients) client.close();
Enumeration<String> e = clientConnection.keys();
boolean exit = false;
while (e.hasMoreElements() && !exit) {
Log.e("totalend", "while");
for (WebSocket client : clients) {
Log.e("totalend", "for");
String tmp = e.nextElement();
if (clientConnection.get(tmp) == client) {
clientConnection.remove(tmp);
exit = true;
break;
}
}
}
e = null; clients = null;
matchClients.remove(matchId);
users_scorePerMatch.remove(matchId);
matchExtractedNumbers.remove(matchId);
}
}
}
});
thread.start();
}
#Override
public void onMessage(WebSocket conn, ByteBuffer message) {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
Log.i("WebSocket(message)", conn + ": " + message );
}
});
thread.start();
}
public static void main(String[] args){
}
#Override
public void onError(WebSocket conn, Exception ex) {
ex.printStackTrace();
}
#Override
public void onStart() {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
Log.i("WebSocket", "Server started!");
}
});
thread.start();
}
}
}
EDIT: The thing seems to be happening at the end of the match(i.e in the message.startsWith("totalEnd") or message.startsWith("endmatchdata") if cases in the onMessage method
EDIT 2: I found out that the addOnView function was badly written.
I changed it into
private static void addOnView(){
ConstraintLayout cl = binding.logsView;
Handler h = new Handler(Looper.getMainLooper());
final TextView tv = new TextView(binding.getRoot().getContext());
tv.setTextSize(16);
tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
tv.setPadding(40,180*(logs.size()+1),40,0);
tv.setText(logs.get(logs.size()-1));
Runnable r = new Runnable() {
#Override
public void run() {
cl.addView(tv);
}
};
h.post(r);
h = null;
r = null;
}
And it solved.
The idea here is to make a socket connection over the local network, send some data, and close the connection immediately. The only thing that should remain running is the serversocket. So far, everything works as expected except one thing:
When the activity that starts the serversocket gets closed with the back button, and then reopened, the data being sent from the client no longer makes it to the serversocket.
DMActivity:
public class DMActivity extends AppCompatActivity {
String ipAddress;
boolean dmListenRunning = false;
DMListen dmListen = new DMListen();
Thread dmListenThread;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dm);
if (!(dmListenRunning)) {
dmListenThread = new Thread(dmListen);
dmListenRunning = true;
dmListenThread.start();
}
}
#Override
public void onBackPressed()
{
try {
dmListen.KillThread(true);
dmListenThread.interrupt();
}
catch (Exception e)
{
Log.i("LOG", e.toString());
}
finish();
}
}
DMListen:
public class DMListen implements Runnable {
ServerSocket serverSocket;
boolean started = false;
boolean closeSockets = false;
boolean killed = false;
public void run() {
ReceivePlayerData();
}
public void ReceivePlayerData() {
try {
while (!(Thread.interrupted())) {
if (!(started)) {
int port = 8080;
serverSocket = new ServerSocket(port);
started = true;
}
Socket clientSocket = serverSocket.accept();
DataInputStream dataIn = new DataInputStream(clientSocket.getInputStream());
String name;
int init;
name = dataIn.readUTF();
init = dataIn.readInt();
dataIn.close();
clientSocket.close();
}
}
catch (Exception e) {
Log.i("LOG", e.toString();
}
if(killed)
{
try {
serverSocket.close();
if (Thread.currentThread().isInterrupted())
{
try {
Thread.currentThread().join();
}
catch (Exception e)
{
Log.i("LOG", e.toString());
}
}
}
catch(IOException e)
{
Log.i("LOG", e.toString());
}
}
}
public void KillThread(boolean k)
{
boolean killed = k;
}
}
PlayerActivity:
public class PlayerActivity extends AppCompatActivity {
EditText hostIPBox;
Button submit;
String hostIPString;
InetAddress hostIP;
boolean denied = false;
boolean started = false;
PlayerConnect playerConnect;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_player);
hostIPBox = (EditText) findViewById(R.id.ipaddress);
hostIPBox.setRawInputType(Configuration.KEYBOARD_12KEY);
hostIPBox.setSingleLine();
submit = (Button) findViewById(R.id.submit);
submit.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
hostIPString = hostIPBox.getText().toString();
try {
if (!(hostIPString.equals(""))) {
hostIP = InetAddress.getByName(hostIPString);
if(!(started)) {
playerConnect = new PlayerConnect();
playerConnect.SetHostIP(hostIP);
denied = playerConnect.GetDenied();
started = true;
}
else {
playerConnect.SetHostIP(hostIP);
denied = playerConnect.GetDenied();
}
if (denied)
{
started = false;
}
else
{
new Thread(playerConnect).start();
}
}
}
catch (Exception e) {
Log.e("LOG", e.toString());
}
}
});
}
}
PlayerConnect:
public class PlayerConnect implements Runnable {
InetAddress hostIP;
boolean closeSockets = false;
boolean denied = false;
public void run() {
SendPlayerData(hostIP, playerName, playerInitiative);
}
private void SendPlayerData(InetAddress IP, String name, int init) {
try {
int port = 8080;
Socket socket = new Socket();
socket.connect(new InetSocketAddress(IP, port), 3000);
DataOutputStream output = new DataOutputStream(socket.getOutputStream());
if (socket.isConnected())
{
output.writeUTF(name);
output.writeInt(init);
output.close();
socket.close();
}
if (closeSockets) {
output.close();
socket.close();
closeSockets = false;
}
}
catch (Exception e) {
denied = true;
Log.i("LOG", e.printStackTrace());
}
}
public void SetHostIP(InetAddress host)
{
hostIP = host;
}
public boolean GetDenied()
{
return denied;
}
}
You should use Service to handle socket connection. You won't have problems with Activity lifecycle.
I keep getting an an error when trying to call WowZa GoCoder SDK's PlayerActivity and I am unable to understand the cause. The error appears when mStreamPlayerView.play(mStreamPlayerConfig, statusCallback) is called. Would really appreciate help on where i am going wrong
vodFragment.java
public class vodFragment extends Fragment {
private int mColumnCount = 1;
ListView videoView;
ArrayList <Vidoes> videoList;
private static String value;
String videoName;
String url = "http://192.168.43.149/twende/channelVOD.php";
public vodFragment() {
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (getActivity().getActionBar() != null) {
getActivity().getActionBar().setTitle(value);
}
View view = inflater.inflate(R.layout.fragment_vod_list, container, false);
videoView = (ListView) view.findViewById(R.id.listView);
videoList = new ArrayList<Vidoes>();
JSONObject channelInfo = new JSONObject();
try {
channelInfo.put("channelName", value);
channelInfo.put("channelOwner", "dan");
postJSONObject(url,channelInfo);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return view;
}
public static void setChannel(String channel){
value = channel;
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
}
#Override
public void onDetach() {
super.onDetach();
}
public void postJSONObject(final String myurl, final JSONObject parameters) {
class postJSONObject extends AsyncTask<Void, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
try {
loadIntoVodView(s);
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
protected String doInBackground(Void... voids) {
HttpURLConnection conn = null;
try {
StringBuffer response = null;
URL url = new URL(myurl);
conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000);
conn.setConnectTimeout(15000);
conn.setRequestProperty("Content-Type", "application/json");
conn.setDoOutput(true);
conn.setRequestMethod("POST");
OutputStream out = new BufferedOutputStream(conn.getOutputStream());
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"));
writer.write(parameters.toString());
writer.close();
out.close();
int responseCode = conn.getResponseCode();
System.out.println("responseCode" + responseCode);
switch (responseCode) {
case 200:
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String inputLine;
response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
return response.toString();
}
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (conn != null) {
try {
conn.disconnect();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
return null;
}
}
postJSONObject postJSONObject = new postJSONObject();
postJSONObject.execute();
}
private void loadIntoVodView(String json) throws JSONException {
JSONArray jsonArray = new JSONArray(json);
final String[] videos = new String[jsonArray.length()];
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject obj = jsonArray.getJSONObject(i);
videos[i] = removeExtension(obj.getString("title"));
Vidoes vidoe = new Vidoes();
vidoe.setTitle(videos[i]);
videoList.add(vidoe);
}
VideoListAdapter adapter = new VideoListAdapter(getActivity(), R.layout.vodparsedata, videoList);
videoView.setAdapter(adapter);
videoView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1,
int position, long arg3) {
videoName = Arrays.asList(videos).get(position);
Intent intent = new Intent(getActivity(), PlayerActivity.class);
String message = videoName+".mp4";
intent.putExtra("videoName", message);
startActivity(intent);
System.out.println("arr: " + Arrays.asList(videos).get(position));
}
});
}
public static String removeExtension(String fileName) {
if (fileName.indexOf(".") > 0) {
return fileName.substring(0, fileName.lastIndexOf("."));
} else {
return fileName;
}
}
}
PlayerActivity.java
public class PlayerActivity extends GoCoderSDKActivityBase {
final private static String TAG = PlayerActivity.class.getSimpleName();
String videoName;
private WOWZPlayerView mStreamPlayerView = null;
private WOWZPlayerConfig mStreamPlayerConfig = new WOWZPlayerConfig();
private MultiStateButton mBtnPlayStream = null;
private MultiStateButton mBtnSettings = null;
private MultiStateButton mBtnMic = null;
private MultiStateButton mBtnScale = null;
private SeekBar mSeekVolume = null;
private ProgressDialog mBufferingDialog = null;
private StatusView mStatusView = null;
private TextView mHelp = null;
private TimerView mTimerView = null;
private ImageButton mStreamMetadata = null;
private boolean mUseHLSPlayback = false;
private WOWZPlayerView.PacketThresholdChangeListener packetChangeListener = null;
private VolumeChangeObserver mVolumeSettingChangeObserver = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_stream_player);
mRequiredPermissions = new String[]{};
if (savedInstanceState == null) {
Bundle extras = getIntent().getExtras();
if(extras == null) {
videoName= null;
} else {
videoName= extras.getString("videoName");
}
} else {
videoName= (String) savedInstanceState.getSerializable("videoName");
}
System.out.print(videoName);
mStreamPlayerConfig.setIsPlayback(true);
mStreamPlayerConfig.setHostAddress("192.168.43.149");
mStreamPlayerConfig.setApplicationName("Dark Souls 2 Channel");
mStreamPlayerConfig.setStreamName(videoName);
mStreamPlayerConfig.setPortNumber(1935);
mStreamPlayerView = (WOWZPlayerView) findViewById(R.id.vwStreamPlayer);
mBtnPlayStream = (MultiStateButton) findViewById(R.id.ic_play_stream);
mBtnSettings = (MultiStateButton) findViewById(R.id.ic_settings);
mBtnMic = (MultiStateButton) findViewById(R.id.ic_mic);
mBtnScale = (MultiStateButton) findViewById(R.id.ic_scale);
mTimerView = (TimerView) findViewById(R.id.txtTimer);
mStatusView = (StatusView) findViewById(R.id.statusView);
mStreamMetadata = (ImageButton) findViewById(R.id.imgBtnStreamInfo);
mHelp = (TextView) findViewById(R.id.streamPlayerHelp);
mSeekVolume = (SeekBar) findViewById(R.id.sb_volume);
WOWZStatusCallback statusCallback = new StatusCallback();
mStreamPlayerView.play(mStreamPlayerConfig, statusCallback);
mTimerView.setVisibility(View.GONE);
mStreamPlayerView.play(mStreamPlayerConfig, statusCallback);
if (sGoCoderSDK != null) {
/*
Packet change listener setup
*/
final PlayerActivity activity = this;
packetChangeListener = new WOWZPlayerView.PacketThresholdChangeListener() {
#Override
public void packetsBelowMinimumThreshold(int packetCount) {
WOWZLog.debug("Packets have fallen below threshold "+packetCount+"... ");
activity.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(activity, "Packets have fallen below threshold ... ", Toast.LENGTH_SHORT).show();
}
});
}
#Override
public void packetsAboveMinimumThreshold(int packetCount) {
WOWZLog.debug("Packets have risen above threshold "+packetCount+" ... ");
activity.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(activity, "Packets have risen above threshold ... ", Toast.LENGTH_SHORT).show();
}
});
}
};
mStreamPlayerView.setShowAllNotificationsWhenBelowThreshold(false);
mStreamPlayerView.setMinimumPacketThreshold(20);
mStreamPlayerView.registerPacketThresholdListener(packetChangeListener);
///// End packet change notification listener
mTimerView.setTimerProvider(new TimerView.TimerProvider() {
#Override
public long getTimecode() {
return mStreamPlayerView.getCurrentTime();
}
#Override
public long getDuration() {
return mStreamPlayerView.getDuration();
}
});
mSeekVolume.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (mStreamPlayerView != null && mStreamPlayerView.isPlaying()) {
mStreamPlayerView.setVolume(progress);
}
}
public void onStartTrackingTouch(SeekBar seekBar) {
}
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
// listen for volume changes from device buttons, etc.
mVolumeSettingChangeObserver = new VolumeChangeObserver(this, new Handler());
getApplicationContext().getContentResolver().registerContentObserver(android.provider.Settings.System.CONTENT_URI, true, mVolumeSettingChangeObserver);
mVolumeSettingChangeObserver.setVolumeChangeListener(new VolumeChangeObserver.VolumeChangeListener() {
#Override
public void onVolumeChanged(int previousLevel, int currentLevel) {
if (mSeekVolume != null)
mSeekVolume.setProgress(currentLevel);
if (mStreamPlayerView != null && mStreamPlayerView.isPlaying()) {
mStreamPlayerView.setVolume(currentLevel);
}
}
});
mBtnScale.setState(mStreamPlayerView.getScaleMode() == WOWZMediaConfig.FILL_VIEW);
// The streaming player configuration properties
mStreamPlayerConfig = new WOWZPlayerConfig();
mBufferingDialog = new ProgressDialog(this);
mBufferingDialog.setTitle(R.string.status_buffering);
mBufferingDialog.setMessage(getResources().getString(R.string.msg_please_wait));
mBufferingDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getResources().getString(R.string.button_cancel), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
cancelBuffering(dialogInterface);
}
});
// testing player data event handler.
mStreamPlayerView.registerDataEventListener("onMetaData", new WOWZDataEvent.EventListener(){
#Override
public WOWZDataMap onWZDataEvent(String eventName, WOWZDataMap eventParams) {
String meta = "";
if(eventParams!=null)
meta = eventParams.toString();
WOWZLog.debug("onWZDataEvent -> eventName "+eventName+" = "+meta);
return null;
}
});
// testing player data event handler.
mStreamPlayerView.registerDataEventListener("onStatus", new WOWZDataEvent.EventListener(){
#Override
public WOWZDataMap onWZDataEvent(String eventName, WOWZDataMap eventParams) {
if(eventParams!=null)
WOWZLog.debug("onWZDataEvent -> eventName "+eventName+" = "+eventParams.toString());
return null;
}
});
// testing player data event handler.
mStreamPlayerView.registerDataEventListener("onTextData", new WOWZDataEvent.EventListener(){
#Override
public WOWZDataMap onWZDataEvent(String eventName, WOWZDataMap eventParams) {
if(eventParams!=null)
WOWZLog.debug("onWZDataEvent -> "+eventName+" = "+eventParams.get("text"));
return null;
}
});
} else {
mHelp.setVisibility(View.GONE);
mStatusView.setErrorMessage(WowzaGoCoder.getLastError().getErrorDescription());
}
}
#Override
protected void onDestroy() {
if (mVolumeSettingChangeObserver != null)
getApplicationContext().getContentResolver().unregisterContentObserver(mVolumeSettingChangeObserver);
super.onDestroy();
}
/**
* Android Activity class methods
*/
#Override
protected void onResume() {
super.onResume();
syncUIControlState();
}
#Override
protected void onPause() {
if (mStreamPlayerView != null && mStreamPlayerView.isPlaying()) {
mStreamPlayerView.stop();
// Wait for the streaming player to disconnect and shutdown...
mStreamPlayerView.getCurrentStatus().waitForState(WOWZState.IDLE);
}
super.onPause();
}
private boolean isNetworkAvailable() {
ConnectivityManager connectivityManager
= (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
public boolean isPlayerConfigReady()
{
return false;
}
/*
Click handler for network pausing
*/
public void onPauseNetwork(View v)
{
Button btn = (Button)findViewById(R.id.pause_network);
if(btn.getText().toString().trim().equalsIgnoreCase("pause network")) {
WOWZLog.info("Pausing network...");
btn.setText("Unpause Network");
mStreamPlayerView.pauseNetworkStack();
}
else{
WOWZLog.info("Unpausing network... btn.getText(): "+btn.getText());
btn.setText("Pause Network");
mStreamPlayerView.unpauseNetworkStack();
}
}
/**
* Click handler for the playback button
*/
public void onTogglePlayStream(View v) {
if (mStreamPlayerView.isPlaying()) {
mStreamPlayerView.stop();
} else if (mStreamPlayerView.isReadyToPlay()) {
if(!this.isNetworkAvailable()){
displayErrorDialog("No internet connection, please try again later.");
return;
}
// if(!this.isPlayerConfigReady()){
// displayErrorDialog("Please be sure to include a host, stream, and application to playback a stream.");
// return;
// }
mHelp.setVisibility(View.GONE);
WOWZStreamingError configValidationError = mStreamPlayerConfig.validateForPlayback();
if (configValidationError != null) {
mStatusView.setErrorMessage(configValidationError.getErrorDescription());
} else {
// Set the detail level for network logging output
mStreamPlayerView.setLogLevel(mWZNetworkLogLevel);
// Set the player's pre-buffer duration as stored in the app prefs
float preBufferDuration = GoCoderSDKPrefs.getPreBufferDuration(PreferenceManager.getDefaultSharedPreferences(this));
mStreamPlayerConfig.setPreRollBufferDuration(preBufferDuration);
// Start playback of the live stream
mStreamPlayerView.play(mStreamPlayerConfig, this);
}
}
}
/**
* WOWZStatusCallback interface methods
*/
#Override
public synchronized void onWZStatus(WOWZStatus status) {
final WOWZStatus playerStatus = new WOWZStatus(status);
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
WOWZStatus status = new WOWZStatus(playerStatus.getState());
switch(playerStatus.getState()) {
case WOWZPlayerView.STATE_PLAYING:
// Keep the screen on while we are playing back the stream
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
if (mStreamPlayerConfig.getPreRollBufferDuration() == 0f) {
mTimerView.startTimer();
}
// Since we have successfully opened up the server connection, store the connection info for auto complete
GoCoderSDKPrefs.storeHostConfig(PreferenceManager.getDefaultSharedPreferences(PlayerActivity.this), mStreamPlayerConfig);
// Log the stream metadata
WOWZLog.debug(TAG, "Stream metadata:\n" + mStreamPlayerView.getMetadata());
break;
case WOWZPlayerView.STATE_READY_TO_PLAY:
// Clear the "keep screen on" flag
WOWZLog.debug(TAG, "STATE_READY_TO_PLAY player activity status!");
if(playerStatus.getLastError()!=null)
displayErrorDialog(playerStatus.getLastError());
playerStatus.clearLastError();
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
mTimerView.stopTimer();
break;
case WOWZPlayerView.STATE_PREBUFFERING_STARTED:
WOWZLog.debug(TAG, "Dialog for buffering should show...");
showBuffering();
break;
case WOWZPlayerView.STATE_PREBUFFERING_ENDED:
WOWZLog.debug(TAG, "Dialog for buffering should stop...");
hideBuffering();
// Make sure player wasn't signaled to shutdown
if (mStreamPlayerView.isPlaying()) {
mTimerView.startTimer();
}
break;
default:
break;
}
syncUIControlState();
}
});
}
#Override
public synchronized void onWZError(final WOWZStatus playerStatus) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
displayErrorDialog(playerStatus.getLastError());
syncUIControlState();
}
});
}
public void onToggleMute(View v) {
mBtnMic.toggleState();
if (mStreamPlayerView != null)
mStreamPlayerView.mute(!mBtnMic.isOn());
mSeekVolume.setEnabled(mBtnMic.isOn());
}
public void onToggleScaleMode(View v) {
int newScaleMode = mStreamPlayerView.getScaleMode() == WOWZMediaConfig.RESIZE_TO_ASPECT ? WOWZMediaConfig.FILL_VIEW : WOWZMediaConfig.RESIZE_TO_ASPECT;
mBtnScale.setState(newScaleMode == WOWZMediaConfig.FILL_VIEW);
mStreamPlayerView.setScaleMode(newScaleMode);
}
public void onStreamMetadata(View v) {
WOWZDataMap streamMetadata = mStreamPlayerView.getMetadata();
WOWZDataMap streamStats = mStreamPlayerView.getStreamStats();
// WOWZDataMap streamConfig = mStreamPlayerView.getStreamConfig().toDataMap();
WOWZDataMap streamConfig = new WOWZDataMap();
WOWZDataMap streamInfo = new WOWZDataMap();
streamInfo.put("- Stream Statistics -", streamStats);
streamInfo.put("- Stream Metadata -", streamMetadata);
//streamInfo.put("- Stream Configuration -", streamConfig);
DataTableFragment dataTableFragment = DataTableFragment.newInstance("Stream Information", streamInfo, false, false);
getFragmentManager().beginTransaction()
.add(android.R.id.content, dataTableFragment)
.addToBackStack("metadata_fragment")
.commit();
}
public void onSettings(View v) {
// Display the prefs fragment
GoCoderSDKPrefs.PrefsFragment prefsFragment = new GoCoderSDKPrefs.PrefsFragment();
prefsFragment.setFixedSource(true);
prefsFragment.setForPlayback(true);
getFragmentManager().beginTransaction()
.replace(android.R.id.content, prefsFragment)
.addToBackStack(null)
.commit();
}
private void syncUIControlState() {
boolean disableControls = (!(mStreamPlayerView.isReadyToPlay() || mStreamPlayerView.isPlaying()) || sGoCoderSDK == null);
if (disableControls) {
mBtnPlayStream.setEnabled(false);
mBtnSettings.setEnabled(false);
mSeekVolume.setEnabled(false);
mBtnScale.setEnabled(false);
mBtnMic.setEnabled(false);
mStreamMetadata.setEnabled(false);
} else {
mBtnPlayStream.setState(mStreamPlayerView.isPlaying());
mBtnPlayStream.setEnabled(true);
if (mStreamPlayerConfig.isAudioEnabled()) {
mBtnMic.setVisibility(View.VISIBLE);
mBtnMic.setEnabled(true);
mSeekVolume.setVisibility(View.VISIBLE);
mSeekVolume.setEnabled(mBtnMic.isOn());
mSeekVolume.setProgress(mStreamPlayerView.getVolume());
} else {
mSeekVolume.setVisibility(View.GONE);
mBtnMic.setVisibility(View.GONE);
}
mBtnScale.setVisibility(View.VISIBLE);
mBtnScale.setVisibility(mStreamPlayerView.isPlaying() && mStreamPlayerConfig.isVideoEnabled() ? View.VISIBLE : View.GONE);
mBtnScale.setEnabled(mStreamPlayerView.isPlaying() && mStreamPlayerConfig.isVideoEnabled());
mBtnSettings.setEnabled(!mStreamPlayerView.isPlaying());
mBtnSettings.setVisibility(mStreamPlayerView.isPlaying() ? View.GONE : View.VISIBLE);
mStreamMetadata.setEnabled(mStreamPlayerView.isPlaying());
mStreamMetadata.setVisibility(mStreamPlayerView.isPlaying() ? View.VISIBLE : View.GONE);
}
}
private void showBuffering() {
try {
if (mBufferingDialog == null) return;
mBufferingDialog.show();
}
catch(Exception ex){}
}
private void cancelBuffering(DialogInterface dialogInterface) {
if(mStreamPlayerConfig.getHLSBackupURL()!=null || mStreamPlayerConfig.isHLSEnabled()){
mStreamPlayerView.stop(true);
}
else if (mStreamPlayerView != null && mStreamPlayerView.isPlaying()) {
mStreamPlayerView.stop(true);
}
}
private void hideBuffering() {
if (mBufferingDialog.isShowing())
mBufferingDialog.dismiss();
}
#Override
public void syncPreferences() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
mWZNetworkLogLevel = Integer.valueOf(prefs.getString("wz_debug_net_log_level", String.valueOf(WOWZLog.LOG_LEVEL_DEBUG)));
mStreamPlayerConfig.setIsPlayback(true);
if (mStreamPlayerConfig != null)
GoCoderSDKPrefs.updateConfigFromPrefsForPlayer(prefs, mStreamPlayerConfig);
}
private class StatusCallback implements WOWZStatusCallback {
#Override
public void onWZStatus(WOWZStatus wzStatus) {
}
#Override
public void onWZError(WOWZStatus wzStatus) {
}
}
}
The error I get is;
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.wowza.gocoder.sdk.sampleapp/com.wowza.gocoder.sdk.sampleapp.PlayerActivity}: java.lang.RuntimeException: Invalid surface: null
You start the stream in onCreate. At this time the Surface used by WOWZPlayerView is not ready yet and the app crashes with the 'Invalid surface' error.
If you look at the sample test in the GoCoder SDK, the playback is started when the user clicks a button. Eg. when the Surface is valid.
Create a button and move your 'mStreamPlayerView.play(mStreamPlayerConfig, statusCallback);' to the button.onClick.
Or ... use any GoCoder SDK v1.7 and more recent.
Please, let me know if I can help any further.
Thanks
I'm trying to setup ProgressDialog to show to the user the progress of an InputStream of bytes. I'm able to show this in the console of the Android Studio by way of this below :
Log.d(TAG, "Progress, transferred " + Integer.toString(100 * bytesTransferred/osSize) + "%");
However, I'm not sure how to attach the bytesTransferred/osSize correctly to a ProgressDialog, I can use a thread to time how long the progress bar will take to fill up the progressBar with the code below:
update = new ProgressDialog(this);
update.setTitle("Transferring update");
update.setMessage("Please wait updating...");
update.setCanceledOnTouchOutside(false);
update.setProgress(0);
final int totalProgressTime = 100;
final Thread t = new Thread() {
#Override
public void run() {
int jumpTime = 0;
while(jumpTime < totalProgressTime) {
try {
sleep(1800);
jumpTime += 1;
update.setProgress(jumpTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t.start();
update.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
update.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
update.show();
}
But would be much better to show to the user the actual transfer of the bytes. This below is what I have to work with:
final int osSize;
final InputStream inputStream;
osSize = inputStream();
public void onProgress(int bytesTransferred) {
Log.d(TAG, "Progress, transferred " + Integer.toString(100 * bytesTransferred/osSize) + "%");
}
Any help would be appreciated, thanks in advance.
Extend this:
#Override
public void run() {
int jumpTime = 0;
while(jumpTime < totalProgressTime) {
try {
sleep(1800);
jumpTime += 1;
update.setProgress(jumpTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
With this:
#Override
public void run() {
int jumpTime = 0;
while(jumpTime < totalProgressTime) {
try {
sleep(1800);
jumpTime += 1;
final int fJumpTime = jumpTime;
runOnUiThread(new Runnable() {
#Override
public void run() {
update.setProgress(fJumpTime);
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
I'm hosting a server on my raspberry pi 2, and sending a stream of values between 0 and 360. I'm trying to grab whatever number is just sent on my android phone. Currently, it runs through the ReadServer code once, returns 48 (char 0) and then crashes with an 'unhandled runtime exception'. I'm able to just dummy values and have it work perfectly fine, so I know its something having to do with the client/server side.
Yes I have internet permission specified in my manifest.
PI
Server hosted on raspberry pi 2:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
void error(char * msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
int sockfd, clisockfd, portno = 5003;
socklen_t clilen;
char buffer[127];
struct sockaddr_in serv_addr, cli_addr;
int n;
/* call socket */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) { error("ERROR opening socket"); }
/* initialize socket structure */
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
printf("waiting to bind\n");
fflush(stdout);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
{ error("ERROR on binding"); }
listen(sockfd, 5);
clilen = (socklen_t) sizeof(cli_addr);
printf("waiting to accept\n");
clisockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
printf("accepted\n");
if (clisockfd < 0) { error("ERROR on accept"); }
int heading = 0;
while (heading < 360)
{
bzero(buffer, 126);
printf("sending\n");
sprintf(buffer, "%d\n", heading);
n = write(clisockfd, buffer, strlen(buffer));
if (n < 0) { error("ERROR writing to socket"); }
printf("sending %s\n", buffer);
usleep(2 * 1000*1000);
heading = heading + 2;
}
close(sockfd);
return 0;
}
ANDROID
Main activity code:
public class MainActivity extends AppCompatActivity {
final String IP_ADDRESS = "x.x.x.x"; // (is an actual address)
final int PORT = 5003;
boolean isManual = true;
RelativeLayout layout_joystick;
JoyStickClass js;
TextView velocityTextView;
Button manualButton;
ImageView compassPhoto;
Wifi wifiController;
ReadServer serverObject;
Timer serverTimer = new Timer();
Handler serverPollHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// set new view
setContentView(R.layout.activity_main);
// define buttons/interactions
manualButton = (Button) findViewById(R.id.manual_button);
Button disconnectButton = (Button) findViewById(R.id.disconnect_button);
layout_joystick = (RelativeLayout) findViewById(R.id.layout_joystick);
compassPhoto = (ImageView) findViewById(R.id.imageViewCompass);
// set joystick settings
js = new JoyStickClass(getApplicationContext()
, layout_joystick, R.drawable.image_button);
js.setStickSize(150, 150);
js.setLayoutSize(500, 500);
js.setLayoutAlpha(150);
js.setStickAlpha(90);
js.setOffset(90);
js.setMinimumDistance(50);
// set button listeners
manualButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
toggleMode();
}
});
layout_joystick.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View arg0, MotionEvent arg1) {
return jsOnTouchListener(arg0, arg1);
}
});
disconnectButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
switchToLoadScreen(view);
}
});
// load camera feed
WebView wv = (WebView)findViewById(R.id.webView);
velocityTextView = (TextView) findViewById(R.id.velocityText);
serverPollHandler = new Handler(serverCallback);
wv.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
//connect wifi
wifiController = new Wifi(IP_ADDRESS, PORT);
if (!wifiController.Connect()){
switchToLoadScreen(findViewById(android.R.id.content));
}
serverObject = new ReadServer(wifiController.getInputStream());
serverTimer.scheduleAtFixedRate(new getFromServer(), 500, 2 * 1000);
}
});
wv.loadUrl("file:///android_asset/cameraFeed.html");
}
Handler.Callback serverCallback = new Handler.Callback() {
public boolean handleMessage(Message msg) {
velocityTextView.setText("1m/s");
try {
serverObject.execute().get();
int headingToMoveTo = serverObject.getHeading();
moveCompassTo(headingToMoveTo);
}
catch (InterruptedException e) {}
catch (ExecutionException e) {}
return true;
}
};
// move the compass
private void moveCompassTo(float degree) {
float currentDegree = 0f;
// create a rotation animation (reverse turn degree degrees)
RotateAnimation ra = new RotateAnimation(
currentDegree,
-degree,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF,
0.5f);
// how long the animation will take place
ra.setDuration(5);
// set the animation after the end of the reservation status
ra.setFillAfter(true);
// Start the animation
compassPhoto.startAnimation(ra);
int a = 5;
}
// toggle between manual and autonomous modes
private void toggleMode() {
if (isManual) {
// set Autonomous Mode
manualButton.setText(R.string.manual_text);
layout_joystick.setVisibility(View.INVISIBLE);
wifiController.enterAutonomous();
isManual = false;
} else {
// set Manual Mode
manualButton.setText(R.string.autonomous_text);
layout_joystick.setVisibility(View.VISIBLE);
wifiController.enterManual();
isManual = true;
}
}
// switch between views
private void switchToLoadScreen(View thisView) {
if (wifiController.Disconnect()) {
serverTimer.cancel();
Intent myIntent = new Intent(thisView.getContext(), LoadScreen.class);
startActivityForResult(myIntent, 0);
}
}
// control what moving the joystick does {emitted}
private boolean jsOnTouchListener(View arg0, MotionEvent arg1) {
js.drawStick(arg1);
if (arg1.getAction() == MotionEvent.ACTION_DOWN
|| arg1.getAction() == MotionEvent.ACTION_MOVE) {
// textView1.setText("X : " + String.valueOf(js.getX()));
// textView2.setText("Y : " + String.valueOf(js.getY()));
// textView3.setText("Angle : " + String.valueOf(js.getAngle()));
// textView4.setText("Distance : " + String.valueOf(js.getDistance()));
switch (js.get8Direction()){
case JoyStickClass.STICK_UP:
wifiController.moveForward();
break;
case JoyStickClass.STICK_UPRIGHT:
wifiController.moveForwardRight();
break;
case JoyStickClass.STICK_RIGHT:
wifiController.moveRight();
break;
case JoyStickClass.STICK_DOWNRIGHT:
wifiController.moveBackRight();
break;
case JoyStickClass.STICK_DOWN:
wifiController.moveBack();
break;
case JoyStickClass.STICK_DOWNLEFT:
wifiController.moveBackLeft();
break;
case JoyStickClass.STICK_LEFT:
wifiController.moveLeft();
break;
case JoyStickClass.STICK_UPLEFT:
wifiController.moveForwardLeft();
break;
case JoyStickClass.STICK_NONE: // center
break;
}
} else if (arg1.getAction() == MotionEvent.ACTION_UP) {
// textView1.setText("X :");
// textView2.setText("Y :");
// textView3.setText("Angle :");
// textView4.setText("Distance :");
// textView5.setText("Direction :");
}
return true;
}
public class getFromServer extends TimerTask {
public void run() {
serverPollHandler.sendEmptyMessage(0);
}
}
}
ReadServer code:
public class ReadServer extends AsyncTask {
BufferedReader thisStream;
int heading = 0;
public ReadServer(BufferedReader fromPi)
{
thisStream = fromPi;
}
public int getHeading() {
return heading;
}
#Override
protected Object doInBackground(Object[] params) {
//communication from PI
try {
if (thisStream.ready()) {
int read = thisStream.read();
String t = Character.toString ((char) read);
if (read > 0) {
heading = Integer.parseInt(t);
}
}
}
catch (IOException e) {}
return params;
}
}
WifiController code:
public class Wifi extends AsyncTask {
// THESE MUST BE IDENTICAL TO THE PI CODE FOR CORRECT FUNCTIONALITY
private enum send_modes {
AUTONOMOUS_FLAG,
MANUAL_FLAG,
DISCONNECT_PI,
MOVE_NORTH,
MOVE_NORTHEAST,
MOVE_EAST,
MOVE_SOUTHEAST,
MOVE_SOUTH,
MOVE_SOUTHWEST,
MOVE_WEST,
MOVE_NORTHWEST
}
//
private Socket phoneToPiSocket;
private boolean isConnected = false;
private InetAddress piIPAddress;
private PrintWriter piSocketWriter;
private int portNumber;
private BufferedReader fromPi;
public Wifi(String ipAddr, int port) {
try {
portNumber = port;
piIPAddress = InetAddress.getByName(ipAddr);
} catch (UnknownHostException e) {
piIPAddress = null;
}
}
#Override
protected Object doInBackground(Object[] params) {
try {
phoneToPiSocket = new Socket(piIPAddress, portNumber);
fromPi = new BufferedReader(new InputStreamReader (phoneToPiSocket.getInputStream()));
// piSocketWriter = new PrintWriter(phoneToPiSocket.getOutputStream(), true);
isConnected = true;
} catch (ConnectException e) {
isConnected = false;
} catch (UnknownHostException e) {
isConnected = false;
} catch (IOException e) {
isConnected = false;
}
return params;
}
public boolean Disconnect() {
if (isConnected) {
try {
fromPi.close();
//disconnectFromPi(); // has to happen before writer is closed!
//piSocketWriter.close();
phoneToPiSocket.close();
isConnected = false;
} catch (IOException e) {
return false;
}
}
return true;
}
public BufferedReader getInputStream()
{
return fromPi;
}
public boolean Connect() {
// set up wifi connection
try {
execute().get();
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}
if (isConnected) {
return true;
} else {
return false;
}
}
boolean isConnected(){
return isConnected;
}
//communication to PI
public void enterAutonomous()
{
piSocketWriter.println(send_modes.AUTONOMOUS_FLAG.ordinal());
}
public void enterManual()
{
piSocketWriter.println(send_modes.MANUAL_FLAG.ordinal());
}
public void disconnectFromPi()
{
piSocketWriter.println(send_modes.DISCONNECT_PI.ordinal());
}
public void moveForward()
{
piSocketWriter.println(send_modes.MOVE_NORTH.ordinal());
}
public void moveForwardRight()
{
piSocketWriter.println(send_modes.MOVE_NORTHEAST.ordinal());
}
public void moveRight()
{
piSocketWriter.println(send_modes.MOVE_EAST.ordinal());
}
public void moveBackRight()
{
piSocketWriter.println(send_modes.MOVE_SOUTHEAST.ordinal());
}
public void moveBack()
{
piSocketWriter.println(send_modes.MOVE_SOUTH.ordinal());
}
public void moveBackLeft()
{
piSocketWriter.println(send_modes.MOVE_SOUTHWEST.ordinal());
}
public void moveLeft()
{
piSocketWriter.println(send_modes.MOVE_WEST.ordinal());
}
public void moveForwardLeft()
{
piSocketWriter.println(send_modes.MOVE_NORTHWEST.ordinal());
}
}
I apologize for how messy / horribly named everything is. Its a work in progress.
Thanks for the help.
UPDATED INFO:
The exception i get is:
"main#20747" prio=5 waiting
java.lang.Thread.State: WAITING
at com.android.internal.os.RuntimeInit$UncaughtHandler.uncaughtException(RuntimeInit.java:72)
at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:693)
at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:690)
Picture of frames at crash