I'm currenlty implementing GCM into my app. I used the tutorial here as a start point.
The problem is that my regId is always null:
GCMRegistrar.checkDevice(this);
GCMRegistrar.checkManifest(this);
final String regId = GCMRegistrar.getRegistrationId(this);
if (regId.equals(""))
{
GCMRegistrar.register(this, "627xxxx78");
}
else
{
if (GCMRegistrar.isRegisteredOnServer(this))
{
Log.i(TAG, "Already registered regId : " + regId );
}
else
{
final Context context = this;
mRegisterTask = new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
boolean registered =
ServerUtilities.register(context, regId);
if (!registered)
{
GCMRegistrar.unregister(context);
}
return null;
}
#Override
protected void onPostExecute(Void result) {
mRegisterTask = null;
}
};
mRegisterTask.execute(null, null, null);
}
}
In the code above, ServerUtilities.register is never called because GCMRegistrar.getRegistrationId(this); always returns an empty string.
Any ideas?
Make sure that your emulator or device is signed in with Google Account. I encountered the same problem. I simply signed in the device's google account, and lolz, I got the regId.
I have had the same issue. Add the following in your application manifest file:
package="yourApplicationPackage"
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<permission
android:name="yourApplicationPackage.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission
android:name="yourApplicationPackage.permission.C2D_MESSAGE" />
<!-- This app has permission to register and receive data message. -->
<uses-permission
android:name="com.google.android.c2dm.permission.RECEIVE" />
<receiver
android:name="com.google.android.gcm.GCMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<!-- Receives the actual messages. -->
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<!-- Receives the registration id. -->
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="yourApplicationPackage" />
</intent-filter>
</receiver>
<service android:name="yourApplicationPackage.GCMIntentService"/>
Must keep this "yourApplicationPackage.GCMIntentService" in application package
yourApplicationPackage.GCMIntentService code is like this.
public class GCMIntentService extends GCMBaseIntentService {
#Override
protected void onError(Context arg0, String arg1) {
// TODO Auto-generated method stub
}
#Override
protected void onMessage(Context context, Intent intent) {
// TODO Auto-generated method stub
}
#Override
protected void onRegistered(Context context, String registrationId) {
// TODO Auto-generated method stub
Log.i(TAG, "Device registered: regId = " + registrationId);
GcmServer.register(context, registrationId);
}
#Override
protected void onUnregistered(Context arg0, String arg1) {
// TODO Auto-generated method stub
}
Related
I'm very new to android studio and in my first app I want to build an sos app, my sos app specifically sends a message via sms with the current location. When I first built it, it only works on android 5.0 and down, it will not work in 6.0 and up and now I've tried to look at the logcat and the logcat says it needs a permission to send sms so I gave it a permission using the code below this paragraph and now it runs in android 6.0 but it's not sending messages... {if(checkselfpermission(Manifest.permission.SEND_SMS)==PackageManager.PERMISSION GRANTED);}
can you help me here is my manifest my file
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.ACCESS_COURSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application
android:allowBackup="true"
android:icon="#mipmap/sos"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!--
ATTENTION: This was auto-generated to add Google Play services to your project for
App Indexing. See https://g.co/AppIndexing/AndroidStudio for more information.
-->
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<activity
android:name=".DisplayContactActivity"
android:label="#string/title_activity_display_contact"
android:parentActivityName=".MainActivity"
android:theme="#style/AppTheme.NoActionBar" />
<activity
android:name=".EditContactActivity"
android:label="#string/title_activity_edit_contact"
android:parentActivityName=".DisplayContactActivity"
android:theme="#style/AppTheme.NoActionBar" />
<activity
android:name=".DisplayMessageActivity"
android:label="#string/title_activity_display_message"
android:parentActivityName=".MainActivity"
android:theme="#style/AppTheme.NoActionBar" />
<activity
android:name=".LogInActivity"
android:label="#string/title_activity_log_in"
android:parentActivityName=".MainActivity"
android:theme="#style/AppTheme.NoActionBar"></activity>
</application>
and here is my main activity.
public class MainActivity extends AppCompatActivity {
private static final int PERMISSION_SEND_SMS = 1;
ContactDbAdapter contactDbAdapter;
private GoogleApiClient client;
EditText messageText;
UserDbAdapter userDbAdapter;
Cursor cursor;
TextView locationText;
#Override
public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
return super.checkUriPermission(uri, pid, uid, modeFlags);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
userDbAdapter = new UserDbAdapter(this);
messageText = (EditText) findViewById(R.id.messageText);
locationText = (TextView) findViewById(R.id.locationTextView);
try {
userDbAdapter.open();
} catch (SQLException error) {
Log.e("mytag", "Error open userDbAdapter\n");
}
contactDbAdapter = new ContactDbAdapter(this);
try {
contactDbAdapter.open();
} catch (SQLException error) {
Log.e("mytag", "Error open contactDbAdapter\n");
}
cursor = contactDbAdapter.getContacts();
final Button sos = (Button) findViewById(R.id.redbutton);
final Button finish = (Button) findViewById(R.id.greenbutton);
final CountDownTimer timer = new CountDownTimer(3999, 100) {
public void onTick(long millisUntilFinished) {
assert sos != null;
sos.setText("" + ((int) (millisUntilFinished) / 1000));
}
#TargetApi(Build.VERSION_CODES.M)
public void onFinish() {
sos.setVisibility(View.GONE);
finish.setVisibility(View.VISIBLE);
finish.setText("finish");
SmsManager smsManager = SmsManager.getDefault();
cursor = contactDbAdapter.getContacts();
String msg = messageText.getText().toString() + "#" + locationText.getText().toString();
Log.e("mytag", msg);
if(cursor.moveToFirst()){
do{
if (checkSelfPermission(Manifest.permission.SEND_SMS)==PackageManager.PERMISSION_GRANTED);
String number=cursor.getString(cursor.getColumnIndex(contactDbAdapter.PHONE_NUM));
smsManager.sendTextMessage(number, null, msg, null, null);
}while(cursor.moveToNext());
}
}
};
sos.setTag(1);
sos.setOnClickListener(
new Button.OnClickListener() {
public void onClick(View v) {
final int status = (Integer) v.getTag();
if (status != 1) {
sos.setText("sos");
sos.setTag(1);
timer.cancel();
} else {
sos.setTag(0);
timer.start();
}
}
}
);
finish.setOnClickListener(
new Button.OnClickListener() {
public void onClick(View v) {
sos.setVisibility(View.VISIBLE);
finish.setVisibility(View.GONE);
sos.callOnClick();
}
}
);
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information
client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
}
#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
switch (id) {
case R.id.contact:
Intent contactIntent = new Intent(getApplicationContext(), LogInActivity.class);
startActivity(contactIntent);
return true;
case R.id.message:
Intent messageIntent = new Intent(getApplicationContext(), DisplayMessageActivity.class);
startActivity(messageIntent);
default:
break;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onStart() {
super.onStart();
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
client.connect();
Action viewAction = Action.newAction(
Action.TYPE_VIEW, // TODO: choose an action type.
"Main Page", // TODO: Define a title for the content shown.
// TODO: If you have web page content that matches this app activity's content,
// make sure this auto-generated web page URL is correct.
// Otherwise, set the URL to null.
Uri.parse("http://host/path"),
// TODO: Make sure this auto-generated app deep link URI is correct.
Uri.parse("android-app://com.cse4471.osu.sos_osu/http/host/path")
);
AppIndex.AppIndexApi.start(client, viewAction);
}
#Override
public void onResume() {
super.onResume();
// refresh user message
cursor = userDbAdapter.getUsers();
if (cursor.moveToFirst()) {
messageText.setText(cursor.getString(cursor.getColumnIndex(userDbAdapter.MESSAGE)));
}
// Acquire a reference to the system Location Manager
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{
Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.INTERNET}, 10);
return;
}
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
// Called when a new location is found by the network location provider.
locationText.setText("Latitude:" + location.getLatitude() + ", Longitude:" + location.getLongitude());
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
public void onProviderEnabled(String provider) {
}
public void onProviderDisabled(String provider) {
}
};
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 0, locationListener);
Location loc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if(loc != null) {
// messageText.setText("Latitude:" + loc.getLatitude() + ", Longitude:" + loc.getLongitude());
locationText.setText("Latitude:" + loc.getLatitude() + ", Longitude:" + loc.getLongitude());
}
}
#Override
public void onStop() {
super.onStop();
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
Action viewAction = Action.newAction(
Action.TYPE_VIEW, // TODO: choose an action type.
"Main Page", // TODO: Define a title for the content shown.
// TODO: If you have web page content that matches this app activity's content,
// make sure this auto-generated web page URL is correct.
// Otherwise, set the URL to null.
Uri.parse("http://host/path"),
// TODO: Make sure this auto-generated app deep link URI is correct.
Uri.parse("android-app://com.cse4471.osu.sos_osu/http/host/path")
);
AppIndex.AppIndexApi.end(client, viewAction);
client.disconnect();
}
#Override
public void onDestroy() {
super.onDestroy();
if (cursor != null) {
cursor.close();
}
}
this is also the logcat that appeared before I gave the permission to run it on android 6.0
Process: com.cse4471.osu.sos_osu, PID: 23011
java.lang.SecurityException: Sending SMS message: uid 10179 does not have android.permission.SEND_SMS.
at android.os.Parcel.readException(Parcel.java:1620)
at android.os.Parcel.readException(Parcel.java:1573)
at com.android.internal.telephony.ISms$Stub$Proxy.sendTextForSubscriber(ISms.java:842)
at android.telephony.SmsManager.sendTextMessageInternal(SmsManager.java:317)
at android.telephony.SmsManager.sendTextMessage(SmsManager.java:300)
at com.cse4471.osu.sos_osu.MainActivity$1.onFinish(MainActivity.java:119)
at android.os.CountDownTimer$1.handleMessage(CountDownTimer.java:127)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5628)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:853)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:737)
I hope you can help me with this.
You can try this :-
Add it in Manifest -
<uses-permission android:name="android.permission.SEND_SMS" />
And use this runtime permission in your activity
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.SEND_SMS},1);
So I followed the tutorial on creating a SyncAdapter without a real ContentProvider and an Account (from here) but came across a problem I just can't fix.
When calling ContentResolver.requestSync() to manually force a sync, it seems, that the SyncAdapter I implemented just doesn't get called.
Please note, that I created all the stub classes (StubAuthenticator, StubProvider, AuthenticatorService) and the SyncService exactly how they got created in the mentioned tutorial. If you need me to post the code either way, I will edit this post.
Android Manifest.xml
<application
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/>
<uses-permission android:name="android.permission.READ_SYNC_STATS"/>
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS"/>
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
...
<service
android:name=".datasync.SyncService"
android:exported="true"
android:process=":sync">
<intent-filter>
<action android:name="android.content.SyncAdapter"/>
</intent-filter>
<meta-data
android:name="android.content.SyncAdapter"
android:resource="#xml/sync_adapter"/>
</service>
<service
android:name=".datasync.AuthenticatorService">
<intent-filter>
<action android:name="android.accounts.AccountAuthenticator"/>
</intent-filter>
<meta-data
android:name="android.accounts.AccountAuthenticator"
android:resource="#xml/authenticator"/>
</service>
<provider
android:name=".datasync.StubProvider"
android:authorities="myexample.com.provider"
android:enabled="true"
android:exported="false"
android:label="DataSyncContentProvider"
android:syncable="true"/>
</application>
sync_adapter.xml
<?xml version="1.0" encoding="utf-8"?>
<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
android:contentAuthority="myexample.com.provider"
android:accountType="myexample.com.account"
android:userVisible="false"
android:allowParallelSyncs="false"
android:isAlwaysSyncable="true"/>
authenticator.xml
<?xml version="1.0" encoding="utf-8"?>
<account-authenticator
xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="myexample.com.account"
android:label="MyExampleApp"/>
DataSyncAdapter.java
public class DataSyncAdapter extends AbstractThreadedSyncAdapter{
public DataSyncAdapter(Context context, boolean autoInitialize) {
super(context, autoInitialize);
}
#Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider,
SyncResult syncResult) {
Log.d(MainActivity.TAG, "onPerformSync: Called");
//do sync stuff here
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity{
/**
* Tag for own application.
*/
public static final String TAG = "com.myexample";
#Override
protected final void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//create UI here...
Bundle syncExtras = new Bundle();
//add additional sync stuff (internal)
DataSyncUtil.createSyncRequest(this, syncExtras);
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[]
grantResults) {
switch (requestCode) {
case PERMISSIONS_GET_ACCOUNTS:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Bundle syncExtras = new Bundle();
//add additional sync stuff (internal)
DataSyncUtil.createSyncRequest(this, syncExtras);
} else {
//TODO handle permission denied
}
return;
}
}
}
DataSyncUtil.java
public class DataSyncUtil {
public static void createSyncRequest(Activity activity, Bundle extras) {
Log.d(MainActivity.TAG, "createSyncRequest: Called");
String authority = "myexample.com.provider";
Account dummy = getDummySyncAccount(activity);
if (dummy != null) {
if (ContentResolver.isSyncPending(dummy, authority) ||
ContentResolver.isSyncActive(dummy, authority)) {
Log.i(MainActivity.TAG, "SyncPending, canceling");
ContentResolver.cancelSync(dummy, authority);
}
extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
extras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
ContentResolver.requestSync(dummy, authority, extras);
}
}
public static Account getDummySyncAccount(Activity activity) {
String auth_type = "myexample.com.account;
Account dummy = null;
AccountManager accountManager = (AccountManager) activity.getSystemService(ACCOUNT_SERVICE);
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.GET_ACCOUNTS) !=
PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.GET_ACCOUNTS},
MainActivity.PERMISSIONS_GET_ACCOUNTS);
} else {
Account[] existing = accountManager.getAccountsByType(auth_type);
if (existing != null && existing.length > 0) {
//TODO handle more than one account
Log.d(MainActivity.TAG, "getDummySyncAccount: Account already exists and is getting returned");
dummy = existing[0];
} else {
Log.d(MainActivity.TAG, "getDummySyncAccount: Account has to be created");
// Create the account type and default account
dummy = new Account(ACCOUNT, auth_type);
// Get an instance of the Android account manager
/*
* Add the account and account type, no password or user data
* If successful, return the Account object, otherwise report an error.
*/
if (accountManager.addAccountExplicitly(dummy, null, null)) {
ContentResolver.setIsSyncable(dummy, "myexample.com.content", 1);
ContentResolver.setSyncAutomatically(dummy, "myexample.com.content", true);
} else {
/*
* The account exists or some other error occurred.Log this, report it,
* or handle it internally.
*/
}
}
}
Log.d(MainActivity.TAG, "getDummySyncAccount: "+dummy.name);
return dummy;
}
}
The code executes just fine up until ContentResolver.requestSync() in the DataSyncUtil class, but the DataSyncAdapter never gets called.
I'd appreciate any help on this :)
FYI: This is my first big scale Android project, so I'm rather inexperienced.
It appears I made a rookie mistake. onPerformSync() does indeed get called. But I had the filter "Show only selected application" in my android monitor set, so that the Log.d in the background sync service didn't show.
This answer helped me out.
I am following a tutorial for adding a user account to the Android AccountManager.
In my main activity, I have the following method:
private void addNewAccount(String accountType, String authTokenType) {
Log.d(TAG,"addNewAccount called");
final AccountManagerFuture<Bundle> future = mAccountManager.addAccount(accountType, authTokenType, null, null, this, new AccountManagerCallback<Bundle>() {
#Override
public void run(AccountManagerFuture<Bundle> future) {
try {
Bundle bnd = future.getResult();
Log.d("ACME", "AddNewAccount Bundle is " + bnd);
} catch (Exception e) {
e.printStackTrace();
}
}
}, null);
}
This method is being called, as I see the log in the logcat. Now my AbstractAccountAuthenticator implementation is as follows:
public class AcmeAuthenticator extends AbstractAccountAuthenticator {
private String TAG = "AcmeAuthenticator";
private final Context mContext;
public AcmeAuthenticator(Context context) {
super(context);
this.mContext = context;
}
#Override
public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options) throws NetworkErrorException {
Log.d("acme", TAG + "> addAccount");
final Intent intent = new Intent(mContext, AuthenticatorActivity.class);
intent.putExtra(AuthenticatorActivity.ARG_ACCOUNT_TYPE, accountType);
intent.putExtra(AuthenticatorActivity.ARG_AUTH_TYPE, authTokenType);
intent.putExtra(AuthenticatorActivity.ARG_IS_ADDING_NEW_ACCOUNT, true);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
final Bundle bundle = new Bundle();
bundle.putParcelable(AccountManager.KEY_INTENT, intent);
return bundle;
}
The above method is never called. The following is the service I have created for it:
public class AcmeAuthenticatorService extends Service {
#Override
public IBinder onBind(Intent intent) {
AcmeAuthenticator authenticator = new AcmeAuthenticator(this);
return authenticator.getIBinder();
}
}
And my manifest definition is as follows:
<activity android:name="com.exercise.accountmanagerstudy.accountAuthenticator.AuthenticatorActivity" android:label="#string/login_label"/>
<service android:name=".accountAuthenticator.AcmeAuthenticatorService">
<intent-filter>
<action android:name="android.accounts.AccountAuthenticator" />
</intent-filter>
<meta-data android:name="android.accounts.AccountAuthenticator"
android:resource="#xml/authenticator" />
</service>
<!-- client -->
<uses-permission android:name="android.permission.USE_CREDENTIALS"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS"/>
<!-- Authenticator -->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/>
I am not getting an compiler errors, the addAccount override in the AbstractAccountAuthenticator implementation is not called. from the main activity addNewAccount method. I have researched around for a few links here and here.
Any help will be appreciated.
Ok, so I finally did figure it out. Apparently, the authenticator.xml file for AcmeAuthenticator has a field called accountType:
<?xml version="1.0" encoding="utf-8"?>
<account-authenticator
xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="com.exercise.accountmanagerstudy"
android:icon="#drawable/ic_launcher"
android:smallIcon="#drawable/ic_launcher"
android:label="#string/label"
android:accountPreferences="#xml/prefs"/>
When I was calling addNewAccount in my main activity, I was supposed to pass the exact value of the accountType in the above mentioned xml as the accountType argument. Phew, that took me quite sometime and hope it helps someone else :-).
I have parse notifications set up for my android app using Parse 1.7.1 sdk version.
But in the new android this method with parse says to call is depreciated.
PushService.setDefaultPushCallback(this, MainActivity.class);
But when it is removed the notification is sent from parse.com as I can see on the website but it does not arrive to the phone?
How can this be changed so that the push will arrive? Without using the depreciated method?
Thanks for the help in advance.
Try extending ParsePushBroadcastReceiver class and and use its
OnPushRecieve (to do something before notification is shown in status bar)
OnPushOpen (to do some action when user open's push for example open an activity)
getNotification and
onPushDismiss methods
And in manifest file replace
<receiver android:name="com.parse.ParsePushBroadcastReceiver" android:exported="false">
<intent-filter>
<action android:name="com.parse.push.intent.RECEIVE" />
<action android:name="com.parse.push.intent.DELETE" />
<action android:name="com.parse.push.intent.OPEN" />
</intent-filter>
</receiver>
with this :
<receiver
android:name="com.example.parse.Notifications.NotificationsReciever"
android:exported="false" >
<intent-filter>
<action android:name="com.parse.push.intent.RECEIVE" />
<action android:name="com.parse.push.intent.DELETE" />
<action android:name="com.parse.push.intent.OPEN" />
</intent-filter>
</receiver>
And if you want to open an activity onPushOpen, here is a sample:
#Override
protected void onPushOpen(Context context, Intent intent) {
// TODO Auto-generated method stub
Intent i = new Intent(context, PushNotificationHandler.class);
i.putExtras(intent.getExtras());
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
Here is a sample class that extends ParsePushBroadcastReciever class
public class NotificationsReciever extends ParsePushBroadcastReceiver {
#Override
protected Class<? extends Activity> getActivity(Context arg0, Intent arg1) {
// TODO Auto-generated method stub
return ParseStarterProjectActivity.class;
}
#Override
protected Notification getNotification(Context context, Intent intent) {
// TODO Auto-generated method stub
return super.getNotification(context, intent);
}
#Override
protected void onPushDismiss(Context context, Intent intent) {
// TODO Auto-generated method stub
super.onPushDismiss(context, intent);
}
#Override
protected void onPushOpen(Context context, Intent intent) {
// TODO Auto-generated method stub
Intent i = new Intent(context, PushNotificationHandler.class);
i.putExtras(intent.getExtras());
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
#Override
protected void onPushReceive(Context context, Intent intent) {
//here You can handle push before appearing into status e.g if you want to stop it.
super.onPushReceive(context, intent);
}
}
I've found an example of how NFC works. But when I'm attaching the NFC card onResume/OnPause calls. Why?
the function: onNewIntent hasn't called.
The code of Activity:
public class AMain extends Activity {
public static final String MIME_TEXT_PLAIN = "text/plain";
public static final String TAG = "NfcDemo";
private TextView mTextView;
private NfcAdapter mNfcAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.amain);
mTextView = (TextView) findViewById(R.id.tv);
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (mNfcAdapter == null) {
// Stop here, we definitely need NFC
Toast.makeText(this, "This device doesn't support NFC.", Toast.LENGTH_LONG).show();
finish();
return;
}
if (!mNfcAdapter.isEnabled()) {
mTextView.setText("NFC is disabled.");
} else {
mTextView.setText("NFC is enabled.");
}
handleIntent(getIntent());
}
#Override
protected void onResume() {
super.onResume();
/*
* It's important, that the activity is in the foreground (resumed). Otherwise
* an IllegalStateException is thrown.
*/
setupForegroundDispatch(this, mNfcAdapter);
}
#Override
protected void onPause() {
/*
* Call this before onPause, otherwise an IllegalArgumentException is thrown as well.
*/
stopForegroundDispatch(this, mNfcAdapter);
super.onPause();
}
#Override
protected void onNewIntent(Intent intent) {
/*
* This method gets called, when a new Intent gets associated with the current activity instance.
* Instead of creating a new activity, onNewIntent will be called. For more information have a look
* at the documentation.
*
* In our case this method gets called, when the user attaches a Tag to the device.
*/
handleIntent(intent);
}
private void handleIntent(Intent intent) {
String action = intent.getAction();
Log.d(TAG,action);
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
String type = intent.getType();
if (MIME_TEXT_PLAIN.equals(type)) {
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
new NdefReaderTask().execute(tag);
} else {
Log.d(TAG, "Wrong mime type: " + type);
}
} else if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) {
// In case we would still use the Tech Discovered Intent
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
String[] techList = tag.getTechList();
String searchedTech = Ndef.class.getName();
for (String tech : techList) {
if (searchedTech.equals(tech)) {
new NdefReaderTask().execute(tag);
break;
}
}
}
}
/**
* #param activity The corresponding {#link Activity} requesting the foreground dispatch.
* #param adapter The {#link NfcAdapter} used for the foreground dispatch.
*/
public static void setupForegroundDispatch(final Activity activity, NfcAdapter adapter) {
final Intent intent = new Intent(activity.getApplicationContext(), activity.getClass());
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
final PendingIntent pendingIntent = PendingIntent.getActivity(activity.getApplicationContext(), 0, intent, 0);
IntentFilter[] filters = new IntentFilter[1];
String[][] techList = new String[][]{};
// Notice that this is the same filter as in our manifest.
filters[0] = new IntentFilter();
filters[0].addAction(NfcAdapter.ACTION_NDEF_DISCOVERED);
filters[0].addCategory(Intent.CATEGORY_DEFAULT);
try {
filters[0].addDataType(MIME_TEXT_PLAIN);
} catch (MalformedMimeTypeException e) {
throw new RuntimeException("Check your mime type.");
}
adapter.enableForegroundDispatch(activity, pendingIntent, filters, techList);
}
/**
* #param activity The corresponding {#link BaseActivity} requesting to stop the foreground dispatch.
* #param adapter The {#link NfcAdapter} used for the foreground dispatch.
*/
public static void stopForegroundDispatch(final Activity activity, NfcAdapter adapter) {
adapter.disableForegroundDispatch(activity);
}
/**
* Background task for reading the data. Do not block the UI thread while reading.
*
* #author Ralf Wondratschek
*
*/
private class NdefReaderTask extends AsyncTask<Tag, Void, String> {
#Override
protected String doInBackground(Tag... params) {
Tag tag = params[0];
Ndef ndef = Ndef.get(tag);
if (ndef == null) {
// NDEF is not supported by this Tag.
return null;
}
NdefMessage ndefMessage = ndef.getCachedNdefMessage();
NdefRecord[] records = ndefMessage.getRecords();
for (NdefRecord ndefRecord : records) {
if (ndefRecord.getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_TEXT)) {
try {
return readText(ndefRecord);
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "Unsupported Encoding", e);
}
}
}
return null;
}
private String readText(NdefRecord record) throws UnsupportedEncodingException {
/*
* See NFC forum specification for "Text Record Type Definition" at 3.2.1
*
* http://www.nfc-forum.org/specs/
*
* bit_7 defines encoding
* bit_6 reserved for future use, must be 0
* bit_5..0 length of IANA language code
*/
byte[] payload = record.getPayload();
// Get the Text Encoding
String textEncoding = ((payload[0] & 128) == 0) ? "UTF-8" : "UTF-16";
// Get the Language Code
int languageCodeLength = payload[0] & 0063;
// String languageCode = new String(payload, 1, languageCodeLength, "US-ASCII");
// e.g. "en"
// Get the Text
return new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncoding);
}
#Override
protected void onPostExecute(String result) {
if (result != null) {
mTextView.setText("Read content: " + result);
}
}
}
}
Manifest file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.nfc"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.NFC" />
<uses-feature
android:name="android.hardware.nfc"
android:required="true" />
<uses-sdk
android:minSdkVersion="10"
android:targetSdkVersion="19" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.nfc.AMain"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED"/>
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED"/>
</intent-filter>
<meta-data android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="#xml/nfc_tech_filter" />
</activity>
</application>
</manifest>
You should add NfcAdapter.ACTION_TAG_DISCOVERED to your intent filter. Your current intent filter( filters[0].addAction(NfcAdapter.ACTION_NDEF_DISCOVERED);) only catches NFC tag containin NDEF messages.
by changing your filter to
filters[0].addAction(NfcAdapter.ACTION_TAG_DISCOVERED);
you should get what you want.
Hi have you set the <uses-permission android:name="android.permission.NFC" /> in your ,manifest?