IllegalMonitorStateException when using locks and conditions in Android app - java

I am trying to familiarize myself with Java Conditions.
Purpose:
Using the following code, I created a simple counter app that races to the stars after clicking start. You can start/stop, pause/resume the counter.
The intended purpose is (for me) to allow a function(s) to run as long as the lock is not locked. The moment the lock is locked, the incrementing should stop until resume is clicked.
Looking over this example and this SO question, I tried to implement my own version - this is not successful.
Problem:
Clicking start, the counter runs. The moment I hit pause, the lock locks correctly but an java.lang.IllegalMonitorStateException occurs when the executor runnable hits the waitCondition.await(); line.
Stack Trace:
E/AndroidRuntime: FATAL EXCEPTION: ForkJoinPool-1-worker-1
Process: nmu.wrpv302.myapplication, PID: 11744
java.lang.IllegalMonitorStateException
at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:156)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1291)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.fullyRelease(AbstractQueuedSynchronizer.java:1752)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2064)
at com.example.myapplication.MainActivity.lambda$start$2$MainActivity(MainActivity.java:61)
^ --------------------- PROBLEM -----------------------
at com.example.myapplication.-$$Lambda$MainActivity$te94WnCx7dwprXfxnjJZuoEc1_8.run(Unknown Source:4)
at java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1411)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:285)
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1155)
at java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1993)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1941)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
Activity Code:
public class MainActivity extends AppCompatActivity {
private TextView lblCounter;
private Button btnStartStop, btnPauseResume;
private ReentrantLock pauseLock = new ReentrantLock();
private Condition waitCondition = pauseLock.newCondition();
private ExecutorService executorService = Executors.newWorkStealingPool(4);
private AtomicBoolean stopStart = new AtomicBoolean(true);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lblCounter = findViewById(R.id.counter);
btnStartStop = findViewById(R.id.startStop);
btnPauseResume = findViewById(R.id.pauseResume);
btnStartStop.setOnClickListener(v -> {
if (stopStart.get()) {
start();
} else {
stop();
}
});
btnPauseResume.setOnClickListener(v -> {
pauseResume();
});
}
public void start() {
btnStartStop.setText("Stop");
AtomicInteger i = new AtomicInteger(0);
executorService.execute(() -> {
while (true) {
while (pauseLock.isLocked()) {
try {
waitCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int i1 = i.incrementAndGet();
lblCounter.setText(String.valueOf(i1));
}
});
}
public void stop() {
executorService.shutdownNow();
btnStartStop.setText("Start");
}
public void pauseResume() {
if (pauseLock.isLocked()) {
pauseLock.unlock();
waitCondition.signal();
btnPauseResume.setText("Pause");
} else {
pauseLock.lock();
btnPauseResume.setText("Resume");
}
}
}
Activity XML:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="#+id/counter"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="96dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="96dp"
android:text="123"
android:textColor="#000000"
android:textSize="36sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textView" />
<Button
android:id="#+id/startStop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="128dp"
android:text="Start"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/pauseResume"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="#+id/pauseResume"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Pause"
app:layout_constraintBottom_toBottomOf="#+id/startStop"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="#+id/startStop" />
<TextView
android:id="#+id/textView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="96dp"
android:layout_marginTop="128dp"
android:layout_marginEnd="96dp"
android:text="Counter"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

You can’t unlock the lock and then signal using it. The lock has to be held by the thread that calls await or signal on the lock’s conditions. The api doc says:
The current thread is assumed to hold the lock associated with this Condition when this method is called.
Not having that lock held leads to the exception being thrown.
That means you can’t use the isLocked check to decide if you’re done waiting. If you look at the code example on the linked question it shows that put and take each use their own condition, and they test variables indicating the buffer’s current state in order to decide whether to wait or signal.

Related

Observable DataBinding ObservableInt vs. LiveData with different results On Confguration change

I am testing the behavior of DataBinding observable when it comes to use a LiveData vs. ObservableInt.
I have simple layout with a button that triggers a counter for both LiveData & ObservableInt variables that I store in the ViewModel, I update their values using BindingAdapter
Both LiveData & ObservableInt variables count up normally; but when there is a device configuration change (screen rotation for my test), the ObservableInt countinues count up with button hits, although the LiveData dismisses one or two counts.
Below gif will illustrate more
My question is how to solve this problem?
I mainly need a LiveData for further Transformations
Layout
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="viewmodel"
type="com.example.android.databindingobservableintlivedata.MyViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<TextView
android:id="#+id/observableint_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ObservableInt: " />
<TextView
android:id="#+id/observableint_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
app:textValueForObservableInt="#{viewmodel.countObservableInt}" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="center">
<TextView
android:id="#+id/livedata_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="LiveData: " />
<TextView
android:id="#+id/livedata_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
app:textValueForLiveData="#{viewmodel.countLiveData}" />
</LinearLayout>
<Button
android:id="#+id/btn_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="16dp"
android:onClick="#{() -> viewmodel.onCount()}"
android:text="Count" />
</LinearLayout>
</layout>
Activity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
MyViewModel viewModel = ViewModelProviders.of(this).get(MyViewModel.class);
mBinding.setViewmodel(viewModel);
mBinding.setLifecycleOwner(this);
}
}
ViewModel
public class MyViewModel extends ViewModel {
public MutableLiveData<Integer> countLiveData = new MutableLiveData<>(0);
public ObservableInt countObservableInt = new ObservableInt(0);
public void onCount() {
countObservableInt.set(countObservableInt.get() + 1);
int value = countLiveData.getValue() == null ? 0 : countLiveData.getValue();
countLiveData.postValue(value + 1);
}
}
BindingAdapters
public class BindingAdapters {
#BindingAdapter("textValueForObservableInt")
public static void bindObservableIntInText(TextView text, ObservableInt value) {
text.setText(String.valueOf(value.get()));
}
#BindingAdapter("textValueForLiveData")
public static void bindLiveDataIntegerInText(TextView text, MutableLiveData<Integer> value) {
text.setText(String.valueOf(value.getValue()));
}
}
Post value of LiveData:
Basically this method indicates that, any value given to LiveData can be/should be called from background thread (other than main thread) would reflect on main thread with updated value.
Meaning that, if you've got two consecutive calls to LiveData about postValue() then only last value would be dispatched!
In your case, countLiveData.postValue(value + 1) this line gets impacted on post-increment of value if there're too frequent calls to this method, which in case only gets updated for last value but not on consecutive ones.
Set Value of LiveData:
This method requires that call must be made from Main thread, resulting UI gets reflected/updated every time no matter how many calls you've made. None of intermediate calls get discarded.
TL;DR
If you've to update/set value from background thread then use postValue() method otherwise use setValue() when on Main thread.
It takes a while for device rotation when I have continuous hits on the button, and suddenly rotate the device.
Reason is that when you call setValue() on main thread before rotating device, each calls must update the UI consecutively, resulting delay on rotation stuff (Holds the UI updates before configuration change happen). That's why it lags/delay on rotation before all setValue() call completes UI updates (this line in your particular case: app:textValueForLiveData="#{viewmodel.countLiveData}").

setText function does not change the TextView

the app runs the way I want I can see that in the Logcat
but the text view is not changing and keeps the default value
i also tried to change button enable status programmatically but stayed in the same , nothing get changed !!
I tried in the setText method both
String.valueof(int)
and
Integer.toString(int)
java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
play =(Button) findViewById(R.id.button4);
Pause =(Button) findViewById(R.id.button5);
hourstext =(TextView) findViewById(R.id.textView1);
mintext =(TextView) findViewById(R.id.textView2);
sectext =(TextView) findViewById(R.id.textView3);
}
void playb(View v) {
while (!ispause) {
sec = 0 ;
while (sec < 60) {
SystemClock.sleep(1000);
sec++;
sectext.setText(Integer.toString(sec));
Log.d("this", "sec value=" + sec);
}
sec = 0;
min++;
Log.d("this","min value ="+min);
mintext.setText(String.valueOf(min));
}
}
XML
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="#+id/textView3"
android:layout_width="114dp"
android:layout_height="94dp"
android:layout_marginTop="159dp"
android:layout_marginEnd="16dp"
android:layout_x="274dp"
android:layout_y="120dp"
android:gravity="center|center_horizontal"
android:text="00"
android:textSize="40sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/pauseButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="72dp"
android:layout_marginTop="116dp"
android:layout_marginEnd="93dp"
android:layout_x="217dp"
android:layout_y="296dp"
android:enabled="false"
android:onClick="playb"
android:text="Pause"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/playbutton"
app:layout_constraintTop_toBottomOf="#+id/textView3" />
<Button
android:id="#+id/playbutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="70dp"
android:layout_marginTop="116dp"
android:layout_x="63dp"
android:layout_y="293dp"
android:onClick="playb"
android:text="playb"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textView2" />
<TextView
android:id="#+id/textView2"
android:layout_width="120dp"
android:layout_height="97dp"
android:layout_marginTop="156dp"
android:layout_marginEnd="17dp"
android:layout_x="139dp"
android:layout_y="117dp"
android:gravity="center|center_horizontal"
android:text="00"
android:textSize="40sp"
app:layout_constraintEnd_toStartOf="#+id/textView3"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/textView1"
android:layout_width="103dp"
android:layout_height="94dp"
android:layout_marginStart="16dp"
android:layout_marginTop="159dp"
android:layout_x="11dp"
android:layout_y="117dp"
android:gravity="center_horizontal|center_vertical"
android:text="00"
android:textSize="40sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
i get no error message ! the app keeps working but no updated textView
i've included my XML Code
It's likely to do with running everything on the main thread. You should never call sleep on the main thread or you will block the UI.
When the button is clicked you should start the counter on a background thread. You will then need to update the TextView on the main thread.
It can be achieved quite easily with RxJava:
private Disposable disposable;
disposable = Observable.interval(1, 1, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(value -> {
// Update UI
});
To stop the counter:
disposable.dispose();
If you want make counter up for 60 sec you can use this code
long time=60;
new CountDownTimer(time*1000, 1000)
{
public void onTick(long millisUntilFinished) {
mTextField.setText("seconds : " + (time-millisUntilFinished /1000));
}
public void onFinish() {
mTextField.setText("done!");
}
}.start();
Before trying to fix this problem, let first understand why it happens
CAUSE
When you call View.setText(), Android doesn't actually set the text immediately. It pushes all of these set-text works to a queue on main thread to do LATER whenever it has free time.
Let's try to run this block, you will notice that until this while loop finish, View.setText() will not be done.
void playb(View v) {
min = 0
while (min < 1000000) {
min++
Log.d("this", "min value =$min")
mintext.setText(String.valueOf(min))
}
}
So in your situtation, actually the TextView will still be set, but you will not see the change until the while loop finishes.
SOLUTION
You should move this while loop to another thread, you can simply use an AsyncTask or a HandlerThread for that
Ex. Use a HandlerThread:
void playb() {
// Start a new background thread
HandlerThread thread = new HandlerThread("");
thread.start();
// Obtain the handler of new background thread
Handler handler = new Handler(thread.getLooper());
// Obtain the handler of main thread (UI Thread)
final Handler mainHandler = new Handler(this.getMainLooper());
// Create a runnable and send it to background thread to execute
handler.post(new Runnable() {
public final void run() {
// Do the job
int min = 0;
while(true) {
int sec = 0;
while(sec < 60) {
SystemClock.sleep(1000L);
sec ++;
final int currentSec = sec;
// Send the update-text job to main thread to execute
mainHandler.post(new Runnable() {
public final void run() {
secText.setText(currentSec);
}
});
}
sec = 0;
min++;
final int currentMin = min;
// Send the update-text job to main thread to execute
mainHandler.post(new Runnable() {
public final void run() {
minText.setText(currentMin);
}
});
}
}
});
}

Progress Bar is not showing up when visibility is changed to visible in java code

I'm making progress bar visible and invisible in async task. I'm doing some db operations in async task while doing operations I want to show progressdialog. as soon as it finishes its operation. I want to make it invisible. My code is below. Problem is progresssbar does not show up.
activity_xml code:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_course_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="info.lms.CourseList">
<!-- The ActionBar displayed at the top -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include
layout="#layout/tool_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/course_list"></ListView>
</LinearLayout>
<ProgressBar
android:id="#+id/progressBar"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true" />
</RelativeLayout>
I'm using an async task where I want to make progress bar visible and invisible
private class tmpCourseOfferingTask extends AsyncTask<String,Void,JSONObject> {
public tmpCourseOfferingTask(){
super();
}
#Override
protected void onPreExecute(){
super.onPreExecute();
progressBar.setVisibility(View.VISIBLE);
}
#Override
protected JSONObject doInBackground(String...params){
return null;
}
#Override
protected void onPostExecute(JSONObject json) {
Thread.sleep(5000);
} catch (JSONException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
progressBar.setVisibility(View.GONE);
}
First, remove the Thread.Sleep(millis) from onPostExecute and put it in the doInBackground. onPostExecute, as onPreExecute, runs on the main thread so the sleep should be put in the background process.
your flow (at the moment) is this:
asynctask created
pre-execute = progressbar visible
onbackground = nothing
post-execute = thread sleep. --> this is stopping the UI thread and the view has no time to update the visibility because it's stopped
progressbar = View.GONE.
This is not showing the progress because the thread is being stopped immediatly and the View changes are applied once after a return. I use the code as below and it works for me.
Another thing is that your catch is without a try (?) so this code is missing something or is not working. With those two fixes it will work. do something like:
private class tmpCourseOfferingTask extends AsyncTask<String,Void,JSONObject> {
public tmpCourseOfferingTask(){
super();
}
#Override
protected void onPreExecute(){
super.onPreExecute();
progressBar.setVisibility(View.VISIBLE);
}
#Override
protected JSONObject doInBackground(String...params){
try{
SystemClock.sleep(timeInMills);
}catch(Exception ignored){
}finally{
return null;
}
}
#Override
protected void onPostExecute(JSONObject json) {
progressBar.setVisibility(View.GONE);
}
}
Another fix:
You have a RelativeLayout with a LinearLayout and a progressbar.. also the progressbar should be with visibility "GONE" so that the view space is not kept used. You can remove the useless LinearLayout and do something like this:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_course_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="info.lms.CourseList">
<include
amdrpod:id="#+id/includeId"
layout="#layout/tool_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ListView
android:layout_below="#+id/includeId"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/course_list"/>
<ProgressBar
android:id="#+id/progressBar"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:layout_centerInParent="true" />
</RelativeLayout>
(wrote by hand, might be not perfect)
To make sure to see the ProgressBar use bringToFront() at PreExecute() like this:
progressBar.bringToFront();
btw I think Pier's answer should do the trick.
Try to wrap your Progressbar inside linerlayout like below and then check show and hide functionality and use the liner layout ID to show and hide.
<LinearLayout
android:id="#+id/Progress"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone" >
<ProgressBar
android:id="#+id/progressBar"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true" />
</LinearLayout>

AsyncTask FATAL EXCEPTION when calling a method from doInBackground

None of the answers to questions on this topic have solved the issue for my specific case.
My app is hogging memory and causing the main thread to be unresponsive. I am using a listener to monitor Telephony states. When the state changes (or once per second) I want to grab the parameter associated and update a TextView with its value. I have tried using Threads and Runnables but the performance still sucks. Now I am trying AsyncTask but I don't understand it. I want this activity to run for at least 15 minutes with the listener running that whole time in the background; and once per second I want the values grabbed with the listener to be used to update TextViews on the UI thread.
public class Second extends Activity {
SignalStrengthListener signalStrengthListener;
TextView lteRsrp;
TextView lteRsrq;
TextView cellPciTextView;
Button startButton;
TelephonyManager tm;
List<CellInfo> cellInfoList;
String lte1, lte2;
int cellPci = 0;
// List<String[]> data;
// #Override
// public void run() {
// // Moves the current Thread into the background
// android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
// startTele();
//
// }
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_activity);
setupUI();
// run();
new MyAsyncTask().execute();
setupButton();
}
public class SignalStrengthListener extends PhoneStateListener {
#Override
public void onSignalStrengthsChanged(android.telephony.SignalStrength signalStrength) {
//++++++++++++++++++++++++++++++++++
((TelephonyManager) getSystemService(TELEPHONY_SERVICE)).listen(signalStrengthListener, SignalStrengthListener.LISTEN_SIGNAL_STRENGTHS);
tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
String ltestr = signalStrength.toString();
String[] parts = ltestr.split(" ");
lte1 = parts[9];
lte2 = parts[10];
try {
cellInfoList = tm.getAllCellInfo();
for (CellInfo cellInfo : cellInfoList) {
if (cellInfo instanceof CellInfoLte) {
// cast to CellInfoLte and call all the CellInfoLte methods you need
// Gets the LTE PCI: (returns Physical Cell Id 0..503, Integer.MAX_VALUE if unknown)
cellPci = ((CellInfoLte) cellInfo).getCellIdentity().getPci();
}
}
} catch (Exception e) {
Log.d("SignalStrength", "+++++++++++++++++++++++++++++++ null array spot 3: " + e);
}
// lteRsrp.setText(String.valueOf(lte1));
// lteRsrq.setText(String.valueOf(lte2));
// cellPciTextView.setText(String.valueOf(cellPci));
super.onSignalStrengthsChanged(signalStrength);
//++++++++++++++++++++++++++++++++++++
}
}
private void setupUI() {
lteRsrp = (TextView) findViewById(R.id.lteRsrp);
lteRsrq = (TextView) findViewById(R.id.lteRsrq);
cellPciTextView = (TextView) findViewById(R.id.cellPciTextView);
startButton = (Button) findViewById(R.id.startButton);
}
public void startTele() {
//start the signal strength listener
signalStrengthListener = new SignalStrengthListener();
((TelephonyManager) getSystemService(TELEPHONY_SERVICE)).listen(signalStrengthListener, SignalStrengthListener.LISTEN_SIGNAL_STRENGTHS);
tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
try {
cellInfoList = tm.getAllCellInfo();
} catch (Exception e) {
Log.d("SignalStrength", "+++++++++++++++++++++++++++++++++++++++++ null array spot 1: " + e);
}
}
private void setupButton() {
startButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getBaseContext(),Third.class);
startActivity(intent);
}
});
}
//??????????????????????????????????????????????????????????????????????????????????????????????
public class MyAsyncTask extends AsyncTask<Void, Void, Void> {
// WeakReference<TextView> lteRsrpWRef, lteRsrqWRef, ltePciWRef;
// public MyAsyncTask(TextView lteRsrp, TextView lteRsrq, TextView cellPciTextView) {
// lteRsrpWRef = new WeakReference<TextView>(lteRsrp);
// lteRsrqWRef = new WeakReference<TextView>(lteRsrq);
// ltePciWRef = new WeakReference<TextView>(cellPciTextView);
//
// }
#Override
public Void doInBackground(Void... params) {
startTele();
return null;
}
#Override
public void onPostExecute(Void aVoid) {
//super.onPostExecute(aVoid);
lteRsrp.setText(String.valueOf(lte1));
lteRsrq.setText(String.valueOf(lte2));
cellPciTextView.setText(String.valueOf(cellPci));
}
}
//??????????????????????????????????????????????????????????????????????????????????????????????
}
My attempt to use AsyncTask is at the bottom enclosed by "//????????????". I simply want to call startTele() which then calls the SignalStrengthListener from the doInBackground() in AsyncTask so that all that code will be run on a background thread. Then I want to get the values String lte1, String lte2, and int cellPci and use them to update TextView lteRsrp, lteRsrq, cellPciTextView; on the UI thread.
Here is my XML for Second.class:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffdc1d">
<TextView
android:layout_width="210dp"
android:layout_height="wrap_content"
android:text="0"
android:textSize="22sp"
android:textColor="#000000"
android:id="#+id/lteRsrp"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:layout_marginStart="29dp"
android:layout_marginTop="80dp"
android:textAlignment="textEnd"
android:background="#ffdc1d"
android:textStyle="bold"
android:layout_marginBottom="20dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="= LTE RSRP"
android:textSize="22sp"
android:textColor="#000000"
android:id="#+id/textView2"
android:background="#ffdc1d"
android:textStyle="bold"
android:layout_alignTop="#+id/lteRsrp"
android:layout_toEndOf="#+id/startButton"
android:layout_marginBottom="20dp" />
<TextView
android:layout_width="210dp"
android:layout_height="wrap_content"
android:text="0"
android:textColor="#a71b1b"
android:textSize="22sp"
android:id="#+id/lteRsrq"
android:layout_below="#+id/lteRsrp"
android:layout_alignStart="#+id/lteRsrp"
android:textAlignment="textEnd"
android:textStyle="bold"
android:background="#ffdc1d"
android:layout_marginBottom="20dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="= LTE RSRQ"
android:textSize="22sp"
android:textColor="#a71b1b"
android:id="#+id/textView3"
android:layout_below="#+id/textView2"
android:layout_alignStart="#+id/textView2"
android:textStyle="bold"
android:background="#ffdc1d"
android:layout_marginBottom="20dp" />
<TextView
android:layout_width="210dp"
android:layout_height="wrap_content"
android:text="0"
android:textSize="22sp"
android:textColor="#075f09"
android:id="#+id/cellPciTextView"
android:layout_below="#+id/lteRsrq"
android:layout_alignStart="#+id/lteRsrq"
android:textAlignment="textEnd"
android:background="#ffdc1d"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="= LTE PCI"
android:textSize="22sp"
android:textColor="#075f09"
android:id="#+id/textView4"
android:layout_below="#+id/textView3"
android:layout_alignStart="#+id/textView3"
android:background="#ffdc1d"
android:textStyle="bold" />
<Button
android:layout_width="120dp"
android:layout_height="wrap_content"
android:text="Start"
android:textColor="#ffdc1d"
android:textSize="22sp"
android:id="#+id/startButton"
android:layout_marginBottom="47dp"
android:background="#f91616"
android:textAlignment="center"
android:textStyle="bold"
android:padding="4dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Press the START button to begin recording"
android:id="#+id/textView8"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:textColor="#f91616"
android:textSize="22sp"
android:textStyle="italic"
android:textAlignment="center"
android:layout_marginTop="12dp" />
</RelativeLayout>
And here is my logcat messages:
So, how can I run my telephony listener in the background for 15 minutes while grabbing the LTE parameters RSRP, RSRQ, and PCI and updating the TextViews on the UI thread with these values once per second?

Flipping to next screen shows black color in background

In vertical flip effect,when flip to next screen the background shows black color it happens only in GT_N7100 mobile...How to fix this problem???can anyone please help me...
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#android:color/white"
android:orientation="vertical"
>
<ImageView
android:id="#+id/bar"
android:layout_width="480dp"
android:layout_height="1dp"
android:layout_marginTop="36dp"
android:scaleType="fitXY"
android:src="#drawable/line" />
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/bar"
android:layout_margin="5dp"
android:textAppearance="#android:style/TextAppearance.Medium"
android:textColor="#android:color/black"
android:textSize="20sp"
android:textStyle="bold"
/>
<ImageView
android:id="#+id/photo"
android:layout_width="fill_parent"
android:layout_height="330dp"
android:layout_below="#+id/title"
android:layout_gravity="center_horizontal"
android:layout_margin="5dp"
android:layout_marginTop="5dp"
android:scaleType="centerCrop" />
If you are performing any heavy task on main thread in onCreate() method, that might block the onCreate() UI; to avoid this issue you can run a separate thread for this task.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splace_layout);
mContext = this;
Thread th = new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
try {
mTask();
} catch (Exception e) {
// TODO: handle exception
}
}
});
th.start();
}

Categories