Android Wearable.API is deprecated. What should I use instead? - android

I'm using the following:
GoogleApiClient mApiClient = new GoogleApiClient.Builder(this)
.addApi( Wearable.API )
...
Since Wearable.API is deprecated? What is the appropriate replacement?

I found something nice which is helpful
private class StartWearableActivityTask extends AsyncTask<Void, Void, Void> {
final String key;
public StartWearableActivityTask(String msg){
key = msg;
}
#Override
protected Void doInBackground(Void... args) {
Collection<String> nodes = getNodes();
for (String node : nodes) {
sendStartActivityMessage(node,key);
}
return null;
}
}
#WorkerThread
private Collection<String> getNodes() {
HashSet<String> results = new HashSet<>();
Task<List<Node>> nodeListTask =
Wearable.getNodeClient(getApplicationContext()).getConnectedNodes();
try {
// Block on a task and get the result synchronously (because this is on a background
// thread).
List<Node> nodes = Tasks.await(nodeListTask);
for (Node node : nodes) {
results.add(node.getId());
}
} catch (ExecutionException exception) {
Log.e(TAG, "Task failed: " + exception);
} catch (InterruptedException exception) {
Log.e(TAG, "Interrupt occurred: " + exception);
}
return results;
}
#WorkerThread
private void sendStartActivityMessage(String node,String event) {
Task<Integer> sendMessageTask =
Wearable.getMessageClient(this).sendMessage(node, event, new byte[0]);
try {
// Block on a task and get the result synchronously (because this is on a background
// thread).
Integer result = Tasks.await(sendMessageTask);
} catch (ExecutionException exception) {
Log.e(TAG, "Task failed: " + exception);
} catch (InterruptedException exception) {
Log.e(TAG, "Interrupt occurred: " + exception);
}
}

I found answer here:
https://developer.android.com/training/wearables/data-layer/migrate-to-googleapi
Migrate Wear apps to GoogleApi
Starting with version 11.8.0 of Google Play services, Wear OS apps should migrate away from the GoogleApiClient class and instead use client objects that are based on the GoogleApi class.
Use of GoogleApi makes it easier to set up asynchronous operations. For example, as described in the introduction to the Tasks API, you can obtain a Task object instead of a PendingResult object.

Related

Where to send message to smartwatch? ViewModel, UseCase or Repository?

Where should I place/split the following code?
The ViewModel shouldn't be responsible for business logic, but I also don't know how to handle the UseCases, have two 'special' UseCases for updating the Ip and the object, which then depend on a general UseCase (SendDataToWatch) to actually send the data? In that case, where should I get the Nodes list and decide to which node to send the message, in ViewModel?
Or should I pass the context to the Repository, but then, which one? (ConnectionDataRep, CmdObjectsRep or one created for this purpose).
Also, regarding the ThreadExecutor, since it is expensive to create, should I pass it from the ViewModel, or create it in each UseCase/Repository?
private Collection<String> getNodes() {
HashSet<String> results = new HashSet<>();
Wearable.getCapabilityClient()
Task<CapabilityInfo> nodeListTask = Wearable.getCapabilityClient(context).getCapability(WATCH_CAPABILITY, CapabilityClient.FILTER_REACHABLE);
try {
// Block on a task and get the result synchronously (because this is on a background
// thread).
Set<Node> nodes = Tasks.await(nodeListTask).getNodes();
for (Node node : nodes) {
results.add(node.getId());
}
} catch (ExecutionException exception) {
Log.e(TAG, "Task failed: " + exception);
} catch (InterruptedException exception) {
Log.e(TAG, "Interrupt occurred: " + exception);
}
return results;
}
private void updateAddrOnWatch(String node, String message) {
sendMessageToEndpoint(node, KeysConstants.UPDATE_CONN_PATH, strToBytes(message));
}
private void updateCmdObjects(String node, String jsonObjectsArr) {
sendMessageToEndpoint(node, KeysConstants.UPDATE_OBJECTS_PATH, strToBytes(jsonObjectsArr));
}
private void sendMessageToEndpoint(String node, String endpoint, byte[] message) {
Task<Integer> sendMessageTask =
Wearable.getMessageClient(context)
.sendMessage(node, endpoint, message);
try {
// Block on a task and get the result synchronously (because this is on a background
// thread).
Integer result = Tasks.await(sendMessageTask);
Log.d(TAG, "Message sent: " + result);
} catch (ExecutionException exception) {
Log.e(TAG, "Task failed: " + exception);
} catch (InterruptedException exception) {
Log.e(TAG, "Interrupt occurred: " + exception);
}
}

Getting API Exception Wearable API is not available on this device error

I have a button in my MapsActivity that communicates to the Wear app. The following Thread is executed:
class NewThread extends Thread {
String path;
String message;
NewThread(String p, String m) {
path = p;
message = m;
}
public void run() {
Task<List<Node>> wearableList =
Wearable.getNodeClient(getApplicationContext()).getConnectedNodes();
try {
List<Node> nodes = Tasks.await(wearableList);
for (Node node : nodes) {
Task<Integer> sendMessageTask =
Wearable.getMessageClient(MapsActivity.this).sendMessage(node.getId(), path, message.getBytes());
try {
Integer result = Tasks.await(sendMessageTask);
sendmessage("I just sent the wearable a message " + sentMessageNumber++);
} catch (final ExecutionException exception) {
MapsActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toasty.error(MapsActivity.this, "[1] Something went wrong. Error details: " + exception.getMessage()).show();
}
});
} catch (final InterruptedException exception) {
MapsActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toasty.error(MapsActivity.this, "[2] Something went wrong. Error details: " + exception.getMessage()).show();
}
});
}
}
} catch (final ExecutionException exception) {
MapsActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toasty.error(MapsActivity.this, "[3] Something went wrong. Error details: " + exception.getMessage()).show();
}
});
} catch (final InterruptedException exception) {
MapsActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toasty.error(MapsActivity.this, "[4] Something went wrong. Error details: " + exception.getMessage()).show();
}
});
}
}
}
But I get the following error in the image when trying to accomplish the Thread.
This happens on an Emulator where the WearOS app/api is not available to me (Probably on real devices which do not have WearOS App/Api too).
It happens on the Wearable.getMessageClient(MapsActivity.this).sendMessage(node.getId(), path, message.getBytes());.
I didn't find a clean way of checking the Wear API to be available so I am trying to get the capabilities first, catching the ApiException and setting a isWearableAvailable property:
private fun checkCapability() {
try {
val capability = capabilityClient
.getCapability(CAPABILITY_XYZ, CapabilityClient.FILTER_REACHABLE)
.await()
isConnected = capability.nodes.any(Node::isNearby)
if (BuildConfig.DEBUG) Log.d(LOG_TAG,
"Capability: ${capability.nodes.joinToString()}} > ${isConnected}")
isWearableApiAvailable = true
} catch (e: ApiException) {
isWearableApiAvailable = false
}
}

Not able to get the userprofile info of google+

I am able to retrieve the access token of google account.But I am unable to get the userprofile info.I am getting null pointer exception.Why i cant understand.
Below I have provided two methods using which we get access token and also gets the userprofile info.
It would be great if you help me.
MainActivity.java
private void tryAuthenticate() {
if (isFinishing()) {
return;
}
mToken = null;
setProgressBarIndeterminateVisibility(true);
AsyncTask<Void, Void, Boolean> task = new AsyncTask<Void, Void, Boolean>() {
#Override
protected Boolean doInBackground(Void... params) {
try {
mToken =
GoogleAuthUtil.getToken(MainActivity.this, mChosenAccountName, "oauth2:"
+ Scopes.PLUS_LOGIN + " " + "https://www.googleapis.com/auth/plus.login" + " "+" https://www.googleapis.com/auth/plus.profile.agerange.read"+" " +YouTubeScopes.YOUTUBE + " "
+ YouTubeScopes.YOUTUBE_UPLOAD);
} catch (GooglePlayServicesAvailabilityException playEx) {
GooglePlayServicesUtil.getErrorDialog(playEx.getConnectionStatusCode(),
MainActivity.this, REQUEST_GMS_ERROR_DIALOG).show();
} catch (UserRecoverableAuthException userAuthEx) {
// Start the user recoverable action using the intent
// returned by
// getIntent()
startActivityForResult(userAuthEx.getIntent(), REQUEST_AUTHENTICATE);
return false;
} catch (IOException transientEx) {
// TODO: backoff
Log.e(this.getClass().getSimpleName(), transientEx.getMessage());
} catch (GoogleAuthException authEx) {
Log.e(this.getClass().getSimpleName(), authEx.getMessage());
}
return true;
}
#Override
protected void onPostExecute(Boolean hideProgressBar) {
invalidateOptionsMenu();
if (hideProgressBar) {
setProgressBarIndeterminateVisibility(false);
}
if (mToken != null) {
runOnUiThread(new Runnable() {
#Override
public void run() {
saveAccount();
}
});
}
loadData();
}
};
task.execute((Void) null);
}
private void loadProfile() {
new AsyncTask<Void, Void, Person>() {
#Override
protected Person doInBackground(Void... voids) {
GoogleCredential credential = new GoogleCredential();
credential.setAccessToken(mToken);
HttpTransport httpTransport = new NetHttpTransport();
JsonFactory jsonFactory = new JacksonFactory();
Plus plus =
new Plus.Builder(httpTransport, jsonFactory, credential).setApplicationName(
Constants.APP_NAME).build();
try {
return plus.people().get("me").execute(); //here am getting null pointer exception
} catch (final GoogleJsonResponseException e) {
if (401 == e.getDetails().getCode()) {
Log.e(this.getClass().getSimpleName(), e.getMessage());
GoogleAuthUtil.invalidateToken(MainActivity.this, mToken);
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
tryAuthenticate();
}
}, mCurrentBackoff * 1000);
mCurrentBackoff *= 2;
if (mCurrentBackoff == 0) {
mCurrentBackoff = 1;
}
}
} catch (final IOException e) {
Log.e(this.getClass().getSimpleName(), e.getMessage());
}
return null;
}
#Override
protected void onPostExecute(Person me) {
mUploadsListFragment.setProfileInfo(me);
}
}.execute((Void) null);
}
It seems as if you have mixed and matched a lot of things all together. The line at which you are getting a Null Pointer is because the me is not defined anywhere else in the program and hence when the get method is called it is not able to find the value.
Secondly, you can separate out the code in two different files if you want to perform a set of two different operations. If you just want to retrieve the information regarding the profile information of a Google+ User account please follow the tutorial.

How to get Advertising ID in android programmatically

I want to get users Advertising ID programmatically.I used the below code from the developer site.But its not working
Info adInfo = null;
try {
adInfo = AdvertisingIdClient.getAdvertisingIdInfo(getApplicationContext());
} catch (IOException e) {
// Unrecoverable error connecting to Google Play services (e.g.,
// the old version of the service doesn't support getting AdvertisingId).
} catch (GooglePlayServicesNotAvailableException e) {
// Google Play services is not available entirely.
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (GooglePlayServicesRepairableException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
final String id = adInfo.getId();
final boolean isLAT = adInfo.isLimitAdTrackingEnabled();
How can I get user's advertising id programmatically ?? please help me
I might be late but this might help someone else!
AsyncTask<Void, Void, String> task = new AsyncTask<Void, Void, String>() {
#Override
protected String doInBackground(Void... params) {
AdvertisingIdClient.Info idInfo = null;
try {
idInfo = AdvertisingIdClient.getAdvertisingIdInfo(getApplicationContext());
} catch (GooglePlayServicesNotAvailableException e) {
e.printStackTrace();
} catch (GooglePlayServicesRepairableException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
String advertId = null;
try{
advertId = idInfo.getId();
}catch (NullPointerException e){
e.printStackTrace();
}
return advertId;
}
#Override
protected void onPostExecute(String advertId) {
Toast.makeText(getApplicationContext(), advertId, Toast.LENGTH_SHORT).show();
}
};
task.execute();
Get GAID(Google’s advertising ID)
1. Download latest Google Play Services SDK.
2. Import the code and add it as a library project.
3. Modify AndroidManifest.xml.
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
4. Enable ProGuard to shrink and obfuscate your code in project.properties this line
proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
5. Add rules in proguard-project.txt.
-keep class * extends java.util.ListResourceBundle {
protected Object[][] getContents(); }
-keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable {
public static final *** NULL; }
-keepnames #com.google.android.gms.common.annotation.KeepName class *
-keepclassmembernames class * {
#com.google.android.gms.common.annotation.KeepName *;
}
-keepnames class * implements android.os.Parcelable {
public static final ** CREATOR;
}
6. Call AdvertisingIdClient.getAdvertisingIdInfo(getApplicationContext()).getId() in a worker thread to get the id in String.
as like this
AsyncTask<Void, Void, String> task = new AsyncTask<Void, Void, String>() {
#Override
protected String doInBackground(Void... params) {
AdvertisingIdClient.Info idInfo = null;
try {
idInfo = AdvertisingIdClient.getAdvertisingIdInfo(getApplicationContext());
} catch (GooglePlayServicesNotAvailableException e) {
e.printStackTrace();
} catch (GooglePlayServicesRepairableException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
String advertId = null;
try{
advertId = idInfo.getId();
}catch (Exception e){
e.printStackTrace();
}
return advertId;
}
#Override
protected void onPostExecute(String advertId) {
Toast.makeText(getApplicationContext(), advertId, Toast.LENGTH_SHORT).show();
}
};
task.execute();
Enjoy!
or
https://developervisits.wordpress.com/2016/09/09/android-2/
You can call the below function in onCreate(Bundle savedInstanceState) of the activity
and in the logcat search for UIDMY then it will display the id like : I/UIDMY: a1cf5t4e-9eb2-4342-b9dc-10cx1ad1abe1
void getUIDs()
{
AsyncTask.execute(new Runnable() {
#Override
public void run() {
try {
AdvertisingIdClient.Info adInfo = AdvertisingIdClient.getAdvertisingIdInfo(SplashScreen.this);
String myId = adInfo != null ? adInfo.getId() : null;
Log.i("UIDMY", myId);
} catch (Exception e) {
Toast toast = Toast.makeText(context, "error occurred ", Toast.LENGTH_SHORT);
toast.setGravity(gravity, 0,0);
toast.show();
}
}
});
}
Just in case someone is interested in trying out the fetching AdvertisingId part while Rx-ing then this might be helpful.
private void fetchAndDoSomethingWithAdId() {
Observable.fromCallable(new Callable<String>() {
#Override
public String call() throws Exception {
return AdvertisingIdClient.getAdvertisingIdInfo(context).getId();
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<String>() {
#Override
public void call(String id) {
//do what you want to do with id for e.g using it for tracking
}
}, new Action1<Throwable>() {
#Override
public void call(Throwable throwable) {
throwable.printStackTrace();
}
});
}
The modern way is to use Coroutines in Kotlin, since AsyncTask is now being deprecated for Android. Here is how I did it:
import com.google.android.gms.ads.identifier.AdvertisingIdClient
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
class AdvertisingInfo(val context: Context) {
private val adInfo = AdvertisingIdClient(context.applicationContext)
suspend fun getAdvertisingId(): String =
withContext(Dispatchers.IO) {
//Connect with start(), disconnect with finish()
adInfo.start()
val adIdInfo = adInfo.info
adInfo.finish()
adIdInfo.id
}
}
When you are ready to use the advertising ID, you need to call another suspending function:
suspend fun applyDeviceId(context: Context) {
val advertisingInfo = AdvertisingInfo(context)
// Here is the suspending function call,
// in this case I'm assigning it to a static object
MyStaticObject.adId = advertisingInfo.getAdvertisingId()
}
Fetch the advertising id from background thread:
AsyncTask.execute(new Runnable() {
#Override
public void run() {
try {
AdvertisingIdClient.Info adInfo = AdvertisingIdClient.getAdvertisingIdInfo(mContext);
String adId = adInfo != null ? adInfo.getId() : null;
// Use the advertising id
} catch (IOException | GooglePlayServicesRepairableException | GooglePlayServicesNotAvailableException exception) {
// Error handling if needed
}
}
});
I added null checks to prevent any crashes. The Google example implementation code would crash with a NullPointerException if an exception occures.
With OS validation.
Call this in an AsyncTask
/** Retrieve the Android Advertising Id
*
* The device must be KitKat (4.4)+
* This method must be invoked from a background thread.
*
* */
public static synchronized String getAdId (Context context) {
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.KITKAT) {
return null;
}
AdvertisingIdClient.Info idInfo = null;
try {
idInfo = AdvertisingIdClient.getAdvertisingIdInfo(context);
} catch (GooglePlayServicesNotAvailableException e) {
e.printStackTrace();
} catch (GooglePlayServicesRepairableException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
String advertId = null;
try{
advertId = idInfo.getId();
}catch (NullPointerException e){
e.printStackTrace();
}
return advertId;
}
If you are using Kotlin use this to get the Google Advertising ID of the device
CoroutineScope(Dispatchers.IO).launch {
var idInfo: AdvertisingIdClient.Info? = null
try {
idInfo = AdvertisingIdClient.getAdvertisingIdInfo(applicationContext)
} catch (e: GooglePlayServicesNotAvailableException) {
e.printStackTrace()
} catch (e: GooglePlayServicesRepairableException) {
e.printStackTrace()
} catch (e: IOException) {
e.printStackTrace()
}
var advertId: String? = null
try {
advertId = idInfo!!.id
} catch (e: NullPointerException) {
e.printStackTrace()
}
Log.d(TAG, "onCreate:AD ID $advertId")
}
import com.google.android.gms.ads.identifier.AdvertisingIdClient.Info;
Info adInfo = null;
try {
adInfo = AdvertisingIdClient.getAdvertisingIdInfo(mContext);
} catch (IOException e) {
e.printStackTrace();
} catch (GooglePlayServicesAvailabilityException e) {
e.printStackTrace();
} catch (GooglePlayServicesNotAvailableException e) {
e.printStackTrace();
}
String AdId = adInfo.getId();
You need add gms libs otherwise you cannot get the advertising id. It can be reset by user or when you do a factory reset (at factory reset time the Android id also reset).
Make sure you have added play identity services, then you can get advertising id by running a thread like this:
Thread thread = new Thread() {
#Override
public void run() {
try {
AdvertisingIdClient.Info adInfo = AdvertisingIdClient.getAdvertisingIdInfo(getApplicationContext());
String advertisingId = adInfo != null ? adInfo.getId() : null;
} catch (IOException | GooglePlayServicesRepairableException | GooglePlayServicesNotAvailableException exception) {
exception.printStackTrace();
}
}
};
// call thread start for background process
thread.start();
You only need this package:
implementation("com.google.android.gms:play-services-ads-identifier:17.0.0")
It's not really listed anywhere but it's published on Mavne.
Get Google Services using
GoogleApiAvailabilityLight.getInstance
You need to run your code using Async Task
try this
Using the new Android Advertiser id inside an SDK
Using Kotlin & RxJava Observers
Import in your Gradle file
implementation 'com.google.android.gms:play-services-ads:15.0.0'
Import on top of your kotlin source file
import io.reactivex.Observable
import com.google.android.gms.ads.identifier.AdvertisingIdClient
Implement a helper function
private fun fetchAdIdAndThen(onNext : Consumer<String>, onError : Consumer<Throwable>) {
Observable.fromCallable(Callable<String> {
AdvertisingIdClient.getAdvertisingIdInfo(context).getId()
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(onNext, onError);
}
Then
fetchAdIdAndThen(Consumer<String>() {
adId ->
performMyTaskWithADID(activity, 10000, adId);
}, Consumer<Throwable>() {
throwable ->
throwable.printStackTrace();
performMyTaskWithADID(activity, 10000, "NoADID");
})

AsyncTask slow with OnClick

Goodmorning,
I have a button on my android app that launches a search on the web (through google endpoints) through an AsyncTask. My problem is that the button does not "unclick" until the AsyncTask is completed, which may take several seconds. When the internet connection is slow, this even makes the application crash, in any case the application is completely stuck until the AsyncTask is completed. Now the reason for using AsyncTask was exactly to eliminate this problem, so I don't really get what happens!
Here is the OnClickListener:
SearchListener = new OnClickListener() {
#Override
public void onClick(View v) {
String cname=TextCourse.getText().toString();
if (!cname.isEmpty()){
try {
CollectionResponseWine listavini= new QueryWinesTask(messageEndpoint,cname,5).execute().get();
} catch (InterruptedException e) {
showDialog("Errore ricerca");
e.printStackTrace();
} catch (ExecutionException e) {
showDialog("Errore ricerca");
e.printStackTrace();
}
} else{
showDialog("Inserisci un piatto");
}
}
};
and here is the AsyncTask that is being called:
private class QueryWinesTask
extends AsyncTask<Void, Void, CollectionResponseWine> {
Exception exceptionThrown = null;
MessageEndpoint messageEndpoint;
String cname;
Integer limit;
public QueryWinesTask(MessageEndpoint messageEndpoint, String cname, Integer limit) {
this.messageEndpoint = messageEndpoint;
this.cname=cname;
this.limit=limit;
}
#Override
protected CollectionResponseWine doInBackground(Void... params) {
try {
CollectionResponseWine wines = messageEndpoint.listwines().setCoursename(cname).setLimit(limit).execute();
return wines;
} catch (IOException e) {
exceptionThrown = e;
return null;
//Handle exception in PostExecute
}
}
protected void onPostExecute(CollectionResponseWine wines) {
// Check if exception was thrown
if (exceptionThrown != null) {
Log.e(RegisterActivity.class.getName(),
"Exception when listing Messages", exceptionThrown);
showDialog("Non ci sono vini associati al tuo piatto. Aggiungine uno!");
}
else {
messageView.setText("Vini piu' votati per " +
cname + ":\n\n");
for(Wine wine : wines.getItems()) {
messageView.append(wine.getName() + " (" + wine.getScore() + ")\n");
}
}
}
}
...execute().get() is blocking. It makes UI thread wait for Task to complete.
Don't do get(). Use onPostExecute() to get the result (wines) of task and update the UI.

Categories

Resources