I'm doing an android app and trying to integrate social login into the application using Azure Mobile Services.
public class SocialLogin extends Activity implements UserAuthenticationCallback {
#Override
protected void onCreate(Bundle savedInstanceState) {
// on create code
}
// All the code
#Override
public void onCompleted(MobileServiceUser user, Exception exception, ServiceFilterResponse response) {
if (exception == null) {
//Take user to the logged in view
cacheUserToken(user);
} else {
Log.e("SocialLogin", "User did not login successfully");
}
}
}
I'm getting two errors because of the onCompleted method.
Error:(176, 5) error: method does not override or implement a method from a supertype
Error:(37, 8) error: SocialLogin is not abstract and does not override abstract method onCompleted(MobileServiceUser,Exception,ServiceFilterResponse) in UserAuthenticationCallback
Edit: Fixed the problem by deleting away the .jar file in my lib.
Per my understanding, 'UserAuthenticationCallback' is not an interface since many of samples are coding like this:
MobileServiceClient mClient = new MobileServiceClient(
"MobileServiceUrl",
"AppKey",
this).withFilter(new ProgressFilter());
mClient.login(MobileServiceAuthenticationProvider.MicrosoftAccount,
new UserAuthenticationCallback() {
#Override
public void onCompleted(MobileServiceUser user,
Exception exception, ServiceFilterResponse response) {
synchronized(mAuthenticationLock)
{
if (exception == null) {
cacheUserToken(mClient.getCurrentUser());
} else {
createAndShowDialog(exception.getMessage(), "Login Error");
}
}
}
});
Since it is not an interface, we cannot implement it as you did. You can either create a class that inherits UserAuthenticationCallback (but the class cannot inherit Activity as we can only inherit one class), or simply create a new instance of UserAuthenticationCallback like the code in the sample.
Also, I'd like to suggest you to check https://azure.microsoft.com/en-us/documentation/articles/mobile-services-android-get-started-users/ and https://azure.microsoft.com/en-us/documentation/articles/mobile-services-android-get-started-data/ for a completed sample of how to add authentication to your Mobile Services Android app.
Related
I have an List called messages property in my Activity.In the synchronization(),I called getDateMessage(upadated_at) function.In this function value of messages has changed but when program go to synchronization messages list is empty.
private List<message_model> messages = new ArrayList<>();
private void synchronization() {
getDateMessage(upadated_at);
Log.e("MSDF",messages.toString()+" list tostring");
}
private void getDateMessage(String date) {
MessengerActivity.APIInterface apiInterface = app_net.getRetrofitInstance().create(MessengerActivity.APIInterface.class);
retrofit2.Call<List<message_model>> call = apiInterface.getMessageDate(Ptoken, date);
call.enqueue(new Callback<List<message_model>>() {
#Override
public void onResponse(Call<List<message_model>> call, Response<List<message_model>> response) {
if(response.isSuccessful()) {
messages.addAll(response.body());
Log.e("MSDF",response.body().toString()+" responsebody in call");
Log.e("MSDF",messages.toString()+" message in call");
Log.e("MESSAGE", "getDateMessage successful");
}
}
#Override
public void onFailure(Call<List<message_model>> call, Throwable t) {
Log.e("MESSAGE", "getDateMessage" + t.toString());
}
});
}
And This is my logcat.
09-30 14:34:53.714 10763-10763/idea.mahdi.bime E/MSDF: [] list tostring
09-30 14:34:54.104 10763-10763/idea.mahdi.bime E/MSDF: [message_model{id=33, thread_id=2, user_id=15, body='چطوری', created_at='2018-09-29 10:28:26', updated_at='2018-09-29 10:28:26', deleted_at='null'}, message_model{id=30, thread_id=2, user_id=15, body='سلام', created_at='2018-09-29 09:30:40', updated_at='2018-09-29 09:30:40', deleted_at='null'}, message_model{id=7, thread_id=2, user_id=15, body='hi', created_at='2018-09-24 09:55:46', updated_at='2018-09-24 09:55:46', deleted_at='null'}] responsebody in api
09-30 14:34:54.104 10763-10763/idea.mahdi.bime E/MSDF: [message_model{id=33, thread_id=2, user_id=15, body='چطوری', created_at='2018-09-29 10:28:26', updated_at='2018-09-29 10:28:26', deleted_at='null'}, message_model{id=30, thread_id=2, user_id=15, body='سلام', created_at='2018-09-29 09:30:40', updated_at='2018-09-29 09:30:40', deleted_at='null'}, message_model{id=7, thread_id=2, user_id=15, body='hi', created_at='2018-09-24 09:55:46', updated_at='2018-09-24 09:55:46', deleted_at='null'}] message in api
09-30 14:34:54.104 10763-10763/idea.mahdi.bime
E/MESSAGE: getDateMessage successful
The problem is that when you call getDataMessage() it performs an asynchronous call (the retrofit enqueue() method). The server will be called to get the messages in a backgroud thread, while the android application will keep in the main thread.
Therefore, Log.e("MSDF",messages.toString()+" list tostring"); is called before the retrofit call is made, hence, there is no current data available yet. You should make sure that you are doing something with the data after it is completed loaded.
private List<message_model> messages = new ArrayList<>();
private void synchronization() {
getDateMessage(upadated_at);
// Anything you put here will be called before the data (messages) is loaded.
// Do not work with your messages here, they'll be null.
}
private void getDateMessage(String date) {
MessengerActivity.APIInterface apiInterface = app_net.getRetrofitInstance().create(MessengerActivity.APIInterface.class);
retrofit2.Call<List<message_model>> call = apiInterface.getMessageDate(Ptoken, date);
call.enqueue(new Callback<List<message_model>>() {
#Override
public void onResponse(Call<List<message_model>> call, Response<List<message_model>> response) {
if(response.isSuccessful()) {
messages.addAll(response.body());
Log.e("MSDF",response.body().toString()+" responsebody in call");
Log.e("MSDF",messages.toString()+" message in call");
Log.e("MESSAGE", "getDateMessage successful");
// Anything you want to do with the messages should be placed here. When you are sure the data is completed.
Log.e("MSDF",messages.toString()+" list tostring");
}
}
#Override
public void onFailure(Call<List<message_model>> call, Throwable t) {
Log.e("MESSAGE", "getDateMessage" + t.toString());
}
});
}
It's worth checking if (response.body() != null) before doing something with it to avoid NPE.
EDIT
As it was asked in the comments. A good solution (Google recommends it) is to fetch the data using a view model as described in this android dev guide article.
ViewModel approach is good because:
The data persist during configuration changes (for example, if you rotate your device, your list of messages will be still in your app).
It does not cause memory leaks.
You separate view data ownership from UI controller logic.
You can see the other advantages in the article.
1 - Add the view model dependecies in your build.gradle(Module:app) file
dependencies {
def lifecycle_version = "1.1.1"
// ViewModel and LiveData
implementation "android.arch.lifecycle:extensions:$lifecycle_version"
}
See here the latest version.
2 - Create a ViewModel class
MessageViewModel.java
public class MessagesViewModel extends ViewModel {
private MutableLiveData<List<message_model>> messagesList;
public LiveData<List<message_model>> getMessages() {
if (messagesList == null) {
messagesList = new MutableLiveData<List<message_model>>();
loadMessages();
}
return messagesList;
}
private void loadMessages() {
MessengerActivity.APIInterface apiInterface = app_net.getRetrofitInstance().create(MessengerActivity.APIInterface.class);
retrofit2.Call<List<message_model>> call = apiInterface.getMessageDate(Ptoken, date);
call.enqueue(new Callback<List<message_model>>() {
#Override
public void onResponse(Call<List<message_model>> call, Response<List<message_model>> response) {
if(response.isSuccessful()) {
if (response.body() != null) {
messagesList.setValue(response.body());
}
}
}
#Override
public void onFailure(Call<List<message_model>> call, Throwable t) {
// Handle failure
}
});
}
}
3 - Get the messages in your activity
public class MainActivity extends AppCompatActivity {
public void onCreate(Bundle savedInstanceState) {
// Create a ViewModel the first time the system calls an activity's onCreate() method.
// Re-created activities receive the same MyViewModel instance created by the first activity.
MessagesViewModel model = ViewModelProviders.of(this).get(MessagesViewModel.class);
model.getMessages().observe(this, messagesList -> {
// Do whatever you want with the list of messages.
});
}
}
Look how clean your activity is now.
Then you can implement a SwipeRefreshLayout if you want to allow your users to refresh the data.
If it is not enough, you can check this ReposViewModel
Finally, if calling retrofit is the main core of your app that is going to be released to the public, you should introduce MVVM approach using Dagger 2 and RxJava, as described in this article. (This is advanced)
Recently I use MVP to develop an Android App.
But I find an Android Bug(maybe I am wrong)
I have two presenter NewsPresenter and MainPresenter. NewsPresenter is created an instance in a Fragment NewsFragment,and MainPresenter is created an instance in an Activity MainActivty.Of course MainActivity include NewsFragment.Both two presenter have two method to implements which to handle the success response and the fail response.
NewsPresenter
public class NewsPresenter extends IPresenter implements IAdapter.OnRecycleItemClickListener{
#Override
protected void onIRequestSuccess(int requestId, IResponse response) {
Log.e("TAG","onIRequestSuccess:"+requestId);
....
}
#Override
protected void onIRequestFail(int requestId, Throwable throwable) {
Log.e("TAG","onIRequestFail:"+requestId);
...
}
}
MainPresenter
public class MainPresenter extends IPresenter{
public MainPresenter(Context context, IMain iMain) {
super(context);
}
#Override
protected void onIRequestSuccess(int requestId, IResponse response) {
//do nothing
}
#Override
protected void onIRequestFail(int requestId, Throwable throwable) {
//do nothing
}
}
Now,in the NewsPresenter I try to make a network request.In the BasePresenter which is its super class I make a log to show the class which try to execute the network request.And the log is that:
01-02 20:09:28.281 17206-17206/com.chengtao.culture E/BasePresenter: class com.chengtao.culture.presenter.NewsPresenter
this mean NewsPresenter execute the request.
But in the IPresente which is NewsPresenter and MainPresenter super class,I try to make a log to show the class which handle the response.And the log is that:
01-02 20:09:38.352 17206-17206/com.chengtao.culture E/TAG: class com.chengtao.culture.presenter.MainPresenter
This mains that the MainPresenter handle the response.
IPresenter
abstract class IPresenter extends BasePresenter{
IPresenter(Context context) {
super(context);
}
#Override
public void onRequestSuccess(int requestId, BaseResponse response) {
Log.e("TAG",this.getClass().toString());
IResponse response1 = (IResponse) response;
Log.e("TAG","onRequestSuccess");
onIRequestSuccess(requestId,response1);
}
#Override
public void onRequestFail(int requestId, Throwable throwable) {
Log.e("TAG",this.getClass().toString());
if (throwable == null || throwable.getMessage() == null){
throwable = new Throwable("请求超时");
onIRequestFail(requestId,throwable);
}else {
onIRequestFail(requestId,throwable);
}
}
protected abstract void onIRequestSuccess(int requestId, IResponse response);
protected abstract void onIRequestFail(int requestId, Throwable throwable);
}
I am so confused why I use NewsPresenter to make the request,but MainPresenter handle the response?It's not scientific,because the log show that the request is NewsPresenter execute,MainPresenter has no relationship with NewsPresenter just both of them extends IPresenter.
But once I delete the instance of MainPresenter in the Activity,the response will be handled by the NewsPresenter.
To see the whole code: https://github.com/ParadiseHell/cultural-creative/tree/master/app/Culture
I make sure my code is all right,So I don't know is Android bug or it's Java bug.If someone knows,please tell me, thanks.
Firstly your Mvp architecture is wrong. List and Adapter are related to UI, so adapter logic must be with fragment not with the presenter.
You should create something other called "Service Class" which will extend the BaseService in which the real API call is sent.
Every API call must have each separate Service Class.We should set the callback method to that serviceclass object so that when the API call gets executed the callback is received for that particular function.
Sample code which explains the above paragraph.
class GetNewsService extends BaseService {
void doApiCall(){
// execute API call . Put the request related code in BaseService.
}
}
class NewsPresenter {
// I am writing psudeo code only.
void getNews(){
GetNewsService newsService=new GetNewsService();
newsService.setCallBack(new RequestClass(){
#Override
onSuccessMethod(Response response){
// send response object to view class through interface and update adapter there
}
#Override
onFailMethod(Error error){}
});
newsService.doApiCall();
}
}
First I have to say,I use MVP right,just because my library has a bug,and I have fixed it.
In the library,there is a class AsyncHttpClient which is singleton pattern,of course it's wrong,because I can init only one response interface in the whole project,but every presenter has a response interface,so it's bad for handling the response.So I delete singleton pattern,use a public constructor,and the problem disappears.
So it's not Android bug or Java bug,just my fault for thinking less.
I'm trying to implement a Google Fit Listener when data is updated into Google Fit services.
In this link of Google Fit documentation there is a simple example, however, it is not 100% clear. For that reason, I have two problems:
I don't know how to implement mResultCallback variable (there aren't any examples in this documentation).
When I define a simple ResultCallback (it seems to work but I'm not sure) and I launch the application, it gives me a result error code: java.lang.SecurityException: Signature check failed
The code within the HistortyApi lists one of android.permission.ACCESS_FINE_LOCATION or android.permission.BODY_SENSORS as being required.
Adding those permissions to my code hasn't resolved the same problem though.
Confirmed bug in Google Fit services. See discussion in https://plus.google.com/110141422948118561903/posts/Lqri4LVR7cD
mResultCallback is a ResultCallback<Status> so you need to implement a class of that type. Documentation is here, but there's only one method you need to implement:
public abstract void onResult (Status result)
The standard way is to do this using an anonymous class either when you declare mResultCallback or when you're using it as a parameter. Below is an example from Google's BasicRecordingAPI example:
Fitness.RecordingApi.subscribe(mClient, DataType.TYPE_ACTIVITY_SAMPLE)
.setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
if (status.isSuccess()) {
if (status.getStatusCode()
== FitnessStatusCodes.SUCCESS_ALREADY_SUBSCRIBED) {
Log.i(TAG, "Existing subscription for activity detected.");
} else {
Log.i(TAG, "Successfully subscribed!");
}
} else {
Log.i(TAG, "There was a problem subscribing.");
}
}
});
If you want to use a member variable you can simply make an assignment instead:
ResultCallback<Status> mResultCallback = new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
...
}
});
Of course you can define a non-anonymous class, but if you did that for every callback you had you would end up creating a LOT of classes.
I want to use the BluetoothA2DPSink service in android,
it's a hidden class but I built a modified SDK and ROM and now Android studio can see it.
The problem is I can't use it, whenever i try
'BluetoothA2DPSink sink = new BluetoothA2DPSink()'
I get this error: "BluetoothA2DPSink() is not public in 'android.bluetooth.BluetoothA2dpSink'. Connot be accesed from outside package".
I verified it and it is in fact public:
"public final class BluetoothA2dpSink implements BluetoothProfile{..."
How can I use its methods?
Any help would be much appreciated.
If you pasted your error message correctly, the problem is not with the class, but with the constructor. Note the parentheses in "BluetoothA2DPSink() is not public in 'android.bluetooth.BluetoothA2dpSink'. Connot be accesed from outside package" — that is a reference to a constructor, not a class. Make sure the zero-argument constructor is public.
Try the below code. It is done using reflection. You can not simply create an object by calling the constructor for BluetoothA2DPSink. You also need to use another class BluetoothProfile.java.
Object mBluetoothA2DPSink;
/**
* This function will connect to A2DPsink profile of the server device to manage audio profile connection
*/
public void getBluetoothA2DPsink() {
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
try {
final int A2DPprofile = BluetoothProfile.class.getField("A2DP_SINK").getInt(null);
BluetoothProfile.ServiceListener mProfileListener1 = new BluetoothProfile.ServiceListener() {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
if (profile == A2DPprofile) {
mBluetoothA2DPSink = proxy;
}
}
public void onServiceDisconnected(int profile) {
if (profile == A2DPprofile) {
mBluetoothA2DPSink = null;
try {
mContext.unregisterReceiver(mA2DPReciever);
} catch (IllegalArgumentException e) {
Log.e(TAG, e.getMessage());
}
}
}
};
// Establish connection to the proxy.
mBluetoothAdapter.getProfileProxy(mContext, mProfileListener1, A2DPprofile);
} catch (NoSuchFieldException | IllegalAccessException e) {
Log.e(TAG, e.getMessage());
}
}
Does someone knows if it is possible to add push notifications(like Amazon Simple Notification Service) in an Android and iOS with RoboVM libGDX projects? And if it is possible, are there any good tutorials or good hints how to implement such things?
I would be happy about every hint how I can implement it.
Hi I know this is an old question but I was struggling to find a solution for this specially for iOS, but I finally found a way. If the explanation below is confusing and you prefer to see an example here is a github repo with a sample project:
Repo GitHub
I only show the code for iOS see the repo for Android.
The idea is simple you need to create a class that handles sending a notification for each platform on each of your projects (Android and iOS) and have it implement an interface called NotificationsHandler.
NotificationsHandler:
public interface NotificationsHandler {
public void showNotification(String title, String text);
}
iOS Adapter:
public class AdapteriOS implements NotificationsHandler {
public AdapteriOS () {
//Registers notifications, it will ask user if ok to receive notifications from this app, if user selects no then no notifications will be received
UIApplication.getSharedApplication().registerUserNotificationSettings(UIUserNotificationSettings.create(UIUserNotificationType.Alert, null));
UIApplication.getSharedApplication().registerUserNotificationSettings(UIUserNotificationSettings.create(UIUserNotificationType.Sound, null));
UIApplication.getSharedApplication().registerUserNotificationSettings(UIUserNotificationSettings.create(UIUserNotificationType.Badge, null));
//Removes notifications indicator in app icon, you can do this in a different way
UIApplication.getSharedApplication().setApplicationIconBadgeNumber(0);
UIApplication.getSharedApplication().cancelAllLocalNotifications();
}
#Override
public void showNotification(final String title, final String text) {
NSOperationQueue.getMainQueue().addOperation(new Runnable() {
#Override
public void run() {
NSDate date = new NSDate();
//5 seconds from now
NSDate secondsMore = date.newDateByAddingTimeInterval(5);
UILocalNotification localNotification = new UILocalNotification();
localNotification.setFireDate(secondsMore);
localNotification.setAlertBody(title);
localNotification.setAlertAction(text);
localNotification.setTimeZone(NSTimeZone.getDefaultTimeZone());
localNotification.setApplicationIconBadgeNumber(UIApplication.getSharedApplication().getApplicationIconBadgeNumber() + 1);
UIApplication.getSharedApplication().scheduleLocalNotification(localNotification);
}
});
}
}
Now by default Libgdx passes your ApplicationListener or Game object to AndroidLauncher and IOSLauncher along with a configuration object. The trick is to pass the class we created earlier to the ApplicationListener so that you can use it inside your Core project. Simple enough:
public class IOSLauncher extends IOSApplication.Delegate {
#Override
protected IOSApplication createApplication() {
IOSApplicationConfiguration config = new IOSApplicationConfiguration();
// This is your ApplicationListener or Game class
// it will be called differently depending on what you
// set up when you created the libgdx project
MainGame game = new MainGame();
// We instantiate the iOS Adapter
AdapteriOS adapter = new AdapteriOS();
// We set the handler, you must create this method in your class
game.setNotificationHandler(adapter);
return new IOSApplication(game, config);
}
public static void main(String[] argv) {
NSAutoreleasePool pool = new NSAutoreleasePool();
UIApplication.main(argv, null, IOSLauncher.class);
pool.close();
}
}
Now that you have a reference to the implementation of NotificationHandler you can simply call it through your Core project.
public class MainGame extends Game {
// This is the notificatino handler
public NotificationHandler notificationHandler;
#Override
public void create () {
// Do whatever you do when your game is created
// ...
}
#Override
public void render () {
super.render();
// This is just an example but you
// can now send notifications in your project
if(condition)
notificationHandler.showNotification("Title", "Content");
}
#Override
public void dispose() {
super.dispose();
}
// This is the method we created to set the notifications handler
public void setNotificationHandler(NotificationHandler handler) {
this.notificationHandler = handler;
}
}
One last thing
If you need to run the Desktop version then you will need to do the same thing for Desktop otherwise you might get errors, it will not do anything on the Desktop, or you can check the platform before calling the method showNotfication. You can clone the repo where I do this:
Repo GitHub
I've never done it myself. But you can use this tutorial to find out how to write Android specific code in your libGDX project. Your Android code could then receive the notifications and trigger a callback in libGDX. I hope this is at least a step in the right direction.
However I' not sure about doing the same for iOS.