In the docs here I'm following how to receive location requests and two unusual things I noticed are in these two blocks of code:
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult(LocationSettingsResult result) {
final Status status = result.getStatus();
final LocationSettingsStates = result.getLocationSettingsStates(); //<--This line I don't understand
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
// All location settings are satisfied. The client can initialize location
// requests here.
...
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location settings are not satisfied. But could be fixed by showing the user
// a dialog.
try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
status.startResolutionForResult(
OuterClass.this,
REQUEST_CHECK_SETTINGS);
} catch (SendIntentException e) {
// Ignore the error.
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
// Location settings are not satisfied. However, we have no way to fix the
// settings so we won't show the dialog.
...
break;
}
}
});
And in the second block:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
final LocationSettingsStates states = LocationSettingsStates.fromIntent(intent); //<--And this line
switch (requestCode) {
case REQUEST_CHECK_SETTINGS:
switch (resultCode) {
case Activity.RESULT_OK:
// All required changes were successfully made
...
break;
case Activity.RESULT_CANCELED:
// The user was asked to change settings, but chose not to
...
break;
default:
break;
}
break;
}
}
I've added some arrows pointing to the lines I don't understand. In particular, these two:
final LocationSettingsStates = result.getLocationSettingsStates();
final LocationSettingsStates states = LocationSettingsStates.fromIntent(intent);
The first line is something I haven't seen before. How is this valid, assigning a value to a data type? Then that class is no longer used anywhere else in that block of code, so what's the purpose of the assignment?
In the other line, now it's assigning a value to an instance called states of that data type but that instance is not used anywhere else in onActivityResult().
So what is going on here? Thanks.
The first line is definitely a typo; it should be something like:
final LocationSettingsStates states = result.getLocationSettingsStates();
And yeah, it isn't used in either place, which is weird, but you can call things like isBleUsable() on it to determine what exactly is present and usable right now. In the latter case, it's what's usable after the attempted resolution.
Related
#Override
public void onClick(View v) {
switch (v.getId()){
case R.id.iv_camera:
Toast.makeText(this, "Camera Clicked", Toast.LENGTH_SHORT).show();
break;
case mBinding.ivCamera.getId():
break;
}
}
The first case works perfectly fine however, the second one throws an error that says Constant Expression Required . Am i forced to use R.id.something or can I continue with view binding?
The reason is that case statements in java needs to be compile time constant. Since mBinding.ivCamera.getId() is not thus the error. Here is already an answer in detail.
I've just finished implementing my app's weather icons, now I'm trying to play weather sounds on the app based on the icons the app is displaying. After doing long hours of thorough research, I found out to my shock that no one has ever asked similar questions on any platform.
My knowledge of java dictionary is quite narrow and I find it hard to understand documentation even after taking my time to read and study their samples. i.e I found a doc I believe would correspond with what I am trying to achieve here https://docs.oracle.com/javase/8/docs/api/java/util/Map.html
It explains that
V put(K key,
V value)
Associates the specified value with the specified key in this map. In that case, I thought of using K as Icon and V as my sound but I didn't know how to apply it so I looked for examples and saw this https://study.com/academy/lesson/the-java-dictionary-class-definition-example.html The examples it provided still wasn't enough to help me through and I know I will mess it up if I try to work it out myself, so I decided to come up with this here to see if anyone can help, I'll really appreciate it.
Following the API instructions, I'm using https://openweathermap.org/weather-conditions.
There are 9 main weather conditions.
These are my goals in trying to play the sounds based on the icons:
If the city displays the clear_sky icon, play the clear_sky_sound
Otherwise, If it displays the few_clouds icon, play the few_clouds_sound
Otherwise, If it displays the scattered_clouds icon, play the scattered_clouds_sound
Otherwise, If it displays the broken_clouds, play the broken_clouds_sound
Otherwise, If it displays the shower_rain icon, play the shower_rain_sound
Otherwise, If it displays the rain icon, play the rain_sound
Otherwise, If it displays the thunderstorm icon, play the thunderstorm_sound
Otherwise, If it displays the snow icon, play the snow_sound
Otherwise, If it displays the mist icon, play the mist_sound.
Here is my Fragment's code:
public class FirstFragment extends Fragment {
private WeatherDataViewModel viewModel;
MediaPlayer firstSound, secondSound, thirdSound, fourthSound, fifthSound, sixthSound, seventhSound, eightSound, ninethSound;
public FirstFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_first, container, false);
// For displaying weather data
final TextView current_temp = rootView.findViewById(R.id.textView10);
final TextView current_output = rootView.findViewById(R.id.textView11);
final TextView rise_time = rootView.findViewById(R.id.textView25);
final TextView set_time = rootView.findViewById(R.id.textView26);
final TextView temp_out = rootView.findViewById(R.id.textView28);
final TextView Press_out = rootView.findViewById(R.id.textView29);
final TextView Humid_out = rootView.findViewById(R.id.textView30);
final TextView Ws_out = rootView.findViewById(R.id.textView33);
final TextView Visi_out = rootView.findViewById(R.id.textView34);
final TextView Cloud_out = rootView.findViewById(R.id.textView35);
final ImageView current_icon = rootView.findViewById(R.id.imageView6);
final SwipeRefreshLayout realSwipe = rootView.findViewById(R.id.real_swipe);
// Get our ViewModel instance
viewModel = new ViewModelProvider(this).get(WeatherDataViewModel.class);
// And whenever the data changes, refresh the UI
viewModel.getWeatherDataLiveData().observe(getViewLifecycleOwner(), data -> {
realSwipe.setOnRefreshListener(() -> {
// perform you action here for ex. add refresh screen code here
new Handler().postDelayed(() -> {
// this code is for stop refreshing icon, After 1000 ms automatically refresh icon will stop
realSwipe.setRefreshing(false);
}, 1000);
});
int drawableResource = -1; // here define default icon for example R.drawable.default_weather_icon
if (data != null) {
current_temp.setVisibility(View.VISIBLE);
current_temp.setText(data.getMain().getTemp() + " ℃"); // for that you can use strings resource and templates more in https://developer.android.com/guide/topics/resources/string-resource.html#formatting-strings
current_output.setVisibility(View.VISIBLE);
current_output.setText(data.getWeather().get(0).getDescription());
rise_time.setVisibility(View.VISIBLE);
rise_time.setText(data.getSys().getSunrise() + " ");
set_time.setVisibility(View.VISIBLE);
set_time.setText(data.getSys().getSunset() + " ");
temp_out.setVisibility(View.VISIBLE);
temp_out.setText(data.getMain().getTemp() + " ℃");
Press_out.setVisibility(View.VISIBLE);
Press_out.setText(data.getMain().getPressure() + " hpa");
Humid_out.setVisibility(View.VISIBLE);
Humid_out.setText(data.getMain().getHumidity() + " %");
Ws_out.setVisibility(View.VISIBLE);
Ws_out.setText(data.getWind().getSpeed() + " Km/h");
Visi_out.setVisibility(View.VISIBLE);
Visi_out.setText(data.getVisibility() + " m");
Cloud_out.setVisibility(View.VISIBLE);
Cloud_out.setText(data.getClouds().getAll() + " %");
// get actual weather.
String icon = data.getWeather().get(0).getIcon();
switch (icon) {
case "01d":
case "01n":
drawableResource = R.drawable.sun;
break;
case "02d":
case "021n":
drawableResource = R.drawable.few_clouds;
break;
case "03d":
case "03n":
drawableResource = R.drawable.scattered_clouds;
break;
case "04d":
case "04n":
drawableResource = R.drawable.broken_clouds;
break;
case "09d":
case "09n":
drawableResource = R.drawable.shower_rain;
break;
case "10d":
case "10n":
drawableResource = R.drawable.small_rain;
break;
case "11d":
case "11n":
drawableResource = R.drawable.thunderstorm;
break;
case "13d":
case "13n":
drawableResource = R.drawable.snow;
break;
case "50d":
case "50n":
drawableResource = R.drawable.mist;
break;
}
if (drawableResource != -1)
current_icon.setImageResource(drawableResource);
} else {
Log.e("TAG", "No City found");
current_temp.setVisibility(View.GONE);
current_output.setVisibility(View.GONE);
rise_time.setVisibility(View.GONE);
set_time.setVisibility(View.GONE);
temp_out.setVisibility(View.GONE);
Press_out.setVisibility(View.GONE);
Humid_out.setVisibility(View.GONE);
Ws_out.setVisibility(View.GONE);
Visi_out.setVisibility(View.GONE);
Cloud_out.setVisibility(View.GONE);
Toast.makeText(requireActivity(), "No City found", Toast.LENGTH_SHORT).show();
}
});
return rootView;
}
public void getWeatherData(String name) {
// The ViewModel controls loading the data, so we just
// tell it what the new name is - this kicks off loading
// the data, which will automatically call through to
// our observe() call when the data load completes
viewModel.setCityName(name);
}
}
EDIT:
DennisVA helped by providing a sample I could follow(i tried his 2nd suggestion) but when I tried it, I got some errors which I shared using a link in his comment section.
I decided to bounty this post to draw more attention, so I can be directed more in the right direction.
MediaPlayer firstSound, secondSound, thirdSound, fourthSound, fifthSound, sixthSound, seventhSound, eightSound, ninethSound;
Here you created 9 MediaPlayer objects, and from their names and their count that exactly the same as the number of icons; I realized that each one will handle the sound of a certain icon.
Although, you could only use a single MediaPlaer object for playing any of the 9 sounds you have. Think of it like your operating system media player, you have a single media player app, and you can drag and drop any media file at a time, and change it whenever you want without changing the app itself.
This is valid as long as you want to play a single media file at a time; but, in case you want to play multiple sounds at the same time, you probably need more than one MediaPlayer object.
So, as in your case you've a single whether condition at a time, so I assume that you want to play a single file at a time; and therefore you've a single icon at a time (due to the switch statement), and hence you need to change above mentioned snippet to be a single variable:
MediaPlayer mediaPlayer;
My knowledge of java dictionary is quite narrow and I find it hard to understand documentation
A dictionary (or it's a Map for accurately speaking in java), think of it like a phone directory: You know the person name (Key), and need to get the corresponding phone number (Value); the difference in this example that in phone directory there is only a unique value for each key/person; but in java Map, you can have duplicate values (i.e. more than one key/person can own the same value/phone number).
V put(K key,
V value)
Also, In java, the key and value can be almost anything and this can be indicated from the (K & V) symbols which are a generics.
I thought of using K as Icon and V as my sound but I didn't know how to apply it
In the shared simple example, I don't really think that you need a map; as the sound resources are highly coupled with the corresponding icon drawable resources, then you can just treat the sound raw files like you did with drawables.
So, whenever you change the current drawable (i.e. in the switch statement), you also need to change the current sound in the switch statement, assuming they have the same name as the drawables:
MediaPlayer mediaPlayer; // single MediaPlayer object
int drawableResource = -1; // here define default icon for example R.drawable.default_weather_icon
int soundResource = -1; // Default sound is nothing
String icon = data.getWeather().get(0).getIcon();
switch (icon) {
case "01d":
case "01n":
drawableResource = R.drawable.sun;
soundResource = R.raw.sun;
break;
case "02d":
case "021n":
drawableResource = R.drawable.few_clouds;
soundResource = R.raw.few_clouds;
break;
case "03d":
case "03n":
drawableResource = R.drawable.scattered_clouds;
soundResource = R.raw.scattered_clouds;
break;
case "04d":
case "04n":
drawableResource = R.drawable.broken_clouds;
soundResource = R.raw.broken_clouds;
break;
case "09d":
case "09n":
drawableResource = R.drawable.shower_rain;
soundResource = R.raw.shower_rain;
break;
case "10d":
case "10n":
drawableResource = R.drawable.small_rain;
soundResource = R.raw.small_rain;
break;
case "11d":
case "11n":
drawableResource = R.drawable.thunderstorm;
soundResource = R.raw.thunderstorm;
break;
case "13d":
case "13n":
drawableResource = R.drawable.snow;
soundResource = R.raw.snow;
break;
case "50d":
case "50n":
drawableResource = R.drawable.mist;
soundResource = R.raw.mist;
break;
}
if (drawableResource != -1)
current_icon.setImageResource(drawableResource);
if (soundResource != -1) {
prepareMediaPlayer(soundResource);
}
// In FirstFragment:
private void prepareMediaPlayer(int resource) {
// add track file
mMediaPlayer = MediaPlayer.create(requireActivity(), resource);
// listening to when the media file finishes playing so that we can release the resources
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
if (mMediaPlayer != null) {
mMediaPlayer.release();
}
}
});
}
And whenever you want to play the sound, just call mMediaPlayer.start(), but make sure that prepareMediaPlayer() is called in advance.
Hint: if you want to use a map, I'd recommend that you create a POJO/Data class for the Weather, so that probably we'd a Map.
I would create a wrapper to make it easier to show things to your UI
For example:
public class Weather{
#DrawableRes
private int icon; //Resource id of the drawable
private String sound; //Name or path the the sound file
public Weather(WeatherPojo pojo){
switch(pojo.icon){
case "01d":
case "01n":
this.icon = R.drawable.sun;
this.sound = ...
}
}
}
This class could also contain a play(MediaPlayer player) method
Some other things i noticed:
avoid hardcoding your strings
you might wanna have a look at viewbinding to reduce that high amount of ugly rootView.findViewById calls (https://developer.android.com/topic/libraries/view-binding)
Edit:
Another, probably better option would be to create some kind of WeatherFactory class or parser that produces subclasses of an abstract Weather class,
and have that abstract class contain code for playing the media file:
public abstract class Weather{
#DrawableRes
private int iconResId;
#RawRes
private int soundResId;
protected Weather(#DrawableRes int iconResId, #RawRes int soundResId){
this.iconResId = iconResId;
this.soundResId = soundResId
}
public void playSound(MediaPlayer mediaPlayer, Context context){
String assetFileDescriptor = context.resources.openRawResourceFd(soundResId);
if(assetFileDescriptor == null)
return;
mediaPlayer.reset();
mediaPlayer.setDataSource(assetFileDescriptor.fileDescriptor,
assetFileDescriptor.startOffset, assetFileDescriptor.declaredLength);
mediaPlayer.prepareAsync();
}
}
public class Snow extends Weather{
public Snow(){
super(R.drawable.snow, R.raw.snow)
}
}
Now u can call snow.playSound() in ur fragment or viewModel and generate getters and setters in the abstract class to get the drawable and display it.
Other variables for example the description can also be injected in the constructor of the subclass, or u can extend the subclasses themselves for the different types of snow (LightSnow, HeavySnow, ...)
Note: I haven't tested any of this code so it might need some changes here and there
I had an issue where Text to Speech would not speak anything. I realised this was due to the fact that I was attempting to call 'Speak()' before TTS had initialised.
I need to wait until TTS has initialised, so that I can call 'Speak()' successfully. I thought doing something along the lines of this would work:
#Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
mTTSInitialised = true;
} else {
Log.e("TTS", "Initialisation Failed!");
}
}
...
while(!mTTSInitialised){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
But this fails to initialise at all. Is there a way to do this effectively?
The initialisation of the Text to Speech engine is asynchronous, which is why you realised you have to 'wait' for it to complete, before requesting that it processes an utterance.
Even when it eventually initialises successfully, it can be subsequently killed by the system, or it can of course fail to initialise, so you always need to be ready to handle a request to speak, where the engine isn't prepared.
Add the following helper class
public class PendingTTS {
private String pendingUtterance;
private int pendingQueueType;
public String getPendingUtterance() {
return this.pendingUtterance;
}
public void setPendingUtterance(#NonNull final String pendingUtterance) {
this.pendingUtterance = pendingUtterance;
}
public int getPendingQueueType() {
return this.pendingQueueType;
}
public void setPendingQueueType(final int pendingQueueType) {
this.pendingQueueType = pendingQueueType;
}
}
Assuming you're using an Activity, you need to declare the following variables:
private volatile PendingTTS pendingTTS;
private static final int MAX_INIT_ATTEMPTS = 4;
private volatile int initCount;
and initialise the Text to Speech object in onCreate()
tts = new TextToSpeech(YOURActivity.this, YOURonInitListener);
In your onInitListener you would check if there is any pending speech:
#Override
public void onInit(final int status) {
switch (status) {
case TextToSpeech.SUCCESS:
initCount = 0;
// Set up tts stuff
tts.setOnUtteranceProgressListener(YOURprogressListener);
if (pendingTTS != null) {
// We have pending speech, process it and check the result
int speechResult = tts.speak(pendingTTS.getPendingUtterance(),pendingTTS.getPendingQueueType(),
// remaining tts variables here)
switch (speechResult){
case TextToSpeech.SUCCESS:
// Result was successful
pendingTTS = null;
break;
case TextToSpeech.ERROR:
// Speech failed
// Check if it has repeatedly failed up to the max attempts
if(initCount < MAX_INIT_ATTEMPTS){
initCount ++;
tts = new TextToSpeech(YOURActivity.this, YOURonInitListener);
} else {
// Totally broken - let the user know it's not working
}
break;
}
} else {
// there was nothing to process
}
break;
case TextToSpeech.ERROR:
// Check if it has repeatedly failed up to the max attempts
if(initCount < MAX_INIT_ATTEMPTS){
initCount ++;
tts = new TextToSpeech(YOURActivity.this, YOURonInitListener);
} else {
// Totally broken - let the user know it's not working
}
break;
}
I've glued the above together from my code - where the speech and initialisation methods are all separated, but I tried to give you an overview above of everything you need to handle.
Elsewhere in your code, when you make a tts.speak(//stuff here) request, you need to check the result as demonstrated above, to make sure it was successful. Again, in my code, this is separated into one single method. If it does fail, you need to set the PendingTTS parameters prior to attempting to initialise again:
pendingTTS = new PendingTTS();
pendingTTS.setPendingQueueType(// your queue type);
pendingTTS.setPendingUtterance(// your utterance);
It is is successful, make sure pendingTTS is set to null.
The overall design is that if the initialisation failed, it will attempt to initialise again, up to the maximum allowed attempts. If the speech fails, it will attempt to initialise the engine again, firstly setting the PendingTTS parameters.
Hope you managed to follow that.
Hmm..
Not a very good idea.
You can try to add the text to the TTS queue and let it do it's work. This snippet can be inside button click, etc as:
tts.speak(toSpeak, TextToSpeech.QUEUE_ADD, null);
Small tutorial that would help.
when case is successful i want to edit the variable value and then i want to use this value in other class of my project.
how can i do it?
kindly suggest me?
switch (status) {
case SUCCESSFUL:
SamplePurchasingListener.this.runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
SharedPreferences.Editor editor = getSharedPreferences(MY_PREFS_NAME, MODE_WORLD_READABLE).edit();
editor.putBoolean("PREMIUM", true); // Storing boolean - true/false
editor.commit();
}
});
final Receipt receipt = response.getReceipt();
iapManager.setAmazonUserId(response.getUserData().getUserId(), response.getUserData().getMarketplace());
Log.d(TAG, "onPurchaseResponse: receipt json:" + receipt.toJSON());
iapManager.handleReceipt(response.getRequestId().toString(), receipt, response.getUserData());
iapManager.refreshLevel2Availability();
break;
case ALREADY_PURCHASED:
Log.i(TAG,
"onPurchaseResponse: already purchased, you should verify the entitlement purchase on your side and make sure the purchase was granted to customer");
break;
If you just want to retrieve value from another class, why don't just get it from preferences? Something like this:
SharedPreferences sp = getSharedPreferences(MY_PREFS_NAME, MODE_WORLD_READABLE);
boolean premium = sp.getBoolean("PREMIUM", false);
if(premium) { ...
If there are not value have been stored before, method will return "false".
Maybe I haven't understood your question.
i have following function run on start and work perfectly.
i would like to add if condition in other function in order to check if device is still connected.
here is code
private final Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case BluetoothService.MESSAGE_STATE_CHANGE:
switch (msg.arg1) {
case BluetoothService.STATE_CONNECTED:
Toast.makeText(getApplicationContext(), "Connect successful",
Toast.LENGTH_SHORT).show();
btnClose.setEnabled(true);
btnSend.setEnabled(true);
btnSendDraw.setEnabled(true);
break;
case BluetoothService.STATE_CONNECTING:
Log.d("À¶ÑÀµ÷ÊÔ","ÕýÔÚÁ¬½Ó.....");
break;
case BluetoothService.STATE_LISTEN:
case BluetoothService.STATE_NONE:
Log.d("À¶ÑÀµ÷ÊÔ","µÈ´ýÁ¬½Ó.....");
break;
}
break;
case BluetoothService.MESSAGE_CONNECTION_LOST:
Toast.makeText(getApplicationContext(), "Device connection was lost",
Toast.LENGTH_SHORT).show();
btnClose.setEnabled(false);
btnSend.setEnabled(false);
btnSendDraw.setEnabled(false);
break;
case BluetoothService.MESSAGE_UNABLE_CONNECT:
Toast.makeText(getApplicationContext(), "Unable to connect device",
Toast.LENGTH_SHORT).show();
break;
}
}
};
other function is start like this
#Override
protected void onPostExecute(String result){
please help me!!
Thanks
ACL_CONNECTED/DISCONNECTED is not exactly reliable, I have learned by experience, because this might happen several times during a device's connection (example, if pin is required, you will get "connected", and then "disconnected" if timeout/wrong pin supplied. This does not necessarily indicate connection proper). This indicates the lower layer connection.
If you want to use a broadcast receiver, it would be better to use the broadcast that is specific to the profile that you have used (example A2DP). Each has it's own broadcast. Another thing you can listen to is Connectivity_state_changed from ConnectivityManager, for the type BLUETOOTH (haven't really tried this one).
Also, the way to check if it is connected, without a broadcast receiver, say, when you want to check in the background before updating an activity, would be to obtain the profile object, via something like:
mBluetoothAdapter.getProfileProxy(mContext, mA2DPProfileListener, BluetoothProfile.A2DP);
where mA2DPProfileListener is a ServiceListener object:
<code>
private ServiceListener mA2DPProfileListener = new ServiceListener(){
//anonymous inner type. etc.
public void onServiceConnected(int profile, BluetoothProfile proxy) {
//cast the BluetoothProfile object to the profile you need, say
//BluetoothA2DP proxyA2DP = (BluetoothA2DP) proxy;
int currentState = proxyA2DP.getConnectionState(mDevice);
//mDevice is the BluetoothDevice object you can get from
//BluetoothAdapter.getRemote...
}
public void onServiceDisconnected(int profile) {
}
}
</code>
you can check what currentState points to, and determine if the device is connected/disconnected/connecting, etc.
HTH,
Sreedevi.