I have a wearable app that has a couple of fragments created with FragmentGridPagerAdapter. One of the fragments has a couple of CircularButtons and I want to update the backcolor of the button when a message is received from handheld phone. I have no problems in receiving the message. However, button's color (or anything in UI) doesn't update. Do you know how can I fix this?
public class UIPageAdapter extends FragmentGridPagerAdapter {
private final Context mContext;
MainControlFragment[] mainControlFragments;
private List mRows;
uiChangeListener mUIChangeListener = new uiChangeListener();
public UIPageAdapter(Context ctx, FragmentManager fm) {
super(fm);
Log.i("pageAdapter", "constructor");
mContext = ctx;
mainControlFragments = new MainControlFragment[2];
mainControlFragments[0] = new MainControlFragment();
mainControlFragments[1] = new MainControlFragment();
LocalBroadcastManager.getInstance(ctx).registerReceiver(mUIChangeListener,new IntentFilter(Constants.BROADCAST_CONTROL_HOME));
}
#Override
public Fragment getFragment(int row, int col) {
Log.i("PageAdapter","Fragment #" + col +"is asked");
return mainControlFragments[col];
}
public void changeStatus(int button, boolean status) {
mainControlFragments[0].setStatus(button,status);
// notifyDataSetChanged();
}
public class uiChangeListener extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
String act = intent.getAction();
if (act == Constants.BROADCAST_CONTROL_HOME) {
int key = intent.getIntExtra(Constants.CONTROL_HOME_KEY,-1);
String command = intent.getStringExtra(Constants.CONTROL_HOME_COMMAND);
changeStatus(key,command.equals("on"));
}
}
}
#Override
public int getRowCount() {
return 1;
}
#Override
public int getColumnCount(int i) {
return 2;
}
}
Basically when a message received from the handheld device a WearableListener class broadcasts an update message to the UIPageAdapter
This is the listener class
public class ListenerService extends WearableListenerService
{
String tag = "ListenerService";
#Override
public void onMessageReceived(MessageEvent messageEvent) {
final String message = (new String(messageEvent.getData()));
Log.i(tag,message);
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(Constants.BROADCAST_CONTROL_HOME)
.putExtra(Constants.CONTROL_HOME_KEY, messageEvent.getPath())
.putExtra(Constants.CONTROL_HOME_COMMAND,Integer.parseInt(message.substring(1)))
.putExtra("caller",tag));
}
#Override
public void onCreate() {
super.onCreate();
Log.i(tag, "onCreate");
}
}
Manifest file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="smartstuff.com.tr.myautomationtool" >
<uses-feature android:name="android.hardware.type.watch" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#android:style/Theme.DeviceDefault" >
<uses-library
android:name="com.google.android.wearable"
android:required="false" />
<service android:name=".ListenerService">
<intent-filter>
<action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
</intent-filter>
</service>
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#android:style/Theme.DeviceDefault.Light" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Finally the custom fragment
public class MainControlFragment extends Fragment{
ViewGroup container;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.i("controlFragment","create");
this.container = container;
// Inflate the layout for this fragment
return inflater.inflate(R.layout.main_control, container, false);
}
public void setStatus(int button, boolean status) {
Log.i("controlFragment",button + " "+ status);
CircularButton[] btns = new CircularButton[4];
btns[0] = (CircularButton) container.findViewById(R.id.cbtnFront);
btns[1] = (CircularButton) container.findViewById(R.id.cbtnBack);
btns[2] = (CircularButton) container.findViewById(R.id.cbtnBed);
btns[3] = (CircularButton) container.findViewById(R.id.cbtnCoffee);
btns[button].setColor(status?Color.BLACK:Color.RED);
}
}
I also tried the notifyDataSetChanged(); method in UIPageAdapter however it it only calls onCreateView method in fragment. Any help is appreciated
I'm assuming you already resolved this but I had to add a call to invalidate() on the CircularButton after calling setColor():
_circularButton.setColor(ContextCompat.getColor(getActivity(), buttonColor));
_circularButton.invalidate();
Without the call to invalidate the UI only updated some of the time.
Related
I have a list view that displays all the songs in my device in the application, then when I click on the song another activity opens where you can play the song, on emulator when I click on the song in the list it takes me to the other activity and I can play and hear the song, but on real device I'm not getting any error but when I select an item from the list, I get the name and artist of the song, but when i click on play it doesn't work, I don't hear sound nor can I jump to middle of song etc..
the list is like this:
When clicked:
I'm using media player to read the audio files, and the code for my main activity is:
public class MusicPlayerOffline extends AppCompatActivity implements View.OnClickListener {
TextView tvTime,tvDuration,tvTitle,tvArtist;
SeekBar seekBarTime,seekBarVolume;
Button btnPlay;
MediaPlayer musicPlayer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_music_player_offline);
Songs song = (Songs) getIntent().getSerializableExtra("song");
tvTime=findViewById(R.id.tvTime);
tvDuration=findViewById(R.id.tvDuration);
seekBarTime=findViewById(R.id.seekBarTime);
seekBarVolume=findViewById(R.id.seekBarVolume);
btnPlay=findViewById(R.id.btnPlay);
tvTitle=findViewById(R.id.tvTitle);
tvArtist=findViewById(R.id.tvArtist);
tvTitle.setText(song.getTitle());
tvArtist.setText(song.getArtist());
musicPlayer=new MediaPlayer();
try {
musicPlayer.setDataSource(song.getPath());
musicPlayer.prepare();
}catch (IOException e){
e.printStackTrace();
}
musicPlayer.setLooping(true);
musicPlayer.seekTo(0);
musicPlayer.setVolume(0.5f, 0.5f);
String duration = millisecondsToString(musicPlayer.getDuration());
tvDuration.setText(duration);
btnPlay.setOnClickListener(this );
seekBarVolume.setProgress(50);
seekBarVolume.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
float volume = progress /100f;
musicPlayer.setVolume(volume, volume);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
seekBarTime.setMax(musicPlayer.getDuration());
seekBarTime.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser){
musicPlayer.seekTo(progress);
seekBar.setProgress(progress);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
new Thread(new Runnable() {
#Override
public void run() {
while (musicPlayer != null){
if (musicPlayer.isPlaying()){
try {
final double current = musicPlayer.getCurrentPosition();
final String elapsdTime = millisecondsToString((int) current);
runOnUiThread(new Runnable() {
#Override
public void run() {
tvTime.setText(elapsdTime);
seekBarTime.setProgress((int) current);
}
});
Thread.sleep(1000);
}catch (InterruptedException e){}
}
}
}
}).start();
}// end main
public String millisecondsToString(int time){
String elapsedTime = "";
int minutes = time / 1000 / 60;
int seconds = time / 1000 % 60;
elapsedTime = minutes+":";
if (seconds < 10){
elapsedTime += "0";
}
elapsedTime += seconds;
return elapsedTime;
}
#Override
public void onClick(View view) {
if (view.getId() == R.id.btnPlay){
if (musicPlayer.isPlaying()){
// is playing
musicPlayer.pause();
btnPlay.setBackgroundResource(R.drawable.ic_play);
}else {
// on pause
musicPlayer.start();
btnPlay.setBackgroundResource(R.drawable.ic_pause);
}
}
}
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
if (item.getItemId() == android.R.id.home){
finish();
if (musicPlayer.isPlaying()){
musicPlayer.stop();
}
}
return super.onOptionsItemSelected(item);
}
}
The code for my listviewmusic activity from where I retrieve title artist and audio is:
public class ListMusicActivity extends AppCompatActivity {
private static final int REQUEST_PERMISSION = 99;
ArrayList<Songs> songArrayList;
ListView tvSongs;
SongsAdapter songsAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_music);
tvSongs = findViewById(R.id.tvSongs);
songArrayList = new ArrayList<>();
songsAdapter = new SongsAdapter(this, songArrayList);
tvSongs.setAdapter(songsAdapter);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_PERMISSION);
return;
}else {
// you have permission to read from external storage
getSongs();
}
tvSongs.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Songs song = songArrayList.get(position);
Intent openMusicPlayer = new Intent(ListMusicActivity.this, MusicPlayerOffline.class);
openMusicPlayer.putExtra("song", song);
startActivity(openMusicPlayer);
}
});
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == REQUEST_PERMISSION){
if (grantResults[0] == PackageManager.PERMISSION_GRANTED){
getSongs();
}
}
}
private void getSongs() {
// read songs from phone
ContentResolver contentProvider = getContentResolver();
Uri songUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
Cursor songCursor = contentProvider.query(songUri,null,null,null,null);
if (songCursor != null && songCursor.moveToNext()) {
int indexTitle = songCursor.getColumnIndex(MediaStore.Audio.Media.TITLE);
int indexArtist = songCursor.getColumnIndex(MediaStore.Audio.Media.ARTIST);
int indexData = songCursor.getColumnIndex(MediaStore.Audio.Media.DATA);
do {
String title = songCursor.getString(indexTitle);
String artist = songCursor.getString(indexArtist);
String path = songCursor.getString(indexData);
songArrayList.add(new Songs(title, artist, path));
}while (songCursor.moveToNext());
}
songsAdapter.notifyDataSetChanged();
}
}
My adapter:
public class SongsAdapter extends ArrayAdapter<Songs> {
public SongsAdapter(#NonNull Context context, #NonNull List<Songs> objects) {
super(context,0, objects);
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_song, null);
TextView tvTitle = convertView.findViewById(R.id.tvTitle);
TextView tvArtist = convertView.findViewById(R.id.tvArtist);
Songs song = getItem(position);
tvTitle.setText(song.getTitle());
tvArtist.setText(song.getArtist());
return convertView;
}
}
I have no idea why it's not working, I don't get any error in the logcat, the music just doesn't start, it stays frozen at 0:00, and I cant jump to middle of it etc, although the name and artist name get obtained successfully just no audio
My manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.smallacademy.authenticatorapp">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme"
android:windowSoftInputMode="adjustPan">
<activity android:name=".ListMusicActivity"></activity>
<activity android:name=".MusicPlayerOffline" />
<activity android:name=".MusicplayerOnline" />
<activity android:name=".Musicplayer" />
<activity
android:name=".Admin_crud_Illness"
android:theme="#style/Theme.AppCompat.DayNight.DarkActionBar" />
<activity
android:name=".Admin_crud_food"
android:theme="#style/Theme.AppCompat.DayNight.DarkActionBar"
android:windowSoftInputMode="adjustPan" />
<activity android:name=".CaloriesCounterAdmin" />
<activity android:name=".Admin_addIllness" />
<activity android:name=".Admin_addfood" />
<activity android:name=".WaterInfo" />
<activity android:name=".WaterIntake" />
<activity android:name=".Share" />
<activity android:name=".Weather_Act" />
<activity android:name=".CalorieCounter" />
<activity android:name=".FetchFeedbacks" />
<activity android:name=".AdminHome" />
<activity android:name=".FeedBack" />
<activity android:name=".AdminDel" />
<activity android:name=".UpdateData" />
<activity android:name=".Fetchdata" />
<activity android:name=".Admin_add" />
<activity android:name=".BmiInfo" />
<activity android:name=".AdminAct" />
<activity android:name=".Loseweight_nutrition" />
<activity android:name=".Maintainweight_nutrition" />
<activity android:name=".Overweight_nutrition" />
<activity android:name=".Nutrition" />
<activity android:name=".CalmMood" />
<activity android:name=".AnnoyedMood" />
<activity android:name=".AngryMood" />
<activity android:name=".SadMood" />
<activity android:name=".HappyMood" />
<activity android:name=".MoodFeature" />
<activity android:name=".Calendar" />
<activity android:name=".Alarm" />
<activity
android:name=".StopWatch"
android:parentActivityName=".Home" />
<activity android:name=".Splash">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".Exercice"
android:windowSoftInputMode="adjustPan" />
<activity android:name=".BMI_Calculator" />
<activity android:name=".Home" />
<activity android:name=".EditProfile" />
<activity android:name=".Login" />
<activity android:name=".Register" />
<activity android:name=".MainActivity" />
<meta-data
android:name="preloaded_fonts"
android:resource="#array/preloaded_fonts" />
<receiver
android:name=".AlertReceiver"
android:enabled="true"
android:exported="true"
android:process=":remote" />
</application>
</manifest>
I am trying to implement simple quick settings tile with the help of google docs,
but my tile appears to be there but greyed out(intent activity)- I can't click or do anything with it and cant remove it either without restarting my phone(one plus 3T/oreo8.0.0).
and the same thing goes with sample code google provided.
what things do i need to keep in mind/ how to do it?
is there anything I am missing?
I saw one similar question but it was a bit over my head.
MANIFEST
<application
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".QSIntentService"
android:icon="#drawable/ic_android_black_24dp"
android:label="#string/qs_intent_tile_label"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE" />
</intent-filter>
</service>
<activity
android:name=".ResultActivity"
android:label="#string/result_label"/>
</application>
JAVA (Main ACtivity)
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
QSintentservice.java
public class QSIntentService extends TileService{
private static final String SERVICE_STATUS_FLAG = "serviceStatus";
private static final String PREFERENCES_KEY = "com.google.android_quick_settings";
#Override
public void onClick() {
updateTile();
boolean isCurrentlyLocked = this.isLocked();
if (!isCurrentlyLocked) {
Resources resources = getApplication().getResources();
Tile tile = getQsTile();
String tileLabel = tile.getLabel().toString();
String tileState = (tile.getState() == Tile.STATE_ACTIVE) ?
resources.getString(R.string.service_active) :
resources.getString(R.string.service_inactive);
Intent intent = new Intent(getApplicationContext(),
ResultActivity.class);
intent.putExtra(ResultActivity.RESULT_ACTIVITY_NAME_KEY,
tileLabel);
intent.putExtra(ResultActivity.RESULT_ACTIVITY_INFO_KEY,
tileState);
startActivityAndCollapse(intent);
}
}
private void updateTile() {
Tile tile = this.getQsTile();
boolean isActive = getServiceStatus();
Icon newIcon;
String newLabel;
int newState;
if (isActive) {
newLabel = String.format(Locale.US,
"%s %s",
getString(R.string.tile_label),
getString(R.string.service_active));
newIcon = Icon.createWithResource(getApplicationContext(), ic_android_black_24dp);
newState = Tile.STATE_ACTIVE;
} else {
newLabel = String.format(Locale.US,
"%s %s",
getString(R.string.tile_label),
getString(R.string.service_inactive));
newIcon =
Icon.createWithResource(getApplicationContext(),
android.R.drawable.ic_dialog_alert);
newState = Tile.STATE_INACTIVE;
}
tile.setLabel(newLabel);
tile.setIcon(newIcon);
tile.setState(newState);
tile.updateTile();
}
private boolean getServiceStatus() {
SharedPreferences prefs =
getApplicationContext()
.getSharedPreferences(PREFERENCES_KEY,
MODE_PRIVATE);
boolean isActive = prefs.getBoolean(SERVICE_STATUS_FLAG, false);
isActive = !isActive;
prefs.edit().putBoolean(SERVICE_STATUS_FLAG, isActive).apply();
return isActive;
}
}
Result.java
public class ResultActivity extends AppCompatActivity {
public static final String RESULT_ACTIVITY_INFO_KEY = "resultActivityInfo";
public static final String RESULT_ACTIVITY_NAME_KEY = "resultActivityName";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_result);
if (getIntent() != null) {
Bundle extras = getIntent().getExtras();
assert extras != null;
String tileState = extras.getString(RESULT_ACTIVITY_INFO_KEY);
String tileName = extras.getString(RESULT_ACTIVITY_NAME_KEY);
TextView outputText = findViewById(R.id.result_info);
outputText.setText(String.format(Locale.US,
getString(R.string.result_output),
tileName,
tileState));
TextView returnHome = findViewById(R.id.result_return_main);
returnHome.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent goHome = new Intent(getApplicationContext(),
MainActivity.class);
startActivity(goHome);
}
});
}
}
}
This code works fine on other devices. However, there is an issue in one plus quick setting menu as its observed and brought to notice. Check the below link to verify,
https://forums.oneplus.net/threads/android-oreo-8-0-oxigenos-quick-settings-bug.690621/
I am trying to implement a spell checker service as described here called SampleSpellCheckerService but it seems the tutorial is incomplete and the source code for it does not seem to be available.
I am struggling with how to get a session from my spell checker service in the setSuggestionsFor() method of my activity, as highlighted here:
public class SpellCheckerSettingsActivity extends AppCompatActivity implements SpellCheckerSession.SpellCheckerSessionListener {
private static final String LOG_TAG = SpellCheckerSettingsActivity.class.getSimpleName();
private TextView textView = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_spell_checker_settings);
final EditText editText = (EditText)findViewById(R.id.editText);
textView = (TextView)findViewById(R.id.textView);
Button button = (Button)findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
fetchSuggestionsFor(editText.getText().toString());
}
});
startService(new Intent(this, SampleSpellCheckerService.class));
}
private void fetchSuggestionsFor(String input){
Log.d(LOG_TAG, "fetchSuggestionsFor(\"" + input + "\")");
/***************************************************
*
* This line is invalid. What do I replace it with?
*
***************************************************/
SpellCheckerSession session = SampleSpellCheckerService.getSession();
TextInfo[] textInfos = new TextInfo[]{ new TextInfo(input) };
int suggestionsLimit = 5;
session.getSentenceSuggestions(textInfos, suggestionsLimit);
}
#Override
public void onGetSuggestions(SuggestionsInfo[] results) {
Log.d(LOG_TAG, "onGetSuggestions(" + results + ")");
runOnUiThread(new Runnable() {
#Override
public void run() {
textView.setText("Suggestions obtained (TODO - get from results[])");
}
});
}
#Override
public void onGetSentenceSuggestions(SentenceSuggestionsInfo[] results) {
Log.d(LOG_TAG, "onGetSentenceSuggestions(" + results + ")");
if (results != null) {
final StringBuffer sb = new StringBuffer("");
for (SentenceSuggestionsInfo result : results) {
int n = result.getSuggestionsCount();
for (int i = 0; i < n; i++) {
int m = result.getSuggestionsInfoAt(i).getSuggestionsCount();
for (int k = 0; k < m; k++) {
sb.append(result.getSuggestionsInfoAt(i).getSuggestionAt(k))
.append("\n");
}
sb.append("\n");
}
}
runOnUiThread(new Runnable() {
#Override
public void run() {
textView.setText(sb.toString());
}
});
}
}
#Override
public void onDestroy() {
stopService(new Intent(this, SampleSpellCheckerService.class));
super.onDestroy();
}
}
So what is the correct way to get a session from SampleSpellCheckerService?
For completeness, here is my spell checker service class:
public class SampleSpellCheckerService extends SpellCheckerService {
public static final String LOG_TAG = SampleSpellCheckerService.class.getSimpleName();
public SampleSpellCheckerService() {
Log.d(LOG_TAG, "SampleSpellCheckerService");
}
#Override
public void onCreate() {
super.onCreate();
Log.d(LOG_TAG, "SampleSpellCheckerService.onCreate");
}
#Override
public Session createSession() {
Log.d(LOG_TAG, "createSession");
return new AndroidSpellCheckerSession();
}
private static class AndroidSpellCheckerSession extends SpellCheckerService.Session {
#Override
public void onCreate() {
Log.d(LOG_TAG, "AndroidSpellCheckerSession.onCreate");
}
#Override
public SentenceSuggestionsInfo[] onGetSentenceSuggestionsMultiple(TextInfo[] textInfos, int suggestionsLimit) {
Log.d(LOG_TAG, "onGetSentenceSuggestionsMultiple");
SentenceSuggestionsInfo[] suggestionsInfos = null;
//suggestionsInfo = new SuggestionsInfo();
//... // look up suggestions for TextInfo
return suggestionsInfos;
}
#Override
public SuggestionsInfo onGetSuggestions(TextInfo textInfo, int suggestionsLimit) {
Log.d(LOG_TAG, "onGetSuggestions");
SuggestionsInfo suggestionsInfo = null;
//suggestionsInfo = new SuggestionsInfo();
//... // look up suggestions for TextInfo
return suggestionsInfo;
}
#Override
public void onCancel() {
Log.d(LOG_TAG, "onCancel");
}
}
}
Here is my manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example">
<permission android:name="android.permission.BIND_TEXT_SERVICE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<service
android:name="com.example.SampleSpellCheckerService"
android:label="#string/app_name"
android:enabled="true"
android:permission="android.permission.BIND_TEXT_SERVICE">
<intent-filter>
<action android:name="android.service.textservice.SpellCheckerService" />
</intent-filter>
<meta-data
android:name="android.view.textservice.scs"
android:resource="#xml/spellchecker" />
</service>
<activity android:name="com.example.SpellCheckerSettingsActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
And here is my spellchecker.xml:
<?xml version="1.0" encoding="utf-8"?>
<spell-checker
xmlns:android="http://schemas.android.com/apk/res/android"
android:label="#string/spellchecker_name"
android:settingsActivity="com.example.SpellCheckerSettingsActivity">
<subtype
android:label="#string/subtype_generic"
android:subtypeLocale="en" />
/>
<subtype
android:label="#string/subtype_generic"
android:subtypeLocale="en_GB" />
/>
</spell-checker>
NB - I am testing with a Samsung device.
As far as I can see from the docs and some sample code, there seems to be some misconception of the android Spell Checking API, that result in your error.
As far as I can tell you can't call your service directly since the APIs goal is for you to define a spellchecker that the user has to select from the system settings first. Basically you mixed up the settings activity (that is displayed for service related settings) with a test activity for your service.
Some better tutorials are written in the android dev blog and here, some sample code for a testing client and an rudimentary example service could be found between the mirrored android samples on github.
What you got so far is the sample service (though the linked samples provide some more code to see how the methods could be implemented), you have your spellchecker.xml needed for locale definition and the spellchecker name appearing in the settings, you already have a settings activity (as defined in your spellchecker.xml, but not needed as long as you don't need any preferences) and you have an activity implementing your SpellCheckerSessionListener (although you named it as settings activity).
What you'd still need to do, is go to your settings -> Language & keyboard -> activate Spell checker and choose your spell checker.
To get a session from that spellchecker you can then make a call to the API with
final TextServicesManager tsm = (TextServicesManager) getSystemService(
Context.TEXT_SERVICES_MANAGER_SERVICE);
mScs = tsm.newSpellCheckerSession(null, null, this, true);
as seen in the samples.
Edit:
if you don't need any settings for your service, you can remove the xml attribute from your xml:
android:settingsActivity="com.example.SpellCheckerSettingsActivity"
I am trying to send a simple message from my wear [Emulator] to my android phone, The message should have been sent according to my logs on the wear but it does not trigger my "showToast" method on my phone [it should be triggered when a message is received]. Anyone has an idea what I could be doing wrong?
This is my Wear Manifest
<manifest package="georgikoemdzhiev.weartesttwo"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-feature android:name="android.hardware.type.watch"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#android:style/Theme.DeviceDefault">
<uses-library
android:name="com.google.android.wearable"
android:required="false"/>
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#android:style/Theme.DeviceDefault.Light">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
This is my Mobile manifest
<manifest package="georgikoemdzhiev.weartesttwo"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service android:name=".ReceiveMessageService">
<intent-filter>
<action android:name="com.google.android.gms.wearable.MESSAGE_RECEIVED" />
<data android:scheme="wear" android:host="*" android:pathPrefix="/prefix" />
</intent-filter>
</service>
</application>
This is my Wear logic [I have a button that sends the showToast message]
public class MainActivity extends WearableActivity {
private static final long CONNECTION_TIME_OUT_MS = 2500;
private static final String TAG = MainActivity.class.getSimpleName();
private CircularButton mSendButton;
private List<Node> myNodes = new ArrayList<>();
private static final SimpleDateFormat AMBIENT_DATE_FORMAT =
new SimpleDateFormat("HH:mm", Locale.UK);
private BoxInsetLayout mContainerView;
private TextView mTextView;
private TextView mClockView;
private GoogleApiClient mClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setAmbientEnabled();
mSendButton = (CircularButton)findViewById(R.id.sendToast);
mSendButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
sendToastMessage();
}
});
mClient = new GoogleApiClient.Builder(this)
.addApiIfAvailable(Wearable.API)
.build();
getNodes();
mContainerView = (BoxInsetLayout) findViewById(R.id.container);
mTextView = (TextView) findViewById(R.id.text);
mClockView = (TextView) findViewById(R.id.clock);
}
private void sendToastMessage() {
Log.d(TAG,"Sending message... Nodes List size:" + myNodes.size());
// send toast message logic...
new Thread(new Runnable() {
#Override
public void run() {
for(Node n:myNodes) {
Log.d(TAG,"Sending message to node:"+n.getDisplayName());
Wearable.MessageApi.sendMessage(mClient,n.getId(),"/showToast",null);
}
}
});
}
private List<Node> getNodes(){
new Thread(new Runnable() {
//
#Override
public void run() {
Log.d(TAG,"Getting nodes...");
mClient.blockingConnect(CONNECTION_TIME_OUT_MS, TimeUnit.MILLISECONDS);
NodeApi.GetConnectedNodesResult result = Wearable.NodeApi.getConnectedNodes(mClient).await();
List<Node> nodes = result.getNodes();
for(Node n:nodes){
Log.d(TAG,"Adding Node: "+n.getDisplayName());
myNodes.add(n);
}
Log.d(TAG,"Getting nodes DONE!");
}
}).start();
return null;
}
}
This is my ReceiveMessageService in Mobile
public class ReceiveMessageService extends WearableListenerService {
#Override
public void onMessageReceived(MessageEvent messageEvent) {
Log.d("ReceiveMessageService","onMessageReceived");
//if(messageEvent.getPath().equals("/showToast")) {
showToast(messageEvent.getPath());
//}
}
private void showToast(String message) {
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
}
}
This is my MainActivity in Mobile
public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener{
private static final String TAG = MainActivity.class.getSimpleName();
private GoogleApiClient mGoogleApiClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Wearable.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
mGoogleApiClient.connect();
}
#Override
public void onConnected(#Nullable Bundle bundle) {
Log.d(TAG,"onConnected");
}
#Override
public void onConnectionSuspended(int i) {
Log.d(TAG,"onConnectionSuspended");
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.d(TAG,"onConnectionFailed");
}
It looks like you are using wrong pathPrefix in your mobile side AndroidManifest. Try to replace
<data android:scheme="wear" android:host="*" android:pathPrefix="/prefix" />
with
<data android:scheme="wear" android:host="*" android:pathPrefix="/showToast" />
Edit
Also keep in mind that MessageApi is not guarantee to deliver a message even if it returns a successful result code as Google's document stated:
Note: A successful result code does not guarantee delivery of the message. If your app requires data reliability, use DataItem objects or the ChannelApi class to send data between devices.
I want to archive network change listener in my app. For example: When I start my app without ON Mobile Data and Wifi then it shows "Network unavailable!". After that when I ON Wifi or Mobile Data than that it automatically get data online and show on UI.
I have Main activity which already extends Fragment implements interface as well as base fragment too.
I tried broadcastreceiver but it not works. when I run app without network it shows no internet connection two time. And after Wifi ON not update automatically but when I clicked Other Option in menu then UI shows. Please help me...
1- Main Activity
public class MainActivity extends AppCompatActivity implements BaseFragment.OnFragmentInteractionListener{
private Realm realm;
private Results results;
RecycleAdapter recyclerAdapter;
BroadcastReceiver receiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
RealmConfiguration realmConfiguration = new RealmConfiguration.Builder
(MainActivity.this)
.build();
Realm.setDefaultConfiguration(realmConfiguration);
}
#Override
public void onTabletListener(Results result) {
DetailFragment detailFragment = (DetailFragment) getFragmentManager()
.findFragmentById(R.id.fragment_detail);
if (detailFragment != null) {
detailFragment.updateTabletUI(result);
}
}
#Override
public void onFragmentInteraction(Results currentMovie) {
DetailFragment detailFragment = (DetailFragment) getFragmentManager()
.findFragmentById(R.id.fragment_detail);
if (detailFragment == null) {
Intent intent = new Intent(this, DetailActivity.class)
.putExtra("movie_Id", currentMovie.getId())
.putExtra("movie_Name", currentMovie.getTitle())
.putExtra("poster_Path", currentMovie.getPoster_path())
.putExtra("back_poster_Path", currentMovie.getBackdrop_path())
.putExtra("release_Date", currentMovie.getRelease_date())
.putExtra("users_Rating", currentMovie.getVote_average())
.putExtra("overview", currentMovie.getOverview());
startActivity(intent);
} else {
detailFragment.updateTabletUI(currentMovie);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.favoriteList) {
Intent intent=new Intent(MainActivity.this, FavoriteActivity.class);
startActivity(intent);
}
return super.onOptionsItemSelected(item);
}
}
2- Base Fragment class
public class BaseFragment extends android.app.Fragment implements RecycleAdapter.GetDataFromAdapter {
#Bind(R.id.recyclerView)
RecyclerView recyclerView;
private static final String STATE_MOVIES = "state_movies";
private View rootView, noView;
private DataManager dataManager;
private RecycleAdapter recyclerAdapter;
private MovieResponse movieResponse;
private List<Results> resultsList;
private Results results;
private OnFragmentInteractionListener mListener;
private int menuItemPosition;
private BroadcastReceiver receiver;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelableArrayList(STATE_MOVIES, (ArrayList<? extends Parcelable>) resultsList);
outState.putInt("menu_item", menuItemPosition);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.most_Popular:
if(item.isChecked()){
}else{
item.setChecked(true);
menuItemPosition = item.getItemId();
makeService("POPULAR");
return true;
}
case R.id.high_rated:
if(item.isChecked()){
}else{
item.setChecked(true);
menuItemPosition = item.getItemId();
makeService("TOP");
return true;
}
}
return super.onOptionsItemSelected(item);
}
#Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
// this will get called when the activity is re-created on device configuration change
menu.findItem(menuItemPosition).setChecked(true);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_base, container, false);
ButterKnife.bind(this, rootView);
resultsList=new ArrayList<Results>();
configRecycleView();
if (savedInstanceState==null){
receiver=new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
int status= NetworkStatus.getConnectivityStatus(context);
if (status==0){
}else{
makeService("POPULAR");
}
}
};
menuItemPosition = R.id.most_Popular;
}else{
resultsList=savedInstanceState.getParcelableArrayList(STATE_MOVIES);
menuItemPosition = savedInstanceState.getInt("menu_item");
recyclerAdapter.addMovieList(resultsList);
}
return rootView;
}
private void configRecycleView() {
AutofitGridlayout layoutManager = new AutofitGridlayout(getActivity(), 200 );
recyclerView.setHasFixedSize(true);
recyclerView.setRecycledViewPool(new RecyclerView.RecycledViewPool());
recyclerView.setLayoutManager(layoutManager);
recyclerAdapter = new RecycleAdapter(getActivity(), BaseFragment.this);
recyclerView.setAdapter(recyclerAdapter);
}
private void makeService(String query){
dataManager = new DataManager();
Call<MovieResponse> listCall;
if (query=="TOP") {
listCall= dataManager.getJSONData().getTopMovies();
}else{
listCall= dataManager.getJSONData().getPopMovies();
}
listCall.enqueue(new Callback<MovieResponse>() {
#Override
public void onResponse(Call<MovieResponse> call, Response<MovieResponse> response) {
if (response.isSuccessful()) {
Results[] results = response.body().getResults();
resultsList = new ArrayList<Results>(Arrays.asList(results));
recyclerAdapter.addMovieList(resultsList);
Results firstResult=resultsList.get(0);
mListener.onTabletListener(firstResult);
}
}
#Override
public void onFailure(Call<MovieResponse> call, Throwable t) {
Snackbar.make(rootView, R.string.Network_error, Snackbar.LENGTH_LONG)
.show();
}
});
}
#Override
public void onCurrentMovie(Results currentMovie) {
mListener.onFragmentInteraction(currentMovie);
}
#Override
public void onAttach(Activity context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
public interface OnFragmentInteractionListener {
void onTabletListener(Results result);
void onFragmentInteraction(Results result);
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
}
3- NetworkStatus class
public class NetworkStatus {
public static int TYPE_WIFI = 1;
public static int TYPE_MOBILE = 2;
public static int TYPE_NOT_CONNECTED = 0;
public static int getConnectivityStatus(Context context) {
ConnectivityManager cm = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
if (null != activeNetwork) {
if(activeNetwork.getType() == ConnectivityManager.TYPE_WIFI)
return TYPE_WIFI;
if(activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE)
return TYPE_MOBILE;
}
return TYPE_NOT_CONNECTED;
}
}
4- manifest ---
<manifest package="com.santossingh.popularmovieapp"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".Activities.MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".Activities.FavoriteActivity"
android:label="#string/title_activity_favorite"
android:parentActivityName=".Activities.MainActivity"
android:theme="#style/AppTheme.NoActionBar">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".Activities.MainActivity"/>
</activity>
<activity
android:name=".Activities.VideoActivity"
android:label="#string/title_activity_video"
android:theme="#style/AppTheme.NoActionBar">
</activity>
<activity
android:name=".Activities.DetailActivity"
android:label="#string/title_activity_detail"
android:parentActivityName=".Activities.MainActivity"
android:theme="#style/AppTheme.NoActionBar">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.santossingh.popularmovieapp.Activities.MainActivity"/>
</activity>
<activity
android:name=".Activities.ReviewActivity"
android:label="#string/title_activity_review"
android:theme="#style/AppTheme.NoActionBar">
</activity>
</application>
</manifest>
First thing is it seems you have not set receiver for network in manifest file, so in Manifest file after all activity tags completed, inside application tag write down below code to register your receiver.
<receiver android:name=".Activities.NetworkChangeReceiver" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
</application>
Note that if you don't have receiver then check below and use it.
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class NetworkChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent intent)
{
String status = NetworkUtil.getConnectivityStatusString(context);
Toast.makeText(context, status, Toast.LENGTH_LONG).show();
}
}