I am trying to create a media player controls notification using a custom remoteView. the problem I got into is that each time I change something in the remote view, I need to cancel the notification and rebuild it from scratch. This method is very bad for performance as it visibly lags. ( i.e changing the pause icon to play icon only, I would need to rebuild the entire notification and reload the album image too )
I tried changing the remoteView and then setting it back again using the NotificationBuilder.setCustomContentView but it didn't work, here is the code of changing the play and pause icons :
public void PlayPause(){
this.play=!this.play;
if (this.play) {
Bitmap toggleBmp = BitmapFactory.decodeResource(parent.getResources(), R.drawable.baseline_pause_black_48);
remoteView.setImageViewBitmap(R.id.toggle, changeBitmapColor(toggleBmp,Color.parseColor(iconColor)));
} else {
Bitmap toggleBmp = BitmapFactory.decodeResource(parent.getResources(), R.drawable.baseline_play_arrow_black_48);
remoteView.setImageViewBitmap(R.id.toggle, changeBitmapColor(toggleBmp,Color.parseColor(iconColor)));
}
nBuilder.setCustomContentView(remoteView);
}
The upper code doesn't work and the icons don't change.
You should be able to update a notification with new information, without having to cancel the original notification.
If you create your notification with a unique ID, you can then use that ID to update the notification by using the NotificationManager.notify(id, notification).
Where id is the unique ID of the notification you want to update and notification is a Notification object either created with new content or updated.
This site has an example of how to update a notification in Java.
Related
I am working on stripe-terminal-android-app, to connect to BBPOS 2X Reader device,
wanted to click-item from list,(recyclerView).
I am trying to do:
when list of devices appears(readers), I am checking if readers.size()==1, then click first-device from list,else show recyclerView();
I have very less experience in Android(coming from JS, PY), :)
After going through debugger to understand flow of program-running, I used F8 key, or stepOver the functions one by one,
and where value is assigned to convert in displayble-format in adapter as here.
public ReaderAdapter(#NotNull DiscoveryViewModel viewModel) {
super();
this.viewModel = viewModel;
if (viewModel.readers.getValue() == null) {
readers = new ArrayList<>();
} else {
readers = viewModel.readers.getValue();
if(readers.size() == 1){
Log.e(TAG, "readers.size() is 1 "+ readers.size());
}
}
}
then in ReaderHolder-file, values are bind() as
void bind(#NotNull Reader reader) {
binding.setItem(reader);
binding.setHandler(clickListener);
binding.executePendingBindings();
}
}
I tried assigining button and manually clicking when only-one device appears, by clicing on reader[0], can't do that by findViewById inside Adapter file, to call onClick() method manually,
I tired another StackOverflow's answer but didn't understood, from here.
Main fragment is discovery-fragment,
how can I click first-device by checking readers.size()==1, then click onClick()?
my final-goal is to automate, whole stripe-terminal-payment process on android.
extra-info:
I am fetching data from python-odoo server, then using url, will open app through browser, (done this part), then device will be selected automatically as everytime-no any devices will be present except one,
so will automatically select that from recyclerView, then proceed.
I have asked for help in detailed way on GitHub-issues, and started learning Android's concepts for this app(by customizing stripe's demo app, which works great, but I wanted to avoid manually clicking/selection of devices).
there are simple activities A and B. Activity A launches Activity B and i can select an image as profile image, which first I will upload it to the server and then show the image via the received url. At first when I switch to activity B everything works fine, if there is an image already downloaded its shown in the imageview or it will be downloded and shown. in this case if I select other images to upload, its working just fine and the imageview will show the new images. when I exit the activity and relaunch it, the previously downloded image is shown (if any exists), but any new image uploaded to server won't be shown not even drawables. the imageview won't update at all until I exit the activity again and relaunch it, which in this case the previous image uploaded will be shown but again no new image is shown. so to sum it, first time everything works fine, but for the next times the image is loaded properly only one time.
I've been using Glide and Frisco and thought the problem is caused by them but then used simple ImageView and simple connection to download bitmap and it was the same. it works only one time.
I've been testing both on Nokia 6.1 plus Android 9 and Nexus 5x Android 8.1 and emulators with Android 8.1 and Android 9. I've also tried the release build and still the same.In addition, I'm using AndroidX and the strategy to download image and load them is the same as my previous projects and I'd never faced this issue before.
tried these below before and after loading image and it's not working.
with Glide and Frisco the cache is also disabled. and The urls are completely random so they wont even have the chance to cache them.
here is a sample download and load, its just temporary.
image.setImageResource(0);
image.setImageBitmap(null);
image.invalidate();
new Thread(new Runnable() {
#Override
public void run() {
Bitmap bmp = null;
try {
trustEveryone();
URL url = new URL(user.image_address);
bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());
Bitmap finalBmp = bmp;
ProfileActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
_profileImage.setImageBitmap(null);
_profileImage.setImageResource(0);
_profileImage.invalidate();
_profileImage.setImageBitmap(finalBmp);
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
before using below method, tested it on my backup project before migrating to androidX and it was the same so the problem was not because of androidX
so here is the solution. the activities order : Main->Profile->Gallery->Crop->Back to Profile
to return the results from Crop to Profile I'm using event bus which has to be run on UI thread, so the Activity used to runOnUI... to post the event was CropActivity which was finished after the event is posted, and although I used ProfileActivity.runOnUI ... to load the image when receiving the event from event bus, the whole code was being run on CropActivity so I used another workaround to send results back to previous activity and that solved the problem without the need for invalidate or setting the image to null.
I want to change the device's background each specific interval (30 seconds for example) . I've been searching for days for a similar project or tutorial but I didn't find anything helpful . As I guess the app that I'm going to code will be a service since I want it to run in the background . I have the background images included in the drawable folder . So can any one help ?? and thanks in advance
There is a great application that does this and it's opensource. It's called Muzei - link created by Roman Nurik. Once a day, this application gets wallpapers from Internet and change your background. You can totally get this code and modify the frequency of the background change, and strip all the web calls and redirect to your internal images
You can also code a plugin for Muzei. You will only have a little part of the code to make it work. It will be a lot easier. But, in the other hand, you will have less control on the time between every wallpaper change.
For your code it will be a mix between :
AlarmManager run every hour
// We want the alarm to go off 30 seconds from now.
long firstTime = SystemClock.elapsedRealtime();
firstTime += remainingMilisecondsToTopHour;
long a=c.getTimeInMillis();
// Schedule the alarm!
AlarmManager am = (AlarmManager)ctx.getSystemService(Context.ALARM_SERVICE);
am.setRepeating(AlarmManager.ELAPSED_REALTIME,
c.getTimeInMillis(), 1*60*60*1000, sender);
and Changing Wallpaper. Do not forget to add the permission of changing background in your manifest
// to set a background we need to use bitmap
InputStream is = getResources().openRawResource(R.Drawable.myImage);
// we set the phone background to that image.
Bitmap bm = BitmapFactory.decodeStream(is);
try {
getApplicationContext().setWallpaper(bm);
// add permission of background from manifest file
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Using a service in background all the time will use way more battery of your device.
Run one task every hour if you still want to use a service ;)
Finally you should register to the broadcast event Screen On/Off to avoid changing wallpaper while the device is idle and draining the battery for nothing
I have a litte appwidget with a configuration activity.
In the configuration activity I have a EditText
to store a particular string and a button to create the widget.
In the widget itself there is only a Imageview with a static image showing a button.
when i press the button im doing the following:
AppWidgetManager app_widget_manager = AppWidgetManager.getInstance(context);
RemoteViews local = new RemoteViews(context.getPackageName(), R.layout.main);
app_widget_manager.updateAppWidget(widget_id, local);
Intent create = new Intent(this, MyWidget.class);
create.setAction("com.test.mywidget.CREATE");
create.putExtra("toastmessage", edittext1.getText().toString);
context.sendBroadcast(create);
Intent result_value = new Intent();
result_value.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widget_id);
setResult(RESULT_OK, result_value);
finish();
the extra 'toastmessage' is just the content of the edittext.
in the widget i catch the broadcast in onReceive() and get the string value that was
passed before as extra 'toastmessage' to the new widget.
if i press on my widget, i create a toast with the passed string
- and here is my problem -
the passed string is different for every widget created.
but the variable (in the widget) where i store the passed string
gets resettet after a little time or when the phone gets restartet or the app killed or something similar,
so i need persistent data for every widget instance.
I need to store which widget got which string passed,
and get this data everytime when the widget gets updated.
How can i achieve this?
According with this link you have some options to accomplish your goal.
For shared preferences, here an example.
For internal storage Take this way.
For external storage, you can use this.
For SQL Lite storage, here.
Hope these examples helps, cheers.
The widget_id you received is a unique identifier of the widget instance. Use it as a key to identify your persisted data.
I am making a keyboard ( InputMethodService ), which needs to launch a dialog.
As I found out, a service can not launch a dialog. So I made a separate activity which is called from the service by
Intent dialogIntent = new Intent(getBaseContext(), dialog.class);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplication().startActivity(dialogIntent);
and show a dialog. The problem is that this activity replaces the previous one, where the user was typing something.
What do you think would be the best way to make it "transparent" ( i.e. not to push away the previous activity ) and also what would be the best way for this activity to talk back to the service, saying that dialog option was picked.
Thanks! :)
If this is an Activity (not a Dialog), you can add a dialog theme in the activity section of your AndroidManifest:
android:theme="#android:style/Theme.Dialog"
As for getting back what the user pressed, you should use startActivityForResult(...)
You should NOT launch an activity from an IME. This is a huge break in the IME flow -- the activity comes along and does an app switch from the current app, taking focus from it, and breaking your connection with its current editor.
Also there is no way to get a result back from it, because you can only use startActivityForResult() from an activity.
To show a Dialog in your IME, just use Dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG before showing the dialog.
To resume in code what have been said, let me share some code for those who need to test the solution:
// 1. CREATE THE DIALOG
val builder: AlertDialog.Builder = AlertDialog.Builder(this, R.style.Theme_AppCompat_Light)
builder.setTitle("Title").setMessage("This is the message for the user. ")
val mDialog = builder.create()
// 2. SET THE IME WINDOW TOKEN ATTRIBUTE WITH THE TOKEN OF THE KEYBOARD VIEW
mDialog.window?.attributes?.token = this.mKeyboardView.windowToken
// 3. SET THE TYPE OF THE DIALOG TO TYPE_APPLICATION_ATTACHED_DIALOG
mDialog.window?.setType(WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG)
// 4. SHOW THE DIALOG
mDialog.show()