How to use UseButton in android - android

i need UseButton in my app to link uber app.For this i have implemented the following code.In useButton Developer site, it has been said to submit for review. while filling the review form, its asking screenshot with a working button. but my button in the screen is not visible. how can it be working button.
please help me.
public class MainActivity2 extends AppCompatActivity {
RelativeLayout rootLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rootLayout = (RelativeLayout) findViewById(R.id.rootlayout);
final ButtonDropin buttonDropin = new ButtonDropin(MainActivity2.this);
buttonDropin.setButtonId("btn-11cd09c63aaa7c02");
buttonDropin.setBackgroundResource(R.drawable.ic_app_button);
buttonDropin.setTextSize_Button(getResources().getDimensionPixelSize(R.dimen.my_text_size));
ButtonContext contexts = null;
try {
final RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
buttonDropin.setLayoutParams(layoutParams);
rootLayout.addView(buttonDropin);
contexts = ButtonContext.withSubjectLocation(new Location("Button HQ", 11.9362587, 79.8268325));
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
final android.location.Location userLocations = new LocationProvider(this).getBestLocation();
if (userLocations != null) {
contexts.setUserLocation(new Location(userLocations));
}
}catch (Exception e){
Toast.makeText(MainActivity2.this,"Exception :"+e,Toast.LENGTH_LONG).show();
}
buttonDropin.prepareForDisplay(contexts, new ButtonDropin.Listener() {
#Override
public void onPrepared(final boolean isReady) {
Toast.makeText(MainActivity2.this,"IsReady:"+isReady,Toast.LENGTH_LONG).show();
}
#Override
public void onClick(ButtonDropin buttonDropin) {
Toast.makeText(MainActivity2.this,"buttonDropin onclick",Toast.LENGTH_LONG).show();
}
});
}}

Buttons that need to be reviewed will still render. Also, Buttons will only render if there is inventory to display (for this example, will there be Ubers to take from where the user is to where the user is going, which set in the Context).
First, add the Button SDK to your app's build.gradle file
compile 'com.usebutton:android-sdk:5+'
Then, add Button to your AndroidManifest.xml file
<application
<activity
<!-- your activities -->
</activity>
<!--Button SDK-->
<meta-data android:name="com.usebutton.applicationid" android:value="YOUR_BUTTON_APP_ID"/>
</application>
Then, import the SDK at the top of the Activity and start it. This should be called when your application class is created.
import com.usebutton.sdk.Button;
public class MyApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
Button.getButton(this).start();
}
}
Then, add the Button to your view:
<com.usebutton.sdk.ButtonDropin
android:id="#+id/main_dropin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
And then load the action for your Button in your Activity file:
final ButtonDropin buttonDropin = (ButtonDropin) findViewById(R.id.main_dropin);
// Set location to go to
final Location location = new Location("LOCATION_NAME", LATITUDE, LONGITUDE);
// Create Button Context
final ButtonContext buttonContext = ButtonContext.withSubjectLocation(location);
// Get Button Action and display if there is inventory
Button.getButton(this).getAction("YOUR_BUTTON_ID", buttonContext, "my-pub-ref", new Button.ActionListener() {
#Override
public void onAction(final AppAction action) {
// Display Button
buttonDropin.prepareWithAction(action);
}
#Override
public void onNoAction() {
// Don't display Button
buttonDropin.setVisibility(View.GONE);
}
});

Related

Main activity class of loaded Dynamic feature is not found

I am trying to add dynamic feature support to my app, so I created a test app.
The test app has a main app part that loads a dynamic feature and try to execute it.
The feature module has MainActivityCalled as main activity.
What I get is that the feature loading process works because I get successful log messages, and I get the list of installed modules.
Note that the app is run on a virtual device and no real download happens, I thinks everything gets installed automatically by deployment procedure from AndroidStudio.
The fact is that I get this kind of error when trying to call the main activity of the module:
W/System.err: android.content.ActivityNotFoundException: Unable to find explicit activity class {com.example.dynamicfeature1/MainActivityCalled}; have you declared this activity in your AndroidManifest.xml?
W/System.err: at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1805)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1523)
at android.app.Activity.startActivityForResult(Activity.java:4225)
at androidx.fragment.app.FragmentActivity.startActivityForResult(FragmentActivity.java:767)
at android.app.Activity.startActivityForResult(Activity.java:4183)
at androidx.fragment.app.FragmentActivity.startActivityForResult(FragmentActivity.java:754)
at android.app.Activity.startActivity(Activity.java:4522)
at android.app.Activity.startActivity(Activity.java:4490)
at com.example.mymodules.MainActivity$2.onClick(MainActivity.java:227)
at android.view.View.performClick(View.java:5637)
at android.view.View$PerformClick.run(View.java:22429)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
Everything is done as in the documentation at https://developer.android.com/guide/app-bundle/playcore#java
except for the explicit call to the module activity that I guessed has to be performed with an intent (no example in the above linked page).
Important part of the code you find below are:
new OnSuccessListener<Integer>() {
#Override
public void onSuccess(Integer result) {
Log.d("request feature load","success "+result);
mySessionId=result;
Set<String> installedModules = splitInstallManager.getInstalledModules();
String[] modules = new String[installedModules.size()];
installedModules.toArray(modules);
for (int i=0;i<modules.length;i++)
{
Log.d("module",modules[i]);
}
}
})
that is OK.
Then
Button button2 = findViewById(R.id.fab2);
button2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.d("feature1","called");
Intent intent=new Intent();
intent.setClassName("com.example.dynamicfeature1","MainActivityCalled");
try{ startActivity(intent);}
catch (Exception e){
e.printStackTrace();
}
}
});
All main activities has this overidden method
#Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
// Emulates installation of on demand modules using SplitCompat.
SplitCompat.installActivity(this);
Log.d("attachBaseContext",base.getPackageName().toString());
}
that is not called in the dynamic feature module when installed.
What is wrong with my code?
This is the Mainactivity of the app
package com.example.mymodules;
...imports...
public class MainActivity extends AppCompatActivity {
private static int MY_REQUEST_CODE=1;
Activity activity;
int mySessionId;
#Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
// Emulates installation of future on demand modules using SplitCompat.
SplitCompat.install(this);
Log.d("attachBaseContext",base.getPackageName().toString());
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == MY_REQUEST_CODE) {
// Handle the user's decision. For example, if the user selects "Cancel",
// you may want to disable certain functionality that depends on the module.
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activity = this;
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
Button button1 = findViewById(R.id.button1);
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Creates an instance of SplitInstallManager.
final SplitInstallManager splitInstallManager =
SplitInstallManagerFactory.create(activity);
// Creates a request to install a module.
SplitInstallRequest request =
SplitInstallRequest
.newBuilder()
// You can download multiple on demand modules per
// request by invoking the following method for each
// module you want to install.
.addModule("dynamicfeature1")
.build();
// Creates a listener for request status updates.
SplitInstallStateUpdatedListener listener =new SplitInstallStateUpdatedListener() {
#Override
public void onStateUpdate(SplitInstallSessionState state) {
if (state.status() == SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION) {
// Displays a dialog for the user to either “Download”
// or “Cancel” the request.
try {
splitInstallManager.startConfirmationDialogForResult(
state,
/* activity = */ activity,
// You use this request code to later retrieve the user's decision.
/* requestCode = */ MY_REQUEST_CODE);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
}
if (state.sessionId() == mySessionId) {
switch (state.status()) {
case SplitInstallSessionStatus.INSTALLED:
Context tempNewContext=null;
try {
tempNewContext = activity.createPackageContext(activity.getPackageName(), 0);
} catch (PackageManager.NameNotFoundException e) {
}
final Context newContext =tempNewContext;
// If you use AssetManager to access your app’s raw asset files, you’ll need
// to generate a new AssetManager instance from the updated context.
AssetManager am = newContext.getAssets();
if (BuildCompat.isAtLeastO()) {
// Updates the app’s context with the code and resources of the
// installed module.
SplitInstallHelper.updateAppInfo(newContext);
new Handler().post(new Runnable() {
#Override public void run() {
// Loads contents from the module using AssetManager
AssetManager am = newContext.getAssets();
}
});
} else
{SplitInstallHelper.updateAppInfo(newContext);}
}
}
}
} ;
splitInstallManager.registerListener(listener);
splitInstallManager
// Submits the request to install the module through the
// asynchronous startInstall() task. Your app needs to be
// in the foreground to submit the request.
.startInstall(request)
// You should also be able to gracefully handle
// request state changes and errors. To learn more, go to
// the section about how to Monitor the request state.
.addOnSuccessListener(new OnSuccessListener<Integer>() {
#Override
public void onSuccess(Integer result) {
Log.d("request feature load","success "+result);
mySessionId=result;
Set<String> installedModules = splitInstallManager.getInstalledModules();
String[] modules = new String[installedModules.size()];
installedModules.toArray(modules);
for (int i=0;i<modules.length;i++)
{
Log.d("module",modules[i]);
}
}
})
.addOnFailureListener(new OnFailureListener() {
void checkForActiveDownloads() {
splitInstallManager
// Returns a SplitInstallSessionState object for each active session as a List.
.getSessionStates()
.addOnCompleteListener(
new OnCompleteListener<List<SplitInstallSessionState>>() {
#Override
public void onComplete(Task<List<SplitInstallSessionState>> task) {
if (task.isSuccessful()) {
// Check for active sessions.
for (SplitInstallSessionState state : task.getResult()) {
if (state.status() == SplitInstallSessionStatus.DOWNLOADING) {
// Cancel the request, or request a deferred installation.
}
}
}
}
});
}
#Override
public void onFailure(Exception e) {
Log.d("request feature load","failure "+e.getMessage());
switch (((SplitInstallException) e).getErrorCode()) {
case SplitInstallErrorCode.NETWORK_ERROR:
// Display a message that requests the user to establish a
// network connection.
break;
case SplitInstallErrorCode.ACTIVE_SESSIONS_LIMIT_EXCEEDED:
checkForActiveDownloads();
}
}
});
}
});
Button button2 = findViewById(R.id.button2);
button2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.d("feature1","called");
Intent intent=new Intent();
intent.setClassName("com.example.dynamicfeature1","MainActivityCalled");
try{ startActivity(intent);}
catch (Exception e){
e.printStackTrace();
}
}
});
Button button3 = findViewById(R.id.button3);
button3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.d("feature2","called");
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
here's the main app manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:dist="http://schemas.android.com/apk/distribution"
package="com.example.mymodules">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:name="com.google.android.play.core.splitcompat.SplitCompatApplication"
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>
</application>
</manifest>
Then there is the MainActivity of the dyamic feature module
package com.example.dynamicfeature1;
...imports...
public class MainActivityCalled extends AppCompatActivity {
#Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
// Emulates installation of on demand modules using SplitCompat.
SplitCompat.installActivity(this);
Log.d("attachBaseContext",base.getPackageName().toString());
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "1-Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
}
and the module manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:dist="http://schemas.android.com/apk/distribution"
package="com.example.dynamicfeature1">
<dist:module
dist:instant="false"
dist:title="#string/title_dynamicfeature1">
<dist:delivery>
<dist:on-demand />
</dist:delivery>
<dist:fusing dist:include="false" />
</dist:module>
<application>
<activity
android:name=".MainActivityCalled"
android:label="#string/title_activity_main"
android:theme="#style/AppTheme.NoActionBar"></activity>
</application>
</manifest>
The right instruction to call the activity is
intent. setClassName(BuildConfig.APPLICATION_ID, "com.example.dynamicfeature.MainActivityCalled");
It works, the activity gets called.
Note that BuildConfig.APPLICATION_ID is
com.example.mymodules
If this string is used in the dynamic modules too, you can make cross-calls:
-from one module to another
-from one module to the main app
but you do not want to use BuildConfig.APPLICATION_ID in modules because there it is a different value, so the main string value has to be put into a variable.

ArcGIS Runtime: Detect if a point is within a certain area in a feature layer?

I have two layers in an application that uses ArcGIS Runtime. One is a basemap layer, and the other is a feature layer having certain areas marked on it.
How can I detect if my location is within those marked areas or not?
There are two things you need to do:
Get the device's location
Use the Display Device Location sample and add a LocationChangedListener
See if that location intersects one of the layer's features
Use the Feature Layer Query sample and adjust as needed.
Here's some code I wrote that puts it all together.
activity_main.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="so47119156.so47119156.MainActivity">
<TextView
android:id="#+id/textView_locationLabel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:text="Looking for your location..."/>
<com.esri.arcgisruntime.mapping.view.MapView
android:id="#+id/mapView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="#+id/textView_locationLabel">
</com.esri.arcgisruntime.mapping.view.MapView>
</RelativeLayout>
MainActivity.java:
public class MainActivity extends Activity {
private static final int PERM_REQ_START_LOCATION_DATA_SOURCE = 1;
// Change these to match your feature service.
private static final String FEATURE_SERVICE_URL =
"https://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer/3";
private static final String FEATURE_SERVICE_NAME_FIELD = "STATE_NAME";
private MapView mapView;
private FeatureLayer statesLayer;
private TextView textView_locationLabel;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Get the output label.
textView_locationLabel = findViewById(R.id.textView_locationLabel);
// Set up the map with a basemap and a feature layer.
mapView = findViewById(R.id.mapView);
ArcGISMap map = new ArcGISMap(Basemap.createTopographicVector());
statesLayer = new FeatureLayer(new ServiceFeatureTable(FEATURE_SERVICE_URL));
map.getOperationalLayers().add(statesLayer);
mapView.setMap(map);
// Check location permission and request if needed.
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
// Permission already granted.
startLocationServices();
} else {
// Permission not yet granted.
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, PERM_REQ_START_LOCATION_DATA_SOURCE);
}
}
/**
* Callback for ActivityCompat.requestPermissions. This method runs when the user allows or
* denies permission.
*/
#Override
public void onRequestPermissionsResult(
int requestCode,
#NonNull String[] permissions,
#NonNull int[] grantResults) {
if (PERM_REQ_START_LOCATION_DATA_SOURCE == requestCode) {
// This is a callback for our call to requestPermissions.
for (int i = 0; i < permissions.length; i++) {
String permission = permissions[i];
if (Manifest.permission.ACCESS_FINE_LOCATION.equals(permission)
&& PackageManager.PERMISSION_GRANTED == grantResults[i]) {
startLocationServices();
break;
}
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
#Override
protected void onResume() {
super.onResume();
mapView.resume();
}
#Override
protected void onPause() {
mapView.pause();
super.onPause();
}
#Override
protected void onStop() {
mapView.getLocationDisplay().stop();
super.onStop();
}
private void startLocationServices() {
// Add a location listener and then start the location display.
mapView.getLocationDisplay().addLocationChangedListener(new LocationDisplay.LocationChangedListener() {
#Override
public void onLocationChanged(LocationDisplay.LocationChangedEvent locationChangedEvent) {
// Location has changed. Query the feature layer.
QueryParameters params = new QueryParameters();
params.setGeometry(locationChangedEvent.getLocation().getPosition());
params.setSpatialRelationship(QueryParameters.SpatialRelationship.INTERSECTS);
try {
final FeatureQueryResult result = statesLayer.getFeatureTable()
.queryFeaturesAsync(params).get();
final Iterator<Feature> iterator = result.iterator();
if (iterator.hasNext()) {
textView_locationLabel.setText("You are in a state named "
+ iterator.next().getAttributes().get(FEATURE_SERVICE_NAME_FIELD));
} else {
textView_locationLabel.setText("You are not inside one of the states.");
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
});
mapView.getLocationDisplay().startAsync();
}
}
Result:

The Android navigation bar automatically changes colors according to criteria

I have a way to decide whether or not to change the color of the navigation bar based on whether a view is on the screen. The method has been written, but I do not know how to call it. I call this method with a button click event, but it is very hard. Want him to call automatically, rather than click on the event call, how can i do?
public class Index extends Activity implements View.OnClickListener{
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.index);
}
private void changeNavigationColour(View view){
Point p = new Point();
getWindowManager().getDefaultDisplay().getSize(p);
int[] loacation = new int[2];
view.getLocationInWindow(loacation);
Toast.makeText(this, Arrays.toString(loacation),Toast.LENGTH_SHORT).show();
Rect ivRect = new Rect(view.getLeft(),view.getTop(),view.getRight(),view.getBottom());
LinearLayout head = (LinearLayout) findViewById(R.id.index_head);
if(view.getLocalVisibleRect(ivRect)){
//Change the navigation color
head.setBackgroundColor(getResources().getColor(R.color.transparent));
}else {
//Change the navigation color
head.setBackgroundColor(getResources().getColor(R.color.colorPrimary));
}
}
Based on your comment it seems you need to call changeNavigationColour(View view) based on a phone call status
For that you can use a PhoneStateListener
public class Index extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.index);
TelephonyManager telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
telephonyManager.listen(new myPhoneStateChangeListener(),PhoneStateListener.LISTEN_CALL_STATE);
}
public class myPhoneStateChangeListener extends PhoneStateListener {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
// call changeNavigationColour based on the state
}
}
}
You also need to have this in your manifest
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>

Android - How to get a Session from my Spell Checker Service?

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"

Activity reset view on orientation change

I have some problems with Android Activity's orientation changes.
I have a game and some flying balloons on it. Balloon (ImageViews) are created dynamically, so they are flying. But when I change device orientation (to port or land) activity is re-creating and my balloons are disappearing. Same thing happens when I move to the next activity and then go back to my balloons activity.
Is there any way to "save" my dynamically created balloons (and it's position and other properties) on my activity
I also tried getLastNonConfigurationInstance() / onRetainNonConfigurationInstance() but it seems to me that it's work with data, not View elements (may be because parent of these views is previous activity)
public class Singleton {
private static final Singleton instance = new Singleton();
private Button btn;
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
public void createBtn(Context context, LinearLayout layout) {
if (btn == null) {
btn = new Button(context);
layout.addView(btn);
}
}
}
public class TestActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Singleton s = Singleton.getInstance();
s.createBtn(this, ((LinearLayout) findViewById(R.id.baseLayout)));
}
}
Button will not appear at second onCreate (on change orientation) (I think the problem is that Button's Context is previous Activity)
Updated code:
public class Singleton {
private static final Singleton instance = new Singleton();
private Button btn;
private SparseArray<Parcelable> container;
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
public void createBtn(Context context, LinearLayout layout) {
if (btn == null) {
btn = new Button(context);
layout.addView(btn);
btn.setText("Hello");
saveBtn();
} else if (container != null){
btn = new Button(context);
btn.restoreHierarchyState(container);
layout.addView(btn);
}
}
public void saveBtn() {
container = new SparseArray<Parcelable>();
btn.saveHierarchyState(container);
}
}
I think that on new Button should appear "Hello" text, but it's doesn't happen. Whats wrong?
Override the onSaveInstanceState() callback in your activity. Save all the data to the bundle you receive in this method. In onCreate of your activity check the savedInstance bundle for null. If its not null, read back and apply the data to your views.
Update
Don't check for null in createBtn method.
public void createBtn(Context context, LinearLayout layout) {
btn = new Button(context);
layout.addView(btn);
}
Update 2
Make the container variable static. I think you are losing the values when activity restarts.
You should be fine if you store all your data in onPause() and load it back in onResume().
Try this:
Add this into your activity declaration part in the manifiest.xml file:
android:configChanges="orientation|keyboardHidden"

Categories

Resources