I am trying to create textview in android which display the remaining time(seconds).
Have used runOnUiThread and Hadnler for this and everything seems working fine(sysout and debug shows that both threads are executed and value is updated properly).
However, on UI the textview value is not updated properly. It gets updated with last value when the thread completes.
I am writing the below code inside private method of the fragment.
final TextView timerText = (TextView) mainView.findViewById(R.id.timerText);
timerText.setText(R.string.maxAllowedSeconds);
handler.post(new Runnable() {
#Override
public void run() {
while(true)
{
System.out.println("Text:"+ ""+maxAllowedSeconds);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
maxAllowedSeconds--;
if(maxAllowedSeconds <= 0)
break;
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
System.out.println("Running on UI Thread : " + maxAllowedSeconds);
timerText.setText("" + maxAllowedSeconds);
}
});
}
}
});
Gone through many of the previous questions in this area but none seems to have concrete solutions for this problem.
Thanks in advance.
SOLUTOIN:
Finally I used AsynchTask which worked perfectly as expected.
private class RapidFireAsyncTimerTask extends AsyncTask<Integer, Integer, Void> {
private Context context;
private View rootView;
public RapidFireAsyncTimerTask(Context ctx, View rootView) {
this.context = ctx;
this.rootView = rootView;
}
#Override
protected Void doInBackground(Integer... params) {
int maxSec= params[0];
while (true) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
publishProgress(--maxSec);
if (maxSec <= 0)
break;
}
return null;
}
#Override
protected void onProgressUpdate(final Integer... values) {
((TextView) rootView.findViewById(R.id.timerText)).setText("" + values[0]);
}
#Override
protected void onPostExecute(Void aVoid) {
//next task
}
}
Instead of Handler, it worked with AsynchTask(No runOnUiThread needed).
public RapidFireAsyncTimerTask(Context ctx, View rootView) {
this.context = ctx;
this.rootView = rootView;
}
#Override
protected Void doInBackground(Integer... params) {
int maxSec= params[0];
while (true) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
publishProgress(--maxSec);
if (maxSec <= 0)
break;
}
return null;
}
#Override
protected void onProgressUpdate(final Integer... values) {
((TextView) rootView.findViewById(R.id.timerText)).setText("" + values[0]);
}
#Override
protected void onPostExecute(Void aVoid) {
//next task
}
}
Related
Recently I am working on a Flutter plugin for my project. My plugin requires startActivityForResult but can't figure out how to use it according to Flutter plugin development. I have given my code below.
public class MyPlugin implements FlutterPlugin, MethodCallHandler {
private static final int REQUEST_CODE = 1;
Result result;
#Override
public void onAttachedToEngine(#NonNull FlutterPluginBinding flutterPluginBinding) {
channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "my_plugin");
channel.setMethodCallHandler(this);
}
#Override
public void onDetachedFromEngine(#NonNull FlutterPluginBinding binding) {
channel.setMethodCallHandler(null);
}
#Override
public void onMethodCall(#NonNull MethodCall call, #NonNull Result result) {
this.result = result;
if (call.method.equals("myMethod")) {
myMethod();
} else {
result.notImplemented();
}
}
private void myMethod() {
// my intent instance will be here
startActivityForResult(intent, REQUEST_CODE); // Cannot resolve method 'startActivityForResult'
}
#Override
public boolean onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
try {
if (requestCode == REQUEST_CODE) {
result.success("done");
} else {
result.error("Something went wrong", null, null);
}
} catch (Exception e) {
Log.e(TAG, "Exception: " + e.toString());
}
return false;
}
}
Try this solution to get the Context. After, call the intent using the Context:
private void myMethod() {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
//Here is my code
package name.ratson.cordova.admob.rewardvideo;
import android.util.Log;
import com.google.android.gms.ads.reward.RewardItem;
import com.google.android.gms.ads.reward.RewardedVideoAdListener;
import org.json.JSONException;
import org.json.JSONObject;
import name.ratson.cordova.admob.AbstractExecutor;
class RewardVideoListener implements RewardedVideoAdListener {
private final RewardVideoExecutor executor;
RewardVideoListener(RewardVideoExecutor executor) {
this.executor = executor;
}
#Override
public void onRewardedVideoAdFailedToLoad(int errorCode) {
synchronized (executor.rewardedVideoLock) {
executor.isRewardedVideoLoading = false;
}
JSONObject data = new JSONObject();
try {
data.put("error", errorCode);
data.put("reason", AbstractExecutor.getErrorReason(errorCode));
data.put("adType", executor.getAdType());
} catch (JSONException e) {
e.printStackTrace();
}
executor.fireAdEvent("admob.rewardvideo.events.LOAD_FAIL", data);
}
#Override
public void onRewardedVideoAdLeftApplication() {
JSONObject data = new JSONObject();
try {
data.put("adType", executor.getAdType());
} catch (JSONException e) {
e.printStackTrace();
}
executor.fireAdEvent("admob.rewardvideo.events.EXIT_APP", data);
}
#Override
public void onRewardedVideoAdLoaded() {
synchronized (executor.rewardedVideoLock) {
executor.isRewardedVideoLoading = false;
}
Log.w("AdMob", "RewardedVideoAdLoaded");
executor.fireAdEvent("admob.rewardvideo.events.LOAD");
if (executor.shouldAutoShow()) {
executor.showAd(true, null);
}
}
#Override
public void onRewardedVideoAdOpened() {
executor.fireAdEvent("admob.rewardvideo.events.OPEN");
}
#Override
public void onRewardedVideoStarted() {
executor.fireAdEvent("admob.rewardvideo.events.START");
}
#Override
public void onRewardedVideoAdClosed() {
executor.fireAdEvent("admob.rewardvideo.events.CLOSE");
executor.clearAd();
}
#Override
public void onRewarded(RewardItem reward) {
JSONObject data = new JSONObject();
try {
data.put("adType", executor.getAdType());
data.put("rewardType", reward.getType());
data.put("rewardAmount", reward.getAmount());
} catch (JSONException e) {
e.printStackTrace();
}
executor.fireAdEvent("admob.rewardvideo.events.REWARD", data);
}
}
your RewardVideoListener class is implementing RewardedVideoAdListener in interface.
In order to compile with the RewardedVideoAdListener interface you need to implement all the interface methods including RewardedVideoAdListener.
So add this to your class:
#Override
public void onRewardedVideoCompleted() {
Toast.makeText(this, "onRewardedVideoCompleted", Toast.LENGTH_SHORT).show();
}
For Cordova projects - TOAST was undefined. This helped...
#Override
public void onRewardedVideoCompleted() {
fireAdEvent(EVENT_AD_WILLDISMISS, ADTYPE_REWARDVIDEO);
}
I am creating an app which required to perform from API 15 to API 23 using camera so what should be the best way to implement camera as camera class is deprecated in API 21 and also android.hardware.camera2 not able to implement on lower version then API 21.
The below code is something I have taken out of one of my projects, it has had a lot of stuff ripped out for the purpose of putting it on here so you will have to edit it for your needs. It uses the original camera api which is back compatible for your api needs.
public class RecordGameKam extends Fragment
implements TextureView.SurfaceTextureListener, View.OnClickListener {
private final static String TAG = "CameraRecordTexture";
private Camera mCamera;
private TextureView mTextureView;
int numberOfCameras;
int defaultCameraId;
private boolean isRecording = false;
protected MediaRecorder mediaRecorder;
#SuppressWarnings("ConstantConditions")
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
View rootView = new RelativeLayout(getActivity());
mTextureView = new TextureView(getActivity());
mTextureView.setSurfaceTextureListener(this);
//View parameters-----------------------------------------------------------------------
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
rootView.setLayoutParams(params);
((ViewGroup) rootView).addView(mTextureView);
return rootView;
}
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
// Find the total number of cameras available
numberOfCameras = Camera.getNumberOfCameras();
// Find the ID of the default camera
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
for (int i = 0; i < numberOfCameras; i++) {
Camera.getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
defaultCameraId = i;
}
}
try {
if (mCamera != null) {
//final Camera.Size previewSize = onMeasure();
//Camera.Size recorderSize = previewSize;
final Camera.Parameters params = mCamera.getParameters();
params.setPreviewSize(720, 480);
mCamera.setParameters(params);
mCamera.setDisplayOrientation(90);
mCamera.setPreviewTexture(surface);
mCamera.startPreview();
startContinuousAutoFocus();
}
} catch (IOException ioe) {
// Something bad happened
mCamera.release();
mCamera = null;
}
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
// Ignored, Camera does all the work for us
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
try {
if (getActivity().getActionBar() != null) {
getActivity().getActionBar().show();
}
} catch (Exception e) {
e.printStackTrace();
}
releaseMediaRecorder();
return true;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
// Invoked every time there's a new Camera preview frame
}
private boolean setMediaRecorder() throws IllegalStateException {
try {
//Create a new instance of MediaRecorder.
mediaRecorder = new MediaRecorder();
//Unlock and set camera to Media recorder
mCamera.unlock();
mediaRecorder.setCamera(mCamera);
//Configure audio/video input
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
CamcorderProfile profile = null;
if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_480P)) {
profile = CamcorderProfile.get(CamcorderProfile.QUALITY_480P);
}
if (profile != null) {
mediaRecorder.setProfile(profile);
}
//Change oritentation
mediaRecorder.setOrientationHint(90 - 180 + 360);
mediaRecorder.setOutputFile(getFilename());
} catch (Exception e) {
e.printStackTrace();
}
//Attempt to prepare the configuration and record video.
try {
button.setBackgroundResource(R.drawable.camera_pressed);
mediaRecorder.prepare();
} catch (Exception e) {
e.printStackTrace();
mediaRecorder.release();
return false;
}
return true;
}
boolean startContinuousAutoFocus() {
Camera.Parameters params = mCamera.getParameters();
List<String> focusModes = params.getSupportedFocusModes();
assert focusModes != null;
String CAF_PICTURE = Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE,
CAF_VIDEO = Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO,
supportedMode = focusModes
.contains(CAF_PICTURE) ? CAF_PICTURE : focusModes
.contains(CAF_VIDEO) ? CAF_VIDEO : "";
if (!supportedMode.equals("")) {
params.setFocusMode(supportedMode);
mCamera.setParameters(params);
return true;
}
return false;
}
#Override
public void onResume() {
super.onResume();
}
#Override
public void onPause() {
super.onPause();
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
enter code here
It is possible to show progress dialog when loading the .obj model. I tried to call the ProgressDialog in RajawaliVuforiaExampleRenderer.java but it said "Can't create handler inside thread that has not called Looper.prepare()"
I have pasted part of the code here:
protected void initScene() {
mLight = new DirectionalLight(.1f, 0, -1.0f);
mLight.setColor(1.0f, 0, 0);
mLight.setPower(1);
getCurrentScene().addLight(mLight);
LoaderOBJ objParser = new LoaderOBJ(mContext.getResources(),
mTextureManager, R.raw.wall_obj);
try {
// Load model
objParser.parse();
wall = objParser.getParsedObject();
addChild(wall);
} catch (Exception e) {
e.printStackTrace();
}
}
EDITED:
I have read the comment from Abhishek Agarwal and updated the code for Renderer part, now i having problem on calling the ProgressDialog when loading the model, here is my code for the UI thread.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
// receive file path
String filePath = this.getIntent().getStringExtra("FullFilePath");
Log.i(filePath, "FullFilePath:" + filePath);
waitDialog = ProgressDialog.show(this, "", "Loading", true);
waitDialog.show();
new ModelLoader().execute();
}
#Override
protected void setupTracker() {
int result = initTracker(TRACKER_TYPE_MARKER);
if (result == 1) {
result = initTracker(TRACKER_TYPE_IMAGE);
if (result == 1) {
super.setupTracker();
} else {RajLog.e("Couldn't initialize image tracker.");
}
} else {
RajLog.e("Couldn't initialize marker tracker.");
}}
protected void initApplicationAR() {
super.initApplicationAR();
createImageMarker("marker.xml");
}
protected void initRajawali() {
super.initRajawali();
mRenderer = new ModelRenderer(this);
mRenderer.setSurfaceView(mSurfaceView);
super.setRenderer(mRenderer);
mUILayout = this;
mUILayout.setContentView(mLayout, new LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
}
private class ModelLoader extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
startVuforia();
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
waitDialog.dismiss();
}
}
Progress Dialog can be shown on the UIThread. So show progress dialog on the main thread not under GLThread
You can use Handler to be on threadUI :
`private Handler mHandler = new Handler();
...
mHandler.post(new Runnable() {
#Override
public void run() {
view_progressBar.setProgress(val);
}
});`
My app is able to receive messages from GCM and saves the messages to the SQLlite database on the phone. The messages are viewable in a activity that has a listview.
In the code below, the onPause() function refreshes the listView. This is not a good implementation because it only works if the activity is not displayed at the time of the update. If the activity is displayed at the time of an update, the list is static and does not update.
Questions:
How to I update the listview when the activity is being displayed? Or is there a way to use a background service to update the adapter, so that whenever the activity is displayed, it always shows the newest data.
is this kind of functionality currently not possible with android and I'll need to implement something else like 'pull-to-refresh'?
refreshing listview in OnResume() crashes the application, and shows a null pointer exception.
Activity:
public class NotesView extends Activity implements OnItemClickListener {
ListView listView;
NoteAdapter objAdapter;
NotificationsDatabase db = new NotificationsDatabase(this);
List<Notes> listAlerts;
String note;
String time;
TextView noteView;
TextView timeView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.note);
listView = (ListView) findViewById(R.id.notelist);
listView.setOnItemClickListener(this);
noteView = (TextView) findViewById(R.id.noteDisplay);
timeView = (TextView) findViewById(R.id.notetimeStampDisplay);
new MyTask().execute();
}
// My AsyncTask start...
class MyTask extends AsyncTask<Void, Void, List<Notes>> {
ProgressDialog pDialog;
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(NotesView.this);
pDialog.setMessage("Loading...");
pDialog.setCancelable(false);
pDialog.show();
if (isCancelled()) {
this.cancel(true);
}
}
#Override
protected List<Notes> doInBackground(Void... params) {
db.open();
listAlerts = db.getData();
if (isCancelled()) {
this.cancel(true);
}
return null;
}
protected void onPostExecute(List<Notes> alerts) {
if (null != pDialog && pDialog.isShowing()) {
pDialog.dismiss();
}
db.close();
setAdapterToListview();
}
}// end myTask
public void setAdapterToListview() {
objAdapter = new NoteAdapter(NotesView.this, R.layout.row_notes, listAlerts);
objAdapter.sortByNoteDesc();
objAdapter.notifyDataSetChanged();
listView.setAdapter(objAdapter);
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
Intent intent = new Intent(
NotesView.this.getApplicationContext(),
TabBarExample.class);
intent.putExtra("goToTab", "Alerts");
startActivity(intent);
return true;
}
return super.onKeyDown(keyCode, event);
}
public void onItemClick(AdapterView<?> parent, View viewDel, int position,
long id) {
for (int i = 0; i < 1; i++) {
Notes item = listAlerts.get(position);
int ids = item.getId();
note = item.getNote();
time = item.getTimeStamp();
}
System.out.println(note + " " + time);
//
}
#Override
protected void onResume() {
super.onResume();
}
#Override
protected void onPause() {
super.onPause();
setContentView(R.layout.note);
listView = (ListView) findViewById(R.id.notelist);
listView.setAdapter(null);
listView.setOnItemClickListener(this);
noteView = (TextView) findViewById(R.id.noteDisplay);
timeView = (TextView) findViewById(R.id.notetimeStampDisplay);
new MyTask().execute();
}
#Override
protected void onDestroy() {
}
}
Code snippets From GCMIntentService
#Override
protected void onMessage(Context context, Intent intent) {
Log.i(TAG, "Received message");
//String message = getString(R.string.gcm_message);
System.out.println("onMessage: ");
Bundle extras = intent.getExtras();
String message = extras.getString("message");
String event_id_from_server = extras.getString("server_id");
// displayMessage(context, message);
generateNotification(context, message);
saveMsg(message);
System.out.println("server id is " + event_id_from_server);
if (event_id_from_server != null) {
updateLocalDatabase(event_id_from_server);
}
}
public void saveMsg(String msg) {
boolean worked = true;
try {
NotificationsDatabase entry = new NotificationsDatabase(GCMIntentService.this);
entry.open();
java.util.Date date = new java.util.Date();
Timestamp x = new Timestamp(date.getTime());
String timeStamp = x.toLocaleString();
entry.createEntry(msg, timeStamp);
entry.close();
//update adapter service
} catch (Exception e) {
worked = false;
String error = e.toString();
System.out.println(error);
} finally {
if (worked) {
}
}
}
I cleaned up your code a little bit. Basically all the view assignments should be done once in onCreate, while the loading of the data should be done in onResume(). See if this helps:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.note);
listView = (ListView) findViewById(R.id.notelist);
listView.setAdapter(null);
listView.setOnItemClickListener(this);
noteView = (TextView) findViewById(R.id.noteDisplay);
timeView = (TextView) findViewById(R.id.notetimeStampDisplay);
}
#Override
protected void onResume() {
super.onResume();
new MyTask().execute();
}
#Override
protected void onPause() {
super.onPause();
}