OutOfMemory Exception in Android-Java. Allocation failed due to fragmentation - java

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.

Related

How to suspend and resume a non-mainstream

Don't look at all of my code, just the wait() and notify() methods I need to pause the run() method after the loop has finished its work and resume it in the onButtonClick() class, but when I do this I get an exception: current thread is not owner. How do I implement what I wrote in the title of the question
private boolean isFirstPage;
private CommandContext ctx;
private ArrayList<String> linkQuestion;
private Message message;
private int page;
public QuestionListThreads(boolean isFirstPage, CommandContext ctx, ArrayList<String> linkQuestion, Message message) {
this.isFirstPage = isFirstPage;
this.ctx = ctx;
this.linkQuestion = linkQuestion;
this.message = message;
}
#Override
public void run() {
synchronized (this) {
EmbedBuilder eb = new EmbedBuilder();
if (isFirstPage) {
for (; page < 3; page++) {
eb.addField("page " + page, "[link]" + linkQuestion.get(page), false);
}
ctx.getChannel().sendMessage(eb.build()).setActionRow(Button.secondary("next", "next")).queue();
} else {
page = 3;
for (int i = 0; i < 3; i++, page++) {
eb.addField("page " + page, "[link]" + linkQuestion.get(page), false);
if (i == 2) {
message.editMessage(eb.build()).setActionRow(Button.secondary("next", "next")).queue();
try {
this.wait();
i = 0;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
public void onButtonClick(ButtonClickEvent event) {
if (event.getComponentId().equals("next")) {
new QuestionListThreads(false, null, QuestionListCommand2.getLinkQuestion(),
event.getMessage()).notify();
}

ScrollView doesn't scroll programmatically in a Thread

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);
}
}
});
}

Android ChangeOverTime method freezing at runtime (but not consistently)

So I am running into a problem with a function I made to slowly change the value of a monitored variable over time that is causing all the java logic to lock up. It doesn't seem to be producing an error or make the application crash so it must be getting stuck in the while loop or something but the logging isn't firing while it is locked so I am just very confused. If anyone can help me figure out how to diagnose what is causing the freezing that would be very much appreciated
EDIT: Turns out the problem was updating the UI from another thread, I manged to get it to crash and got the error and used a CountDownTimer instead of the background thread and now it is working fine. For those curious checkout my GitHub for this project.
Function in question:
public static void changeOverTime(final MonitoredVariable<Integer> tVar, final int tTo, final long tTime, final long tUpdateFreq) {
if (tTime < tUpdateFreq) { Log.e(TAG, "Time must be greater then update freq."); }
if (tVar == null) { Log.e(TAG, "Container cannot be null."); }
else {
final Thread tBackgroundThread = new Thread(new Runnable() {
#Override
public void run() {
float tSteps = tTime / tUpdateFreq; // 2000/100 = 20
float tInterval = (tTo - tVar.get()) / tSteps; // 67-175 = -108/20 = -5.4
float tVal = tVar.get(); //175
while (Math.round(tVal) != tTo) { //67(After 20 Times) != 67 -> FALSE
Debug.Log(TAG, "EQ: " + Math.round(tVal) + "?=" + tTo);
tVal += tInterval; // -5.4 * 20(Times) = -108+175 = 67
tryToSleep(tUpdateFreq); // 100ms * 20(Times) = 2000ms total
tVar.set(Math.round(tVal));
}
}
});
tBackgroundThread.start();
}
}
Supporting Function:
private static void tryToSleep(long tTime) {
try { sleep(tTime); }
catch (InterruptedException e) { e.printStackTrace(); }
}
Monitored Variable Class:
public class MonitoredVariable<Prototype> {
protected Prototype mData;
protected ChangeListener mListener;
public MonitoredVariable(Prototype tData) {
this(tData, null);
}
public MonitoredVariable(Prototype tData, ChangeListener tListener) {
if (tListener != null) setListener(tListener);
mData = tData;
}
public Prototype get() {
return mData;
}
public void set(Prototype tData) {
if (mData != tData) {
mData = tData;
notifyChange();
}
}
public void setListener(ChangeListener tListener) {
mListener = tListener;
}
public ChangeListener getListener() {
return mListener;
}
public void notifyChange() {
if (mListener != null) mListener.onChange();
}
public interface ChangeListener {
void onChange();
}
}
Usage:
public static void init() {
MonitoredVariable.ChangeListener tUpdateBackground = new MonitoredVariable.ChangeListener() {
#Override
public void onChange() { updateBackgroud();
}
};
mTop = new MonitoredVariable[]{
new MonitoredVariable<>(0, tUpdateBackground),
new MonitoredVariable<>(0, tUpdateBackground),
new MonitoredVariable<>(0, tUpdateBackground)
};
mBottom = new MonitoredVariable[]{
new MonitoredVariable<>(0, tUpdateBackground),
new MonitoredVariable<>(0, tUpdateBackground),
new MonitoredVariable<>(0, tUpdateBackground)
};
mAnimationLoop = new Handler();
mAnimation = new Runnable() {
#Override
public void run() {
Debug.Log(TAG, "RUNNING ANIMATION");
final Random RNG = new Random();
for (MonitoredVariable<Integer>[] tBackground: new MonitoredVariable[][] {mTop, mBottom}) {
for (MonitoredVariable<Integer> tColor : tBackground) {
int tRandomColor = RNG.nextInt(255);
//tColor.set(tRandomColor);
Shift.changeOverTime(tColor, tRandomColor, 2000, 100);
}
}
if(mAnimate.get()) {
mAnimationLoop.postDelayed(mAnimation, 10000);
}
}
};
mAnimate = new MonitoredVariable<>(false, new MonitoredVariable.ChangeListener() {
#Override
public void onChange() {
if (mAnimate.get()) mAnimationLoop.postDelayed(mAnimation, 0);
else mAnimationLoop.removeCallbacks(mAnimation);
}
});
}
public static void setBackground(final Activity tActivity){
final View tActivityBackground = tActivity.findViewById(R.id.background);
mListener = new ChangeListener() {
#Override
public void onChange() { tActivityBackground.setBackground(mBackground); }
};
notifyChange();
}
private static void updateBackgroud() {
int tTop = Color.argb(255, mTop[0].get(), mTop[1].get(), mTop[2].get());
int tBottom = Color.argb(255, mBottom[0].get(), mBottom[1].get(), mBottom[2].get());
int[] colors = {tTop, tBottom};
mBackground = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, colors);
mBackground.setCornerRadius(0f);
notifyChange();
}
public static void animateBackground(boolean tAnimate) {
mAnimate.set(tAnimate);
}
public static void notifyChange() {
if (mListener != null) mListener.onChange();
}
public interface ChangeListener {
void onChange();
}

Problems with Out of memory error

I get out of memory error if the function doesWifiExist is false if it is true every thing works normally.Can someone tell me what m i doing wrong
The idea is to get a list of wifi networks nearby and check if the inserted network exists in the list.
Here is the wifi network scanning code and the the function that checks if the wifi network exists.
MainActivity:
private WiFiConnection _wifiConnection = null;
static final int MY_PERMISSIONS_REQUEST = 1042;
private static final String PERMISSIONS_TAG = "PERMISSION";
...
#Override
protected void onStart() {
super.onStart();
_wifiConnection = new WiFiConnection(this);
startScan();
}
#Override
protected void onStop() {
super.onStop();
_wifiConnection.stopScan();
unregisterReceiver(_wifiScanReceiver);
}
void startScan() {
checkPermission(this);
registerReceiver(_wifiScanReceiver,
new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
Thread t = new Thread(_wifiConnection.getWifiScanner());
t.start();
}
private final BroadcastReceiver _wifiScanReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context c, Intent intent) {
if (intent.getAction().equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
if (_wifiConnection != null && _wifiConnection.isWifiEnabled()) {
_wifiConnection.updateScanData();
}
}
}
};
public static boolean checkPermission(Activity activity) {
boolean permission = true;
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
List<String> requiringList = new ArrayList<>();
permission = activity.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;
Log.d(PERMISSIONS_TAG, "ACCESS_COARSE_LOCATION: " + permission);
if (!permission) {
requiringList.add(Manifest.permission.ACCESS_COARSE_LOCATION);
}
if (requiringList.size() > 0) {
String[] stringArray = requiringList.toArray(new String[0]);
activity.requestPermissions(stringArray, MY_PERMISSIONS_REQUEST);
}
}
return permission;
}
private boolean doesWifiExist(String s){
String[] array = s.split(" ");
String ssid = array[0];
boolean flag = false;
//Check if wifi exists in the area
for(int i = 0 ; i < _wifiConnection.getListSSIDs().size(); i++){
if(_wifiConnection.getListSSIDs().get(i).equals(ssid)){
flag = true;
break;
}
}
return flag;
}
WiFiConnection class:
public class WiFiConnection
{
private static final int SCAN_INTERVAL = 5000;
final private List<String> _listSSIDs = new ArrayList<>();
private WifiManager _wifiManager;
private final WiFiScanner _startScan = new WiFiScanner();
private List<ScanResult> scanResults;
WiFiConnection(Activity activity) {
_wifiManager = (WifiManager) activity.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
}
//Puts wifi networks in a list
public List<String> getListSSIDs() {
for(int i = 0; i < scanResults.size(); i++)
{
_listSSIDs.add(scanResults.get(i).SSID);
}
return _listSSIDs;
}
WiFiScanner getWifiScanner() { return _startScan; }
void stopScan() { _startScan.stop(); }
boolean isWifiEnabled() { return _wifiManager.isWifiEnabled(); }
//Gets the wifi networks
void updateScanData() {
if ((_wifiManager != null && _wifiManager.isWifiEnabled())) {
scanResults = _wifiManager.getScanResults();
}
}
//Scans at an interval
private class WiFiScanner implements Runnable
{
private boolean _stop = false;
public void stop() {_stop = true;}
#Override
public void run() {
while (!_stop) {
_listSSIDs.clear();
_wifiManager.startScan();
try {
Thread.sleep(SCAN_INTERVAL);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
The code where doesWifiExist is used.
//Check if wifi exists in the area
if(doesWifiExist(barcode.displayValue)){
//Connects to wifi
WifiConnect(barcode.displayValue);
//Saves item in db
insertItem();
if(networkSecurity.equals("None")){
networkPass = empty;
}
//Adds item to recyclerview
historyItems.add(0, new HistoryItem(wifiName + " " + networkSSID, wifiPass + " " + networkPass));
adapter.notifyItemInserted(0);
} else
Snackbar.make(findViewById(R.id.main_activity), R.string.snackInvalidQrCode, Snackbar.LENGTH_SHORT).show();
This method is called many times, and it everytime adds all scanResults at the end of field _listSSIDS.
public List<String> getListSSIDs() {
for(int i = 0; i < scanResults.size(); i++)
{
_listSSIDs.add(scanResults.get(i).SSID);
}
return _listSSIDs;
}
Use a local variable with a new List or better Set there.
Instead replace
for(int i = 0 ; i < _wifiConnection.getListSSIDs().size(); i++){
if(_wifiConnection.getListSSIDs().get(i).equals(ssid)){
flag = true;
break;
}
}
with
flag = _wifiConnection.hasSSID(String ssid);
public boolean hasSSID(String ssid) {
for (int i = 0; i < scanResults.size(); i++) {
if (ssid.equals(scanResults.get(i).SSID)) {
return true;
}
}
return false;
}

Stuck in a loop, freezing the android app

I found out that when i pressed a button to run a while loop, the android app will freeze although the program can run. It seem that i stuck in a loop and i want to make a thread to show the GUI and the other for the main code . I'm new in java and i'm self-learned so i would appreciated if anyone could give me an example how to prevent the app from freezing.
I'm sorry if i didn't explain my problem well.
Thank you
Here is my code
public class TachoCount extends Thread {
public boolean isConnected;
protected static final String TAG = "TachoCount";
NXTConnector conn;
//_message = (TextView) findViewById(R.id.messageText);
//final TextView textView = (TextView) findViewById(R.id.textView1);
public static NXTConnector connect(final CONN_TYPE connection_type) {
Log.d(TAG, " about to add LEJOS listener ");
NXTConnector conn = new NXTConnector();
conn.setDebug(true);
conn.addLogListener(new NXTCommLogListener() {
public void logEvent(String arg0) {
Log.e(TAG + " NXJ log:", arg0);
}
public void logEvent(Throwable arg0) {
Log.e(TAG + " NXJ log:", arg0.getMessage(), arg0);
}
});
switch (connection_type) {
case LEGO_LCP:
conn.connectTo("btspp://NXT", NXTComm.LCP);
break;
case LEJOS_PACKET:
conn.connectTo("btspp://");
break;
}
return conn;
}
public TachoCount() {
}
public void closeConnection() {
try {
Log.d(TAG, "TachoCount run loop finished and closing");
conn.getNXTComm().close();
} catch (Exception e) {
} finally {
conn = null;
}
}
public void establishConnection(){
conn = TachoCount.connect(CONN_TYPE.LEGO_LCP);
NXTCommand.getSingleton().setNXTComm(conn.getNXTComm());
NXTInfo info = conn.getNXTInfo();
if (info.connectionState== NXTConnectionState.LCP_CONNECTED)
{
isConnected = true;
// set
//textView.setText("NXT is here");
}
}
public void forward(){
Motor.A.setSpeed(300);
Motor.C.setSpeed(300);
Motor.A.forward();
Motor.C.forward();
}
public void backward(){
Motor.A.setSpeed(300);
Motor.C.setSpeed(300);
Motor.A.backward();
Motor.C.backward();
}
public void byebye(){
Motor.A.stop();
Motor.C.stop();
}
public int getSensorValue()
{
int val = 0;
LightSensor ls = new LightSensor(SensorPort.S3);
val = ls.readValue();
return val;
}
public void linefollower()
{
run();
}
public void run()
{
int min = 30, max = 37, readLight = 0, Mspeed = 90, Mspeed2 = 20;
LightSensor ls = new LightSensor(SensorPort.S3);
while(true){
Motor.A.forward();
Motor.C.forward();
readLight = ls.readValue();
LeJOSDroid.sendMessageToUIThread("Sensor: "+ls.readValue());
if (readLight < min){
readLight = min+1;
}
if (max < readLight){
readLight = max-1;
}
Motor.C.setSpeed(Mspeed + (Mspeed2 * (readLight - min)));
Motor.A.setSpeed(Mspeed + (Mspeed2 * (max - readLight)));
}
}
i tried to change the code. It runs well (although the reading of the
sensor doesn't seem accurate), but then when i push another button,
nothing happens
public void linefollower()
{
Thread thread = new Thread(runnable);
thread.start();
}
Runnable runnable = new Runnable ()
{
public void run(){
int min = 30, max = 37, readLight = 0, Mspeed = 90, Mspeed2 = 20;
LightSensor ls = new LightSensor(SensorPort.S3);
while(true){
Motor.A.forward();
Motor.C.forward();
readLight = ls.readValue();
LeJOSDroid.sendMessageToUIThread("Sensor: "+ls.readValue());
if (readLight < min){
readLight = min+1;
}
if (max < readLight){
readLight = max-1;
}
Motor.C.setSpeed(Mspeed + (Mspeed2 * (readLight - min)));
Motor.A.setSpeed(Mspeed + (Mspeed2 * (max - readLight)));
}
}
};
Try using Runnable or background worker
Your loop looks infinite, it's always true. Also, it's probably better to do heavy tasks in an asynctask activity.
Check the official info: http://developer.android.com/reference/android/os/AsyncTask.html

Categories

Resources