I am developing an application that must read a confirmation code by SMS exactly as on registration on Whatsapp. It works well for Android versions 5 and below, but from version 6 the application does not read the sms.
Below is the class called in the main function. It reads received SMS messages automatically:
public class SmsReceiver extends BroadcastReceiver {
private static SmsListener mListener;
//add...
private static final String
TAG = SmsReceiver.class.getSimpleName();
public static final String pdu_type = "pdus";
//add..
#TargetApi(Build.VERSION_CODES.M)
#Override
public void onReceive(Context context, Intent intent) {
Bundle data = intent.getExtras();
Object[] pdus = (Object[]) data.get("pdus");
String format = data.getString("format");
//Toast.makeText(context,"coollll:" + pdus,Toast.LENGTH_LONG).show();
if (pdus!=null){
//
Toast.makeText(context,"noooooooo",Toast.LENGTH_LONG).show();
boolean isVersionM= (Build.VERSION.SDK_INT >=
Build.VERSION_CODES.M);
for (int i=0; i<pdus.length; i++){
if (isVersionM){
SmsMessage smsMessage =
SmsMessage.createFromPdu((byte[]) pdus[i],format);
String sender = smsMessage.getDisplayOriginatingAddress();
if(sender.equals("myProjet")){
String messageBody = smsMessage.getMessageBody();
mListener.messageReceived(messageBody);
}
}else {
SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) pdus[i]);
String sender = smsMessage.getDisplayOriginatingAddress();
if(sender.equals("projet")){
String messageBody = smsMessage.getMessageBody();
mListener.messageReceived(messageBody);
}
}
}
}
}
public static void bindListerner(SmsListener listener){
mListener = listener;
}
}
Below is the SmsListener.java interface which listens for incoming messages:
public interface SmsListener {
public void messageReceived(String messageText);
}
And below is the activity that processes the received SMS:
public class CodeConfirmation extends Activity {
private String telephone;
private TextView tel, textcode, textCount, textSendAgainSms;
private RequestQueue requestQueue;
private StringRequest stringRequest;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_code_confirmation);
final Pinview pin = (Pinview) findViewById(R.id.pinview);
pin.setPinBackgroundRes(R.drawable.sample_background);
countTime();
requestQueue= Volley.newRequestQueue(this);
Intent intent= getIntent();
final String codeGenere=
getIntent().getExtras().getString("code");
telephone= getIntent().getExtras().getString("telephone");
Toast.makeText(CodeConfirmation.this, codeGenere,
Toast.LENGTH_SHORT).show();
// on affiche le numéro de l'utilisateur dans la vue
tel =(TextView)findViewById(R.id.my_number);
textcode=(TextView)findViewById(R.id.text);
tel.setText(getString(R.string.your_tel)+ telephone);
textcode.setText(getString(R.string.code_confirmation));
textCount=(TextView)findViewById(R.id.textCount);
textSendAgainSms=(TextView)findViewById(R.id.send_code_agent);
textSendAgainSms.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
textSendAgainSms.setText(null);
countTime();
}
});
SmsReceiver.bindListerner(new SmsListener() {
#Override
public void messageReceived(String messageText) {
Toast.makeText(CodeConfirmation.this,"Message:" + messageText,Toast.LENGTH_LONG).show();
if (messageText.compareToIgnoreCase(codeGenere)==0){
pin.setValue(messageText);
Toast.makeText(CodeConfirmation.this, getString(R.string.succes_code), Toast.LENGTH_SHORT).show();
finish();
startActivity(new Intent(getApplicationContext(), LoginActivity.class));
}
}
});
/*
*Lorsque l'utilisateur entre le code à 5 chiffres
*/
pin.setPinViewEventListener(new
Pinview.PinViewEventListener() {
#Override
public void onDataEntered(Pinview pinview, boolean b) {
final String code= pinview.getValue();
//Toast.makeText(CodeConfirmation.this, code, Toast.LENGTH_SHORT).show();
if (code.compareToIgnoreCase(codeGenere)==0){
Toast.makeText(CodeConfirmation.this,getString(R.string.succes_code), Toast.LENGTH_SHORT).show();
finish();
startActivity(new Intent(getApplicationContext(),LoginActivity.class));
}
else{
Toast.makeText(CodeConfirmation.this,getString(R.string.wrong_code), Toast.LENGTH_SHORT).show();
}
}
});
}
public void countTime(){
new CountDownTimer(30000, 1000) {
#Override
public void onTick(long millisUntilFinished) {
textCount.setText(getString(R.string.TimeCount)+":"+millisUntilFinished/1000);
}
#Override
public void onFinish() {
textSendAgainSms.setText(getString(R.string.send_code_agent));
}
}.start();
}
public void CheckNumber(final String telephone){
stringRequest= new StringRequest(Request.Method.POST, BuildConfig.server + "register", new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jsonObject = new JSONObject(response);
String objetJson= jsonObject.getString("success");
//Toast.makeText(getApplicationContext(),"response-> : "+jsonObject.getString("success"), Toast.LENGTH_SHORT).show();
if(objetJson.equals("true")){
/*Toast.makeText(getApplicationContext(), "code-> "+jsonObject.getString("code"), Toast.LENGTH_LONG).show();
Toast.makeText(getApplicationContext(), "telephone-> "+jsonObject.getString("telephone"), Toast.LENGTH_LONG).show();*/
//startActivity(new Intent(getApplicationContext(),CodeConfirmation.class));
}
else if(objetJson.equals("false")){
Toast.makeText(getApplicationContext(),"error", Toast.LENGTH_SHORT).show();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getApplicationContext(),"Aucune connexion internet " ,Toast.LENGTH_SHORT).show();
}
}){
#Override
protected Map<String, String> getParams() throws AuthFailureError {
HashMap<String, String> hashMap = new HashMap<String, String>();
hashMap.put("telephone", telephone);
return hashMap;
}
};
requestQueue.add(stringRequest);
}
}
This is what my AndroidManifest.xml file looks like:
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission
android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission
android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.SEND_SMS"/>
<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">
<activity
android:name=".connexion.LoginActivity"
android:label="#string/title_activity_login"
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=".connexion.CodeConfirmation"
android:label="#string/title_activity_code_confirmation" />
<receiver
android:name=".sms.SmsReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action
android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
</application>
</manifest>
in the new android api, you need of course permission on Manifest, but you need implement runtime permissions, maybe you can put it in your first Activity.
Look this link
Examples to do runtime permission
Related
I am building an android firebase chat app that doesn't require a server setup, I've already built everything for it and found a couple of YouTube tutorials on how to do what I'm having trouble with right now, I'm trying to get the app itself to send a push notification to the device its sending the message to, I'm using Volley to send the notification, the problem that I'm facing is the other device is not getting or showing the notification, can you please tell me what I'm doing wrong and how to fix it?
build.gradle
implementation 'com.google.firebase:firebase-auth:20.0.4'
implementation 'com.google.firebase:firebase-database:19.7.0'
implementation platform('com.google.firebase:firebase-bom:27.0.0')
implementation 'com.google.firebase:firebase-analytics'
implementation 'com.google.firebase:firebase-messaging:20.0.1'
implementation 'com.android.volley:volley:1.1.1'
AndroidManifest
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
...
<service
android:name=".MyFirebaseMessagingService"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
<service
android:name=".MyFirebaseInstanceIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
MyFirebaseInstanceIDService
public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
private static final String TAG = "mFirebaseIIDService";
#Override
public void onTokenRefresh() {
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
final String token = FirebaseInstanceId.getInstance().getToken();
FirebaseInstallations.getInstance().getToken(false)
.addOnCompleteListener(new OnCompleteListener<InstallationTokenResult>() {
#Override
public void onComplete(#NonNull Task<InstallationTokenResult> task) {
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
FirebaseMessaging.getInstance().subscribeToTopic(user.getUid());
Log.i("TAG", "onTokenRefresh completed with token: " + task.getResult().getToken());
}
});
}
}
MyFirebaseMessagingService
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private final String ADMIN_CHANNEL_ID = "admin_channel";
#Override
public void onMessageReceived(#NonNull RemoteMessage remoteMessage) {
final Intent intent = new Intent(this, MainActivity.class);
NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
int notificationID = new Random().nextInt(85-65);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
setupChannels(notificationManager);
}
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this , 0, intent,
PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, ADMIN_CHANNEL_ID)
.setContentTitle(remoteMessage.getData().get("title"))
.setContentText(remoteMessage.getData().get("message"))
.setAutoCancel(true)
.setSound(notificationSoundUri)
.setContentIntent(pendingIntent);
notificationManager.notify(notificationID, notificationBuilder.build());
}
#RequiresApi(api = Build.VERSION_CODES.O)
private void setupChannels(NotificationManager notificationManager){
CharSequence adminChannelName = "New notification";
String adminChannelDescription = "Device to device notification";
NotificationChannel adminChannel;
adminChannel = new NotificationChannel(ADMIN_CHANNEL_ID, adminChannelName, NotificationManager.IMPORTANCE_HIGH);
adminChannel.setDescription(adminChannelDescription);
adminChannel.enableLights(true);
adminChannel.setLightColor(Color.RED);
adminChannel.enableVibration(true);
if (notificationManager != null) {
notificationManager.createNotificationChannel(adminChannel);
}
}
}
MessageActivity
final private String FCM_API = "https://fcm.googleapis.com/fcm/send";
final private String serverKey = "key=MY_KEY";
final private String contentType = "application/json";
final String TAG = "NOTIFICATION TAG";
...
sendBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String msg = msg_editText.getText().toString();
if (!msg.equals("")) {
sendMessage(fuser.getUid(), userid, msg);
JSONObject notification = getStructure(fuser.getUid(), userid, msg);
sendNotification(notification);
}
msg_editText.setText("");
}
});
...
private JSONObject getStructure(String senderId, String receiverId, String msg) {
JSONObject notification = new JSONObject();
JSONObject notificationBody = new JSONObject();
try {
notificationBody.put("title", "App Test");
notificationBody.put("message", "This is a test notification from the app");
notification.put("to", "/topics/" + receiverId);
notification.put("data", notificationBody);
} catch (JSONException e) {
e.printStackTrace();
}
return notification;
}
...
private void sendNotification(JSONObject notification) {
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(FCM_API, notification,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.i(TAG, "onResponse: " + response.toString());
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(MessageActivity.this, "Request error", Toast.LENGTH_SHORT).show();
Log.i(TAG, "onErrorResponse: Didn't work");
}
}) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("Authorization", serverKey);
params.put("Content-Type", contentType);
return params;
}
};
MySingleton.getInstance(getApplicationContext()).addToRequestQueue(jsonObjectRequest);
}
MySingleton
public class MySingleton {
private static MySingleton instance;
private RequestQueue requestQueue;
private Context ctx;
public MySingleton(Context ctx) {
this.ctx = ctx;
requestQueue = getRequestQueue();
}
public static synchronized MySingleton getInstance(Context context) {
if (instance == null) {
instance = new MySingleton(context);
}
return instance;
}
public RequestQueue getRequestQueue() {
if (requestQueue == null) {
requestQueue = Volley.newRequestQueue(ctx.getApplicationContext());
}
return requestQueue;
}
public <T> void addToRequestQueue(Request<T> req) {
getRequestQueue().add(req);
}
}
When I update the app to a new version, the service that was installed with the previous app version is still running. When I update the app the second time, the updated service is running properly.
However, after first update, whenever i close the app or restart the phone the service from the previous version is running.
How can i force the new service to run as soon as the app is updated.
Here is my code
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.djuro.updateservicewithappupdate">
<application
android:name=".App"
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">
<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=".MyService"
android:process=":myService" />
<receiver android:name=".PackageReplacedReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<data android:scheme="package" android:path="com.djuro.updateservicewithappupdate"/>
</intent-filter>
</receiver>
</application>
</manifest>
App.java
public class App extends Application {
private static final String TAG = App.class.getName();
private static App mInstance;
private Messenger myServiceMessenger;
private boolean isBound;
private Messenger replyMessenger = new Messenger(new IncomingHandler());
#Override
public void onCreate() {
super.onCreate();
if (mInstance == null) {
mInstance = this;
startMyService();
}
isBound = false;
// start the chore service (if it is not running) and bind to it
}
public void startMyService() {
startService(new Intent(mInstance, MyService.class));
doBindService();
}
public void stopMyService() {
doUnBindService(true);
stopService(new Intent(mInstance, MyService.class));
}
public static App getInstance() {
return mInstance;
}
public static Context getContext() {
return mInstance.getApplicationContext();
}
public static Messenger getChoreMessenger() {return mInstance.myServiceMessenger;}
#Override
public void onTerminate() {
doUnBindService(false);
super.onTerminate();
}
private void doBindService() {
if (!isBound) {
Log.d(TAG, "Binding ChoreService.");
bindService(new Intent(this, MyService.class), myServiceConnection, Context.BIND_AUTO_CREATE);
isBound = true;
}
}
private void doUnBindService(boolean restartService) {
if (isBound) {
Log.d(TAG, "Unbinding ChoreService.");
if (myServiceMessenger != null) {
try {
Message msg = Message.obtain(null, MyService.UNREGISTER_CLIENT);
msg.replyTo = replyMessenger;
replyMessenger.send(msg);
}
catch (RemoteException e) {
// There is nothing special we need to do if the service has crashed.
}
}
if (restartService) {
try {
Message msg = Message.obtain(null, MyService.STOP_SERVICE_ON_UNBIND);
msg.replyTo = replyMessenger;
replyMessenger.send(msg);
}
catch (RemoteException e) {
// There is nothing special we need to do if the service has crashed.
}
}
unbindService(myServiceConnection);
isBound = false;
} else if (restartService) {
stopService(new Intent(mInstance, MyService.class));
}
}
private ServiceConnection myServiceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
myServiceMessenger = new Messenger(service);
Log.d(TAG, "connected to service");
try {
Message msg = Message.obtain(null, MyService.REGISTER_CLIENT);
msg.replyTo = replyMessenger;
myServiceMessenger.send(msg);
}
catch (RemoteException e) {
// In this case the service has crashed before we could even do anything with it
}
}
public void onServiceDisconnected(ComponentName className) {
myServiceMessenger = null;
Log.d(TAG, "disconnected from ChoreService");
}
};
class IncomingHandler extends Handler {
#Override
public void handleMessage(Message msg) {
}
}
}
MyService.java
public class MyService extends Service {
private static final String TAG = MyService.class.getName();
public static final int UNREGISTER_CLIENT = 1;
public static final int REGISTER_CLIENT = 2;
public static final int STOP_SERVICE_ON_UNBIND = 3;
final Messenger messenger = new Messenger(new IncomingHandler());
private String appVersion;
private boolean stopOnUnbind;
private int boundCount = 0;
// called when the intent starts the Service
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//return super.onStartCommand(intent, flags, startId);
Log.d(TAG, "onStartCommand()");
getVersion();
return START_STICKY;
}
// called once at creation (before onStartCommand)
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate");
}
// used to bind intent to service
#Nullable
#Override
public IBinder onBind(Intent intent) {
//doStopForeground();
boundCount ++;
Log.d(TAG, "bound count: " + boundCount);
return messenger.getBinder();
}
#Override
public boolean onUnbind(Intent intent) {
boundCount --;
Log.d(TAG, "bound count: " + boundCount);
boolean result = super.onUnbind(intent);
if (stopOnUnbind) {
Log.d(TAG, "stopSelf()");
stopSelf();
}
return result;
}
// called when the service is destroyed
#Override
public void onDestroy() {
Log.d(TAG, "onDestroy()");
super.onDestroy();
}
public void getVersion() {
try {
PackageInfo pInfo = this.getPackageManager().getPackageInfo(getPackageName(), 0);
appVersion = pInfo.versionName;
Log.d(TAG, "appVersion: " + appVersion);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
private class IncomingHandler extends Handler {
#Override
public void handleMessage(Message msg) {
Log.d(TAG, "IncomingHandler handling message. msg.what= " + msg.what);
switch (msg.what) {
case STOP_SERVICE_ON_UNBIND:
stopOnUnbind = true;
break;
default:
super.handleMessage(msg);
break;
}
}
}
}
PackageReplacedReceiver.java
public class PackageReplacedReceiver extends BroadcastReceiver {
private static final String TAG = PackageReplacedReceiver.class.getName();
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "package updated");
App.getInstance().stopMyService();
}
}
Use android.intent.action.MY_PACKAGE_REPLACED action in your intent filer and stop your service from broadcast receiver.
<receiver android:name=".PackageReplacedReceiver" android:enabled="#bool/is_at_least_api_12" > <intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
</intent-filter>
</receiver>
I'm trying to run bluetooth beacon scanner as a service, so when the application is not active, when beacon is detected, a notification can.
The Service Code (Java) :
public class BtService extends Service {
public static final String TAG = BtService.class.getSimpleName();
private ScanCallback mScanCallback;
private BluetoothAdapter btAdapter;
private BluetoothLeScanner btScanner;
private boolean mIsScanning = false;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "OnCreate Service");
final BluetoothManager btManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
btAdapter = btManager.getAdapter();
initBtCallBack();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "OnStartCommand Service");
btStartScanning();
return Service.START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "Destroy");
btStopScanning();
}
/**
* BlueTooth CallBack
*/
private void initBtCallBack() {
Log.d(TAG, "InitBtCallBack");
try {
btScanner = btAdapter.getBluetoothLeScanner();
} catch (Exception e) {
e.printStackTrace();
}
mScanCallback = new ScanCallback() {
#Override
public void onScanResult(int callbackType, ScanResult result) {
Log.i(TAG, "Something found : " + result.getDevice().getAddress());
BluetoothDevice device = result.getDevice();
Log.i(TAG, "btDevice : " + device.toString());
Log.i(TAG, "result : " + result.toString());
btUseBeacon(result);
}
};
}
private void btStartScanning() {
if (btScanner != null) {
if(! mIsScanning) {
Log.i(TAG, "START scanning...");
myBeacons.clear();
loadMyBeaconList();
mIsScanning = true;
btScanner.startScan(mScanCallback);
}
} else {
Log.i(TAG, "CANNOT START Scanning");
}
}
private void btStopScanning() {
if(mIsScanning) {
Log.i(TAG, "STOP scanning");
mIsScanning = false;
btScanner.stopScan(mScanCallback);
saveMyBeaconList();
}
}
}
There also a BroadcastReceiver Class to start the Service
public class BtStartServiceReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent service = new Intent(context, BtService.class);
context.startService(service);
}
}
Déclaration in the Manifest.xml, between the . Permission for Boot_Completed as also been added.
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<service
android:name=".BtService"
android:icon="#mipmap/ic_launcher"
android:enabled="true">
</service>
<receiver android:name=".BtStartServiceReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
When the application is active or not, seems it does not work. In the logcat, I don't see any of the LOG i added in the code of the service.
When I kill the application, the logcat shows that the application is restarting, but nothing about Logs in code.
When I try to run this code adapted for an Activity, It works, beacon are detected and can make notification.
I don't wan't to use any beacon library or SDK, as I work with generic beacon.
Thank's for your help.
I did login with facebook in the Activity
private CallbackManager callbackManager;
private LoginButton loginFBButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(LAYOUT);
callbackManager = CallbackManager.Factory.create();
loginFBButton = (LoginButton) findViewById(R.id.loginFBButton);
loginFBButton.setReadPermissions(Arrays.asList("email", "public_profile"));
loginFBButton.registerCallback(callbackManager, new FacebookCallback<LoginResult>() {
#Override
public void onSuccess(LoginResult loginResult) {
final String accessToken = loginResult.getAccessToken().getToken();
LogTag.v("onSuccess - getToken - " + accessToken);
GraphRequest request = GraphRequest.newMeRequest(
loginResult.getAccessToken(),
new GraphRequest.GraphJSONObjectCallback() {
#Override
public void onCompleted(JSONObject object, GraphResponse response) {
LogTag.v("onSuccess - " + response.toString());
// Application code
try {
String email = object.getString("email");
LogTag.v("email - " + email);
String name = object.getString("name");
LogTag.v("name - " + name);
saveUserData(name, email, accessToken);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
Bundle parameters = new Bundle();
parameters.putString("fields", "id,name,email,gender,birthday");
request.setParameters(parameters);
request.executeAsync();
}
#Override
public void onCancel() {
LogTag.v("onCancel");
}
#Override
public void onError(FacebookException error) {
LogTag.v("onError - " + error.getMessage());
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
callbackManager.onActivityResult(requestCode, resultCode, data);
}
in gradle
dependencies { compile 'com.facebook.android:facebook-android-sdk:4.11.0' }
in AndroidManifest
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<application
android:name=".application.MyApp"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<meta-data
android:name="com.facebook.sdk.ApplicationId"
android:value="#string/facebook_app_id" />
<activity
android:name=".activity.ActivitySignIn"
android:label="#string/app_name"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.facebook.FacebookActivity"
android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
android:label="#string/app_name"
android:theme="#android:style/Theme.Translucent.NoTitleBar" />
</application>
in MyApp
public class MyApp extends Application {
#Override
public void onCreate() {
super.onCreate();
FacebookSdk.sdkInitialize(getApplicationContext());
} }
but it does not always work on 4.4.2 - OK, in the phone (5.1) on one normal and the other hangs after login with a progress bar under which there is a notice of confirmation of access to personal data, and then triggers onCancel
On your phone, which it might be a bug in the log shows a link to the message:
{ "error": {
"message": "An access token is required to request this resource.",
"type": "OAuthException",
"code": 104,
"fbtrace_id": "AV/53FbmMya" } }
What is the problem? How to solve it?
Try this code i use in fragment.
FacebookSdk.sdkInitialize(getActivity());
callbackManager = CallbackManager.Factory.create();
LoginManager.getInstance().registerCallback(callbackManager,
new FacebookCallback<LoginResult>() {
#Override
public void onSuccess(LoginResult loginResult) {
// App code
accessToken = loginResult.getAccessToken()
.getToken();
Log.i("accessToken", accessToken);
}
#Override
public void onCancel() {
// App code
Toast.makeText(getActivity(), "on Cancel", Toast.LENGTH_SHORT).show();
}
#Override
public void onError(FacebookException exception) {
// App code
Toast.makeText(getActivity(), "on Error", Toast.LENGTH_SHORT).show();
IRoidAppHelper.Log("FacebokkError", exception.toString());
}
});`
Im trying to add notifications to my android app. So I decided to implement GCM.
I have used the sample code from the official documentation
https://developer.android.com/google/gcm/client.html
and the sample application
https://code.google.com/p/gcm/source/browse/samples/gcm-demo-client/src/com/google/android/gcm/demo/app/
Here is my implementation
public class RegisterActivity extends Activity implements SurfaceHolder.Callback{
public static final String PROPERTY_REG_ID = "registration_id";
private static final String PROPERTY_APP_VERSION = "appVersion";
private static final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
String SENDER_ID = "210822831159";
GoogleCloudMessaging gcm;
AtomicInteger msgId = new AtomicInteger();
Context context;
String regid;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
context = getApplicationContext();
if (checkPlayServices())
{
gcm = GoogleCloudMessaging.getInstance(this);
regid = getRegistrationId(context);
if (regid.isEmpty())
{
registerInBackground();
}
else
{
//"No valid Google Play Services APK found."
}
}
//...
}
#Override
protected void onResume() {
super.onResume();
// Check device for Play Services APK.
checkPlayServices();
}
private boolean checkPlayServices() {
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
GooglePlayServicesUtil.getErrorDialog(resultCode, this,
PLAY_SERVICES_RESOLUTION_REQUEST).show();
} else {
finish();
}
return false;
}
return true;
}
private void storeRegistrationId(Context context, String regId) {
final SharedPreferences prefs = getGcmPreferences(context);
int appVersion = getAppVersion(context);
SharedPreferences.Editor editor = prefs.edit();
editor.putString(PROPERTY_REG_ID, regId);
editor.putInt(PROPERTY_APP_VERSION, appVersion);
editor.commit();
}
private String getRegistrationId(Context context) {
final SharedPreferences prefs = getGcmPreferences(context);
String registrationId = prefs.getString(PROPERTY_REG_ID, "");
if (registrationId.isEmpty()) {
return "";
}
int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);
int currentVersion = getAppVersion(context);
if (registeredVersion != currentVersion) {
return "";
}
return registrationId;
}
private void registerInBackground() {
new AsyncTask<Void, Void, String>() {
#Override
protected String doInBackground(Void... params) {
String msg = "";
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(context);
}
regid = gcm.register(SENDER_ID);
msg = "Device registered, registration ID=" + regid;
sendRegistrationIdToBackend();
storeRegistrationId(context, regid);
} catch (IOException ex) {
msg = "Error :" + ex.getMessage();
}
return msg;
}
#Override
protected void onPostExecute(String msg) {
//...
}
}.execute(null, null, null);
}
private static int getAppVersion(Context context) {
try {
PackageInfo packageInfo = context.getPackageManager()
.getPackageInfo(context.getPackageName(), 0);
return packageInfo.versionCode;
} catch (PackageManager.NameNotFoundException e) {
// should never happen
throw new RuntimeException("Could not get package name: " + e);
}
}
private SharedPreferences getGcmPreferences(Context context) {
return getSharedPreferences(RegisterActivity.class.getSimpleName(),
Context.MODE_PRIVATE);
}
private void sendRegistrationIdToBackend() {
// TODO
}
//...
}
The Broadcaster:
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Explicitly specify that GcmIntentService will handle the intent.
ComponentName comp = new ComponentName(context.getPackageName(),
GcmIntentService.class.getName());
// Start the service, keeping the device awake while it is launching.
startWakefulService(context, (intent.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
}
}
Intent Service:
public class GcmIntentService extends IntentService {
public static final int NOTIFICATION_ID = 1;
private NotificationManager mNotificationManager;
NotificationCompat.Builder builder;
public GcmIntentService() {
super("GcmIntentService");
}
#Override
protected void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
// The getMessageType() intent parameter must be the intent you received
// in your BroadcastReceiver.
String messageType = gcm.getMessageType(intent);
if (!extras.isEmpty()) { // has effect of unparcelling Bundle
/*
* Filter messages based on message type. Since it is likely that GCM
* will be extended in the future with new message types, just ignore
* any message types you're not interested in, or that you don't
* recognize.
*/
if (GoogleCloudMessaging.
MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
sendNotification("Send error: " + extras.toString());
} else if (GoogleCloudMessaging.
MESSAGE_TYPE_DELETED.equals(messageType)) {
sendNotification("Deleted messages on server: " +
extras.toString());
// If it's a regular GCM message, do some work.
} else if (GoogleCloudMessaging.
MESSAGE_TYPE_MESSAGE.equals(messageType)) {
// This loop represents the service doing some work.
for (int i=0; i<5; i++) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
}
// Post notification of received message.
sendNotification("Received: " + extras.toString());
}
}
// Release the wake lock provided by the WakefulBroadcastReceiver.
GcmBroadcastReceiver.completeWakefulIntent(intent);
}
// Put the message into a notification and post it.
// This is just one simple example of what you might choose to do with
// a GCM message.
private void sendNotification(String msg) {
mNotificationManager = (NotificationManager)
this.getSystemService(Context.NOTIFICATION_SERVICE);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, HomeActivity.class), 0);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setContentTitle("GCM Notification")
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(msg))
.setContentText(msg);
mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
}
}
Android Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.HBM.sample" >
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission android:name="com.HBM.sample.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.HBM.sample.permission.C2D_MESSAGE" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<receiver
android:name=".GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.HBM.sample" />
</intent-filter>
</receiver>
<service
android:name=".GcmIntentService"
android:enabled="true" />
<activity
android:name=".RegisterActivity"
android:windowSoftInputMode="stateHidden|adjustResize" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".HomeActivity"
android:windowSoftInputMode="stateHidden|adjustResize" >
android:label="#string/title_activity_home" >
</activity>
<meta-data android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
</application>
</manifest>
The app compiles fine and when I set a breakpoint in registerInBackground after:
regid = gcm.register(SENDER_ID);
the client registers fine and I get the registration id that looks something like this:
APA91bEdxx0UyqtX6qoVuhYNSeJkuAITIpdkbCkBCCsOyX5-lpbtNAJBvvGqIGKqxGhW24-y-tWbj2EDKJAiyvzVhP7jhMevZBr-o-Y6Eli0uG24oWXjFOWa1Sj9vjNXaO5wbWs7WodC4Oq4QOFaPQscF_v44Z_kyg
After that I created a GCM Server application and send a notification to the registrationId
Here is the json response:
{"multicast_id":5827029040432755439,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1407451852374547%913f6fe1f9fd7ecd"}]}
It looks like the app registers fine and the notifications are pushed successfully. But onReceive never fires and I dont get any notifications o_O
I have tried the app on two different phones and different networks. But Im not sure what Im doing wrong. I hope someone can help me. I would really appreciate it.