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 :-).
Related
I have written code to make screenshots on Android and I am trying to write a test for this. When running the test method, then I receive the following error message: Activity never becomes requested state "[STARTED, CREATED, DESTROYED, RESUMED]" (last lifecycle transition = "PRE_ON_CREATE"). I have a hard time figuring out what I am doing wrong.
The production code has been tested manually.
My test code in src/androidTest/java/org/app:
#RunWith (AndroidJUnit4.class)
public class ScreenshotsCaptorTest {
#Rule
public ActivityScenarioRule<TestActivity> rule =
new ActivityScenarioRule<>(TestActivity.class);
#Test
public void test() {
// This line is never reached
ActivityScenario<TestActivity> scenario = rule.getScenario();
scenario.onActivity(activity -> {
activity.setCallback(() -> {
try {
Bitmap screenshot = ScreenshotsCaptorBuilder.captor.takeScreenshot();
// Assert screenshot is non-null
} catch (CaptureScreenshotFailedException e) {
throw new RuntimeException(e);
}
});
Intent intent = ScreenshotsCaptorBuilder.intent(activity);
activity.startActivityForResult(intent, 100);
});
}
}
My helper Activity in src/androidTest/java/org/app:
import org.app.test.R;
public class TestActivity extends Activity {
private Callback callback;
#Override
public void onCreate(Bundle savedInstanceState) {
// This line is never reached
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
}
public void setCallback(Callback callback) {
// This line is never reached
this.callback = callback;
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
// This line is never reached
ScreenshotsCaptorBuilder.createCaptor(this, resultCode, intent);
callback.done();
}
public interface Callback {
// This line is never reached
void done();
}
}
The src/androidTest/AndroidManifest.xml file:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.app">
<application>
<activity
android:name=".TestActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
And src/androidTest/res/layout/activity_test.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.constraintlayout.widget.ConstraintLayout>
It would be really helpful if someone provide me some suggestions or tips to resolve my issue. Thanks in advance.
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 trying to start a service inside a Unity3d Android plugin but can not make it work. Is working on Android Studio test app, but the service call fail inside unity.
My service class
public class ProximityService extends Service {
private String TAG = "iProximity: ";
NotificationManager _NotificationManager;
private Context _Context;
private static Timer _Timer = new Timer();
public ProximityService() {
}
private void sendNotification() {
Uri sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder builder;
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, iRealUnityPlayerActivity.class), 0);
builder = (NotificationCompat.Builder) new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ireal)
.setContentTitle("Notification")
.setContentText("message")
.setTicker("msg: mensaje")
.setSound(sound)
.setAutoCancel(true);
builder.setContentIntent(contentIntent);
_NotificationManager.notify(0, builder.build());
}
#Override
public void onCreate() {
Log.i(TAG, "onCreate()");
super.onCreate();
_Context = getApplicationContext();
_NotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
}
// methods
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommanf()");
//startProximity();
sendNotification();
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind()");
// TODO: Return the communication channel to the service.
return null;
}
}
Java class that is used to start the service:
public final class StatusCheckStarter {
static Context myContext;
// Called From C# to get the Context Instance
public static void ReceiveContextInstance(Context tempContext) {
myContext = tempContext;
}
public static String StartProximityService()
{
String result = "OK";
try
{
myContext.startService(new Intent(myContext, ProximityService.class));
}
catch (Exception e) {
e.printStackTrace();
result = e.getMessage();
}
return result;
}
public static String Dummy() {
return "DONEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE";
}
}
Unity C# code that is used to call the java functions to start the service:
AndroidJavaClass unityClass;
AndroidJavaObject unityActivity;
AndroidJavaObject unityContext;
AndroidJavaClass customClass;
string a1 = "";
string a2 = "";
string a3 = "";
string a4 = "";
void Start () {
//Replace with your full package name
sendActivityReference("info.ireal.proximitylib.StatusCheckStarter");
//Now, start service
startService();
Debug.Log ("START");
}
void sendActivityReference(string packageName)
{
unityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
unityActivity = unityClass.GetStatic<AndroidJavaObject>("currentActivity");
unityContext = unityActivity.Call<AndroidJavaObject>("getApplicationContext");
customClass = new AndroidJavaClass(packageName);
customClass.CallStatic("ReceiveContextInstance", unityContext);
}
void startService()
{
a4 = customClass.CallStatic<string> ("Dummy");
a3 = customClass.CallStatic<string>("StartProximityService");
}
The Dummy method is working and return a string value, but the service does not work
Adb logcat message:
Unable to start service Intent {
cmp=info.ireal.proximitytest/info.ireal.proximitylib.ProximityService
VirtualScreenParam=Params{mDisplayId=-1, null, mFlags=0x00000000)} }
U=0: not found
I really appreciate any help Best regards
Mariano
I am using the solution from this thread but still cant make it work.
EDIT
My AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.unity3d.player"
android:installLocation="preferExternal"
android:versionCode="1"
android:versionName="1.0">
<supports-screens
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true"
android:anyDensity="true"/>
<application
android:theme="#style/UnityThemeSelector"
android:icon="#drawable/app_icon"
android:label="#string/app_name"
android:debuggable="true">
<activity android:name="com.unity3d.player.UnityPlayerActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
<service android:name="info.ireal.proximitylib.ProximityService" />
<!---<service android:name="ProximityService" />-->
</application>
</manifest>
This could be the Manifest. Make sure to include the service class in the service tag.
It could be any of these problems below. Build, Run and test each one you try.
1.Add the class to the Manifest.
<application
<service android:name=".ProximityService" />
</application>
2.Add the class with the full path to the Manifest.
If this does not work, use the full service class package name
<application
<service android:name="info.ireal.proximitylib.ProximityService" />
</application>
3.Add the class to the Manifest from Unity itself.
Again, if that fails, go to <UnityInstallationDirecory>\Editor\Data\PlaybackEngines\AndroidPlayer\Apk
Copy the AndroidManifest.xml from that place file to your Assets\Plugins\Android directory then include the service tag code above in the Manifest. Save and run.
4.Finally, use Activity instead of Context.
Changes on the Java side:
A.Rename static Context myContext; to static Activity myActivity;
B.Change
public static void ReceiveContextInstance(Context tempContext) {
myContext = tempContext;
}
to
public static void ReceiveContextInstance(Activity tempActivity) {
myActivity = tempActivity;
}
Changes on C# side:
C.Replace customClass.CallStatic("ReceiveContextInstance", unityContext); with customClass.CallStatic("ReceiveContextInstance", unityActivity);
For some reason I cannot bind to my service? I need the onServiceConnected() method to run so that I can use my AIDL interface. What am I doing wrong?
private ServiceConnection serviceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className, IBinder service) {
Log.d("BindingService", "Service trying to bind!");
sendService = ISendMessageService.Stub.asInterface((IBinder) service);
boundToService = true;
pendingFragment.bindToService();
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
sendService = null;
boundToService = false;
pendingFragment.unbindService();
}
};
The main activity methods:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
schedulerFragment = new SchedulerFragment();
pendingFragment = new PendingFragment();
fm = getFragmentManager();
titleBar = getActionBar();
titleBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
scheduleTab = titleBar.newTab();
pendingTab = titleBar.newTab();
scheduleTab.setText("Schedule");
pendingTab.setText("Pending");
scheduleTab.setTabListener(new MyTabListener(schedulerFragment));
pendingTab.setTabListener(new MyTabListener(pendingFragment));
titleBar.addTab(scheduleTab);
titleBar.addTab(pendingTab);
titleBar.selectTab(scheduleTab);
Boolean success = getApplicationContext().bindService(new Intent(SendMessageService.class.getName()),
serviceConnection, Context.BIND_AUTO_CREATE);
Log.d("ServiceConnection", success.toString());
}
#Override
public void onStop() {
super.onStop();
if (boundToService) {
unbindService(serviceConnection);
}
}
#Override
public void onPause() {
super.onPause();
if (boundToService) {
unbindService(serviceConnection);
}
}
This is the service's onBind() function:
#Override
public IBinder onBind(Intent intent) {
mBinder = new ISendMessageService.Stub(){
#Override
public void deleteMessage(int index) throws RemoteException {
TimedMessage m = schedule.get(index);
schedule.get(index).alarm.cancel(m.intent);
schedule.remove(m);
}
#Override
public void cancelAllMessages() throws RemoteException {
for(TimedMessage m : schedule){
m.alarm.cancel(m.intent);
}
schedule.clear();
}
};
return mBinder;
The manifest:
<service
android:name="com.pearhill.messagesender.SendMessageService"
android:enabled="true"
android:exported="true"
android:process=":remote" >
<intent-filter>
<action android:name="com.pearhill.messagesender.ISendMessageService.aidl" />
</intent-filter>
</service>
Here are the links for full description:
https://developer.android.com/guide/components/bound-services.html
https://developer.android.com/guide/components/aidl.html#Calling
As a key point make sure your aidl is copied over to your application properly. Clean the project and remove aidl.
Then copy the aidl over to your application in aidl folder, but package name same of remote aidl. Rebuild. You need not to mention service in your androidManifest of calling application; it will be taken care by aidl interface that you copied over.
Make sure service is also an app and not a library (jar type). At least we couldn't make it work with service in jar file. You may choose "No activity" in the new app wizard, if you are not planning to create local activity. In that case you can create apk using "Build->Build Apk" menu in Android studio for service based app. Make sure to install the service apk before running BindService from remote app. You need not to run service as BindService will also start the service, but you need to install apk, so that it is available in system. You can use adb install path/myapkname.apk.
Action name is not must, but this is how we did bind the service, where "com.example.RemoteService.BIND" was action name for service:
String pkg = IRemoteService.class.getPackage().getName();
//get the class name from the interface package
String interfaceName = IRemoteService.class.getName();
String clsName = interfaceName.replace("IRemoteService", "RemoteService");
Intent it = new Intent("com.example.RemoteService.BIND");
it.setClassName(pkg, clsName);
boolean bRet = getApplicationContext().bindService(it, mConnection, Service.BIND_AUTO_CREATE);
Log.d("IRemote", "IRemoteService Service.BIND_AUTO_CREATE return: " + bRet);
This is what was used in eclipse and worked, but failed in Android studio because of explicit intent:
Intent it = new Intent( );
it.setClassName("com.example.aidlservice",
"com.example.aidlservice.MyService");
//optional
it.setAction("com.example.RemoteService.BIND");
//binding to remote service
boolean bRet = bindService(it, mServiceConnection, Service.BIND_AUTO_CREATE);
Log.d("IRemote", "Service.BIND_AUTO_CREATE");
Here is manifest of service app. You may want to add permissions for security reasons:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.testaidl">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<service android:name=".RemoteService" android:process=":remote" android:exported="true">
<intent-filter>
<action android:name="com.example.RemoteService.BIND" />
</intent-filter>
</service>
</application>
</manifest>
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
}