i'm creating and app which notify the user in some specific period of time, i used JobService to let it working automatically and with the app closed, my problem is... there are some devices that my Job simply does not start, i dont know what is happing, because in my cellphone it works nice, but in some of my friends' devices, it doesn't.
I'm sending my JobService's class
package com.medicina.mednews;
public class JobServiceNotification extends JobService {
private static final String TAG = "JobServiceNotification ";
private boolean jobCancelled = false;
String android_id;
FirebaseDatabase db = FirebaseDatabase.getInstance();
DatabaseReference reference, refJob;
#Override
public boolean onStartJob(JobParameters params) {
Log.d(TAG, "Job started");
doBackgroundWork(params);
return true;
}
private void doBackgroundWork(final JobParameters params) {
new Thread(new Runnable() {
#Override
public void run() {
android_id = Settings.Secure.getString(getApplicationContext().getContentResolver(),
Settings.Secure.ANDROID_ID);
reference= db.getReference().child("Usuarios").child(android_id).child("NoticiasDoPython");
refJob = db.getReference().child("Usuarios").child(android_id).child("JobServiceFinished");
reference.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot snapshot, #Nullable String previousChildName) {
}
#Override
public void onChildChanged(#NonNull DataSnapshot snapshot, #Nullable String previousChildName) {
}
#Override
public void onChildRemoved(#NonNull DataSnapshot snapshot) {
PrincipalModel principalModell3=snapshot.getValue(PrincipalModel.class);
Log.i("G3",""+principalModell3);
Log.i("GT",snapshot.getKey());
String aa = principalModell3.getData();
String[] aaS = aa.split(" ");
String idNotification = aaS[4];
idNotification = idNotification.replace(":","");
Log.i("IdNotification",idNotification);
addNotification(principalModell3.getTitulo(),principalModell3.getDescrição(),idNotification);
}
#Override
public void onChildMoved(#NonNull DataSnapshot snapshot, #Nullable String previousChildName) {
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
for (int i = 0; i < 10; i++) {
copyFirebaseData();
Log.i("Execução","Executei = "+i);
if (jobCancelled) {
return;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Log.d(TAG, "Job finished");
DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
Date date = new Date();
Date currentTime = Calendar.getInstance().getTime();
refJob.child(dateFormat.format(date)).setValue(""+currentTime);
jobFinished(params, false);
}
}).start();
}
#Override
public boolean onStopJob(JobParameters params) {
Log.d(TAG, "Job cancelled before completion");
jobCancelled = true;
return true;
}
public void copyFirebaseData() {
android_id = Settings.Secure.getString(getApplicationContext().getContentResolver(),
Settings.Secure.ANDROID_ID);
DatabaseReference questionNodes = FirebaseDatabase.getInstance().getReference().child("Usuarios").child(android_id).child("NoticiasDoPython");
final DatabaseReference toUsersQuestions = FirebaseDatabase.getInstance().getReference().child("Usuarios").child(android_id).child("NoticiasMovidasPeloAndroid");
questionNodes.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot questionCode : dataSnapshot.getChildren()) {
String KeyChild = questionCode.getKey();
Log.i("KEYYY",KeyChild);
String DateAntiga = questionCode.child("Data").getValue(String.class);
String DescricaoAntiga = questionCode.child("Descrição").getValue(String.class);
String TituloAntiga = questionCode.child("Titulo").getValue(String.class);
String LinkAntiga = questionCode.child("Link").getValue(String.class);
String ImagemAntiga = questionCode.child("Imagem").getValue(String.class);
String Id = questionCode.child("IdNoticia").getValue(String.class);
toUsersQuestions.child(KeyChild).child("Id").setValue(Id);
toUsersQuestions.child(KeyChild).child("Imagem").setValue(ImagemAntiga);
toUsersQuestions.child(KeyChild).child("Data").setValue(DateAntiga);
toUsersQuestions.child(KeyChild).child("Descrição").setValue(DescricaoAntiga);
toUsersQuestions.child(KeyChild).child("Link").setValue(LinkAntiga);
toUsersQuestions.child(KeyChild).child("Titulo").setValue(TituloAntiga);
questionNodes.child(KeyChild).removeValue();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
private void addNotification(String titleNot,String DescriptNot, String idNotification) {
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel("default", "Channel name", NotificationManager.IMPORTANCE_DEFAULT);
channel.setDescription("Channel description");
notificationManager.createNotificationChannel(channel);
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "default")
.setSmallIcon(R.drawable.ic_baseline_nuvem_deletar)
.setContentTitle(getResources().getString(R.string.app_name))
.setDefaults(Notification.DEFAULT_ALL)
.setContentTitle(titleNot)
.setPriority(Notification.PRIORITY_HIGH)
.setPriority(NotificationManager.IMPORTANCE_HIGH)
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(DescriptNot))
.setCategory(NotificationCompat.CATEGORY_MESSAGE)
.setContentText(DescriptNot);
builder.setSound(Settings.System.DEFAULT_NOTIFICATION_URI);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
//ESTAMOS DEFININDO UM ID ALEATÓRIO PARA GERAR MÚLTIPLAS NOTIFICAÇÕES
Calendar cal = Calendar.getInstance();
long millisecondOfDay =
TimeUnit.HOURS.toMillis(cal.get(Calendar.HOUR_OF_DAY)) +
TimeUnit.MINUTES.toMillis(cal.get(Calendar.MINUTE)) +
TimeUnit.SECONDS.toMillis(cal.get(Calendar.SECOND)) +
cal.get(Calendar.MILLISECOND);
manager.notify(Integer.parseInt(idNotification), builder.build()); //IREMOS DEFINIR UM ID COM UUID, MAS DEPOIS TEREMOS QUE MUDAR POIS ISSO NÃO ESTÁ CERTO !!! POSSIVELMENTE TEREMOS QUE IR PRO JSON
//ESTAMOS DEFININDO UM ID ALEATÓRIO PARA GERAR MÚLTIPLAS NOTIFICAÇÕES
}
}
Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.QUICKBOOT_POWERON" />
<application
android:name=".FirebaseHandler"
android:allowBackup="true"
android:dataExtractionRules="#xml/data_extraction_rules"
android:fullBackupContent="#xml/backup_rules"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher"
android:supportsRtl="true"
android:theme="#style/Theme.Mednews"
tools:targetApi="31">
<receiver
android:name=".StartReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
<service
android:name=".JobServiceNotification"
android:permission="android.permission.BIND_JOB_SERVICE" />
<activity
android:name=".MedMenu.activity.MainActivity"
android:exported="true"
android:screenOrientation="portrait"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data
android:name="preloaded_fonts"
android:resource="#array/preloaded_fonts" />
</application>
</manifest>
I tried to use the normal JobService class, but it simply doesn't work in some specific devices, the result is that my notifications don't start
Related
The problem I'm currently experiencing is that I am unable to start and stop the service of another class. I was able to run the application but I couldn't get the results I wanted, as the program didn't show any errors. I thought it was something wrong with my buttons at first, so i tried using System.out.println to see if i get any feedback, in which i did. Then, i decided to try it on my other class (location.java), the System.out.Println I used did not work, which probably means its not even working.
MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private EditText input;
private Button start, stop;
private Intent intent;
public static int minute;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iniUI();
}
private void iniUI() {
input=findViewById(R.id.input);
start=findViewById(R.id.start);
stop=findViewById(R.id.stop);
start.setEnabled(false);
stop.setEnabled(false);
start.setOnClickListener(this);
stop.setOnClickListener(this);
intent=new Intent(this, Location.class);
permission();
}
#Override
public void onClick(View view) {
if(view.getId()==R.id.start) {
minute=Integer.parseInt(input.getText().toString());
startTracking();
}
else if(view.getId()==R.id.stop)
stopTracking();
}
private void permission(){
if(ContextCompat.checkSelfPermission(getApplicationContext(), ACCESS_FINE_LOCATION)==PackageManager.PERMISSION_GRANTED) {
start.setEnabled(true);
}
else{
ActivityCompat.requestPermissions(this, new String[]{ACCESS_FINE_LOCATION}, 0);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode==0){
if(grantResults.length>0 && grantResults[0]==PackageManager.PERMISSION_GRANTED){
permission();
}
}
}
private void startTracking(){
startService(intent);
buttonAlt();
}
private void stopTracking() {
stopService(intent);
buttonAlt();
}
private void buttonAlt(){
start.setEnabled(!start.isEnabled());
stop.setEnabled(!start.isEnabled());
}}
Location.java
public class Location extends Service{ private Thread thread;
private LocationManager locationManager;
private double longitude, latitude;
private String dateTime, encodeData;
public Location() {
}
#Override
public void onCreate() {
super.onCreate();
thread = new Thread(runThread);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
thread.start();
return super.onStartCommand(intent, flags, startId);
}
private Runnable runThread = new Runnable() {
#Override
public void run() {
while (true) {
try {
System.out.println("Shutting down");
long sMinutes = MainActivity.minute * 60 * 1000;
Thread.sleep(sMinutes);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
System.out.println("Running");
sendLocation();
}
}
};
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
private void sendLocation() {
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
#SuppressLint("MissingPermission")
android.location.Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
longitude=location.getLongitude();
latitude=location.getLatitude();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date=new Date(System.currentTimeMillis());
dateTime=sdf.format(date);
postData();
}
private void encodeData() throws UnsupportedEncodingException {
encodeData= URLEncoder.encode("datetime", "UTF-8") + "=" + URLEncoder.encode(dateTime, "UTF-8") +
"&" + URLEncoder.encode("latitude", "UTF-8") + "=" + URLEncoder.encode(Double.toString(latitude), "UTF-8") +
"&" + URLEncoder.encode("longitude", "UTF-8") + "=" + URLEncoder.encode(Double.toString(longitude), "UTF-8");
System.out.println("Lat:"+latitude);
System.out.println("Long:"+longitude);
}
private void postData(){
try {
encodeData();
URL url=new URL("A PHP SCRIPT TO OBTAIN MY LATITUDE AND LONGITUDE");
URLConnection urlConnection=url.openConnection();
urlConnection.setDoOutput(true);
OutputStreamWriter outputStreamWriter=new OutputStreamWriter(urlConnection.getOutputStream());
outputStreamWriter.write(encodeData);
outputStreamWriter.flush();
new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
}}
AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<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=".Location"></activity>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
To sum it all up, both classes showed no errors, but only the MainActivity.java was working. Is there anything i could change about it to get it to work? I think it has something to do with my startService() and stopService().
It seems like in your Manifest file you have registered your service Location.java as an activity, it should work once you change that to service
<service android:name=".Location" />
instead of
<activity android:name=".Location"></activity>
My call detector app is running fine on all android version except 8 Oreo. I get a deadlock paradigm: My detector is not called, and when I close the application the system kills it, not leaving it in the background.
I have already read the documentation from cable to tail https://developer.android.com/about/versions/oreo/background, I already looked a lot in google, and here in stack over flow, but no solution applied to my case, because of the required "dangerous" permissions.
My case seems simple: I have a detector, a service and the main with a button. I want it when the user calls a certain number, my main open.
What is the right way to fix this issue?
manifest.xml :
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.ACTION_MANAGE_OVERLAY_PERMISSION" />
<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">
<service
android:name=".CallDetectionService"
android:enabled="true"
android:exported="false"/>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</activity>
</application>
CallDetectionService.java
public class CallDetectionService extends Service {
private CallDetector callDetector;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
callDetector = new CallDetector(this);
int r = super.onStartCommand(intent, flags, startId);
callDetector.start();
return r;
}
#Override
public void onDestroy() {
super.onDestroy();
callDetector.stop();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
CallDetector.java
public class CallDetector {
public static final String MY_PREF = "MY_PREF";
public static final String NUMBER_KEY = "NUMBER_KEY";
private SharedPreferences sharedPreferences;
public class OutgoingDetector extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
String number = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
String compare_num = "12345678";
if (number.equals(compare_num)) {
Intent i = new Intent(context, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
setResultData(null);
context.startActivity(i);
}
}
}
private Context ctx;
private OutgoingDetector outgoingDetector;
public CallDetector(Context ctx) {
this.ctx = ctx;
outgoingDetector = new OutgoingDetector();
}
public void start() {
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_NEW_OUTGOING_CALL);
ctx.registerReceiver(outgoingDetector, intentFilter);
}
public void stop(){
ctx.unregisterReceiver(outgoingDetector);
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
private Button button;
private TextView textView;
private boolean detecting = false;
private static final int MY_PERMISSIONS_REQUEST_CALL_PHONE = 0;
public boolean isPermissionGranted() {
if (Build.VERSION.SDK_INT >= 23) {
if (checkSelfPermission(android.Manifest.permission.CALL_PHONE)
== PackageManager.PERMISSION_GRANTED) {
Log.v("TAG", "Permission is granted");
return true;
} else {
Log.v("TAG", "Permission is revoked");
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CALL_PHONE}, 1);
return false;
}
} else {
Log.v("TAG", "Permission is granted");
return true;
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textView);
button = (Button) findViewById(R.id.button);
/* button.setOnClickListener(this); */
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.CALL_PHONE)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
Manifest.permission.CALL_PHONE)) {
} else {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.CALL_PHONE},
MY_PERMISSIONS_REQUEST_CALL_PHONE);
}
}
String action = "START";
final Intent intent = new Intent(this, CallDetectionService.class);
intent.setAction(action);
startService(intent);
}
#Override
public void onResume() {
super.onResume();
SharedPreferences sharedPreferences = getSharedPreferences(CallDetector.MY_PREF, MODE_PRIVATE);
String number = sharedPreferences.getString(CallDetector.NUMBER_KEY, "URA VISUAL");
textView.setText(number);
}
}
What am I doing so wrong? I've been looking for a solution for 4 days and I still have not found anything.
i run the app in emulator it works but run it in phone api 17 and api 22 textRecognizer.isOperational() return false
what is the problem?
Manifest
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.CAMERA"/>
<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=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data android:name="com.google.android.gms.vision.DEPENDENCIES" android:value="ocr"/>
</application>
MainActivity
public class MainActivity extends AppCompatActivity {
SurfaceView CameraView;
TextView textView;
CameraSource cameraSource;
final int RequestCameraPermissionID = 1001;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
CameraView = (SurfaceView) findViewById(R.id.surface_view);
textView = (TextView) findViewById(R.id.textview);
final TextRecognizer textRecognizer = new TextRecognizer.Builder(this).build();
if (!textRecognizer.isOperational()) {
Log.w("MainActivity", "dependencies are not available");
} else {
cameraSource = new CameraSource.Builder(getApplicationContext(), textRecognizer)
.setFacing(CameraSource.CAMERA_FACING_BACK)
.setRequestedPreviewSize(1280, 1024)
.setRequestedFps(2.0f)
.setAutoFocusEnabled(true)
.build();
CameraView.getHolder().addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder holder) {
if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CAMERA},RequestCameraPermissionID);
return;
}
try {
cameraSource.start(CameraView.getHolder());
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
cameraSource.stop();
}
});
textRecognizer.setProcessor(new Detector.Processor<TextBlock>() {
#Override
public void release() {
}
#Override
public void receiveDetections(Detector.Detections<TextBlock> detections) {
final SparseArray<TextBlock> item = detections.getDetectedItems();
if(item.size() != 0){
textView.post(new Runnable() {
#Override
public void run() {
StringBuilder stringBuilder = new StringBuilder();
for (int i=0;i<item.size();i++){
TextBlock items = item.valueAt(i);
stringBuilder.append(items.getValue());
stringBuilder.append("\n");
}
textView.setText(stringBuilder.toString());
}
});
}
}
});
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode){
case RequestCameraPermissionID:
if(grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
return;
}
try {
cameraSource.start(CameraView.getHolder());
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
please help thanks
emulator api 25
phone huawei g730 u10 api 17
Imet api 22
Everytime I launch the apk, "Text recognizer could not be set up : is displayed. Even though I have set all dependencies but still i am getting this error. Please help why TextRecognizer.isOperational() is always false.
I have and android wear and android phone app. I'm trying to get them connect and ultimately send messages from the watch to the phone. On the watch though, Wearable.CapabilityApi.getCapability() returns no nodes
Here is the Wear MainActivity:
public class MainActivity extends WearableActivity {
public static final String TAG = "WatchApp";
public GoogleApiClient mApiClient;
public static final int CONNECTION_TIME_OUT_MS = 1000;
public static String nodeId;
private static final String AIR_LIFT_CAPABILITY = "airlift";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initApi();
final Button btnUp = (Button)findViewById(R.id.btnUp);
btnUp.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String text = "Preset";
//mAdapter.add( text );
//mAdapter.notifyDataSetChanged();
sendMessage( text );
Log.i("WatchApp", "btnUp Sent Preset");
}
});
Button btnDown = (Button)findViewById(R.id.btnDown);
btnDown.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String text = "AirOut";
//mAdapter.add( text );
//mAdapter.notifyDataSetChanged();
sendMessage(text );
Log.i("WatchApp", "btnUp Sent AirOut");
}
});
// Enables Always-on
setAmbientEnabled();
}
private void initApi() {
mApiClient = getGoogleApiClient(this);
setOrUpdateNotification();
Log.i("WatchApp", "initApi()");
}
private GoogleApiClient getGoogleApiClient(Context context) {
return new GoogleApiClient.Builder(context)
.addApi(Wearable.API)
.build();
}
private void setOrUpdateNotification() {
new Thread(new Runnable() {
#Override
public void run() {
CapabilityApi.GetCapabilityResult result =
Wearable.CapabilityApi.getCapability(
mApiClient, AIR_LIFT_CAPABILITY,
CapabilityApi.FILTER_REACHABLE).await(1000, TimeUnit.MILLISECONDS);
updateFindMeCapability(result.getCapability());
CapabilityApi.CapabilityListener capabilityListener =
new CapabilityApi.CapabilityListener() {
#Override
public void onCapabilityChanged(CapabilityInfo capabilityInfo) {
updateFindMeCapability(capabilityInfo);
}
};
// Wearable.CapabilityApi.addCapabilityListener(mApiClient, capabilityListener, AIR_LIFT_CAPABILITY);
}
}).start();
}
private void updateFindMeCapability(CapabilityInfo capabilityInfo) {
if (capabilityInfo.getNodes() == null) return;
Set<Node> connectedNodes = capabilityInfo.getNodes();
if (connectedNodes.isEmpty()) {
Log.i(TAG,"No Nodes Found.");
} else {
for (Node node : connectedNodes) {
// we are only considering those nodes that are directly connected
if (node.isNearby()) {
Log.i(TAG,"FOUND NODE");
nodeId = node.getId();
}
}
}
}
private void sendMessage(final String MESSAGE) {
if (nodeId != null) {
new Thread(new Runnable() {
#Override
public void run() {
mApiClient.blockingConnect(CONNECTION_TIME_OUT_MS, TimeUnit.MILLISECONDS);
Wearable.MessageApi.sendMessage(mApiClient, nodeId, MESSAGE, null);
mApiClient.disconnect();
Log.i("WatchApp", "Message ("+MESSAGE+") sent");
}
}).start();
} else {
Log.i("WatchApp", "No Nodes to send message!");
}
}
#Override
protected void onDestroy() {
super.onDestroy();
mApiClient.disconnect();
mApiClient = null;
Log.i("WatchApp", "onDestroy()");
}
}
Wear AndroidManifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.schoen.jonathan.airliftwatch">
<uses-feature android:name="android.hardware.type.watch" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#android:style/Theme.DeviceDefault">
<uses-library
android:name="com.google.android.wearable"
android:required="true" />
<meta-data android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<activity
android:name="com.schoen.jonathan.airliftwatch.MainActivity"
android:label="#string/app_name">
<intent-filter>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Phone MainActivity:
public class MainActivity extends Activity {
boolean mBound = false;
public static final String TAG = "PhoneApp";
public ListenerService listener;
public GoogleApiClient client;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnStart = (Button)findViewById(R.id.btnStart);
Button btnStop = (Button)findViewById(R.id.btnStop);
Log.i("PhoneApp", "onCreate() Receiver Registered ");
btnStart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i("PhoneApp", "btnStart Receiver Registered");
}
});
btnStop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i("PhoneApp", "btnStop Receiver unRegistered");
}
});
registerListener();
}
public void registerListener() {
client = new GoogleApiClient.Builder(this)
.addApi(Wearable.API)
.build();
listener = new ListenerService();
Wearable.MessageApi.addListener(client ,listener);
Log.i("PhoneApp", "registerListener() Listener Registered ");
}
#Override
protected void onStart() {
super.onStart();
registerListener();
Log.i("PhoneApp", "onStart() Listener Registered ");
}
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
registerListener();
Log.i("PhoneApp", "onResume() Listener Registered ");
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
//unregister our receiver
if (client != null && listener != null)
Wearable.MessageApi.removeListener(client, listener);
client = null;
listener = null;
Log.i("PhoneApp", "onPause() Listener Unregistered ");
}
#Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
//unregister our receiver
if (client != null && listener != null)
Wearable.MessageApi.removeListener(client, listener);
client = null;
listener = null;
Log.i("PhoneApp", "onPause() Listener Unregistered ");
}
}
Phone Listener Service:
public class ListenerService extends WearableListenerService {
String nodeId;
#Override
public void onMessageReceived(MessageEvent messageEvent) {
nodeId = messageEvent.getSourceNodeId();
Log.i(MainActivity.TAG, messageEvent.getPath());
showToast(messageEvent.getPath());
String msg_for_me = messageEvent.getPath();
if (msg_for_me == "AirOut")
{
Log.i(MainActivity.TAG, "Air Out");
} else if (msg_for_me == "Preset")
{
Log.i(MainActivity.TAG, "Preset");
}
}
private void showToast(String message) {
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
}
}
Phone Android Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.schoen.jonathan.airliftwatch">
<uses-permission android:name="android.permission.WAKE_LOCK" />
<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">
<meta-data android:name="com.google.android.gms.version" android:value="#integer/google_play_services_version" />
<service
android:name="com.schoen.jonathan.airliftwatch.ListenerService" >
<intent-filter>
<action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
</intent-filter>
</service>
<meta-data android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Phone wear.xml:
<resources>
<string-array name="android_wear_capabilities">
<item>airlift</item>
</string-array>
</resources>
Any ideas why I get null result for returned nodes? my phone and watch are currently paired and i get updates on my watch from my phone from things like facebook and emails.
As stated in this thread, NodeApi can be used on the device side.
NodeApi.GetConnectedNodesResult nodes =
Wearable.NodeApi.getConnectedNodes(mApiClient).await();
Then for each node within nodes, you can call getDisplayName().
Also, based from this link, use the same debug certificate for both the handheld and wearable app, otherwise the CapabilityAPI won't work.
my server is sending the message to the gcm serer with a response code of 200. but my OnMessageReceiver is not getting called therefore im not getting the message.
public class MyGcmListenerService extends GcmListenerService {
private static final String TAG = "MyGcmListenerService";
private static int no_calls;
#Override
public void onMessageReceived (String from, Bundle data){
String message = data.getString("message");
Log.d(TAG, "From: " + from);
Log.d(TAG, "Message: " + message);
out.println("print something");
System.out.println("Message" + message + "from" + from);
sendNotification(message);
}
private void sendNotification(String message) {
System.out.println("Message" + message + "from");
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_setting_dark)
.setContentTitle("GCM Message")
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.caesar.gcm" >
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="21"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission android:name="com.example.caesar.gcm.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.example.caesar.gcm.permission.C2D_MESSAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="com.example.gcm.permission.C2D_MESSAGE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<reciever
android:name = "com.google.android.gms.gcm.GcmReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE"/>
<category android:name="com.example.caesar.gcm" />
</intent-filter>
</reciever>
<service
android:name=".MyGcmListenerService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
</application>
</manifest>
public class MainActivity extends Activity {
GoogleCloudMessaging gcm;
String regid;
TextView mDisplay;
TextView textView;
String SENDER_ID = "";
public static final String EXTRA_MESSAGE = "message";
public static final String PROPERTY_REG_ID = "registration_id";
private static final String PROPERTY_APP_VERSION = "appVersion";
Context context;
AsyncHttpClient client = new AsyncHttpClient();
static final String TAG = "GCMDemo";
String mess = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDisplay = (TextView) findViewById(R.id.display);
textView = (TextView) findViewById(R.id.textView);
context = getApplicationContext();
// GCM registration.
if (checkPlayServices()) {
gcm = GoogleCloudMessaging.getInstance(this);
regid = getRegistrationId(context);
textView.setText(regid);
SendID();
if (regid.isEmpty()) {
registerInBackground();
}
} else {
Log.i(TAG, "No valid Google Play Services APK found.");
}
}
public void SendID(){
final RequestParams params = new RequestParams();
params.put("id", regid);
client.post("", params, new JsonHttpResponseHandler() {
#Override
public void onStart() {
// called before request is started
}
public void onSuccess(int statusCode, PreferenceActivity.Header[] headers, JSONObject response) {
}
public void onFailure(int statusCode, PreferenceActivity.Header[] headers, JSONObject errorResponse, Throwable e) {
// called when response HTTP status is "4XX" (eg. 401, 403, 404)
}
#Override
public void onRetry(int retryNo) {
// called when request is retried
}
});
}
private boolean checkPlayServices() {
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (status != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(status)) {
Log.i(TAG, String.valueOf(status));
} else {
Toast.makeText(this, "This device is not supported.",
Toast.LENGTH_LONG).show();
finish();
}
return false;
}
return true;
}
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;
// You should send the registration ID to your server over HTTP,
// so it can use GCM/HTTP or CCS to send messages to your app.
// The request to your server should be authenticated if your app
// is using accounts.
sendRegistrationIdToBackend();
// For this demo: we don't need to send it because the device
// will send upstream messages to a server that echo back the
// message using the 'from' address in the message.
// Persist the registration ID - no need to register again.
storeRegistrationId(context, regid);
} catch (IOException ex) {
msg = "Error :" + ex.getMessage();
// If there is an error, don't just keep trying to register.
// Require the user to click a button again, or perform
// exponential back-off.
}
return msg;
}
private void storeRegistrationId(Context context, String regId) {
final SharedPreferences prefs = getGCMPreferences(context);
int appVersion = getAppVersion(context);
Log.i(TAG, "Saving regId on app version " + appVersion);
SharedPreferences.Editor editor = prefs.edit();
editor.putString(PROPERTY_REG_ID, regId);
editor.putInt(PROPERTY_APP_VERSION, appVersion);
editor.commit();
}
#Override
protected void onPostExecute(String msg) {
mDisplay.append(msg + "\n");
}
}.execute(null, null, null);
}
private void sendRegistrationIdToBackend() {
// Your implementation here.
}
private String getRegistrationId(Context context) {
final SharedPreferences prefs = getGCMPreferences(context);
String registrationId = prefs.getString(PROPERTY_REG_ID, "");
if (registrationId.isEmpty()) {
Log.i(TAG, "Registration not found.");
return "";
}
// Check if app was updated; if so, it must clear the registration ID
// since the existing registration ID is not guaranteed to work with
// the new app version.
int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);
int currentVersion = getAppVersion(context);
if (registeredVersion != currentVersion) {
Log.i(TAG, "App version changed.");
return "";
}
return registrationId;
}
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) {
// This sample app persists the registration ID in shared preferences, but
// how you store the registration ID in your app is up to you.
return getSharedPreferences(Activity.class.getSimpleName(),
Context.MODE_PRIVATE);
}
}
//updated main
public class MainActivity extends Activity {
GoogleCloudMessaging gcm;
TextView mDisplay;
TextView textView;
public static final String EXTRA_MESSAGE = "message";
public static final String PROPERTY_REG_ID = "registration_id";
private static final String PROPERTY_APP_VERSION = "appVersion";
Context context;
AsyncHttpClient client = new AsyncHttpClient();
static final String TAG = "GCMDemo";
Context mContext = this;
String mess = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDisplay = (TextView) findViewById(R.id.display);
textView = (TextView) findViewById(R.id.textView);
SharedPreferences appPrefs = mContext.getSharedPreferences("com.example.caesar.gcm", Context.MODE_PRIVATE);
String token = appPrefs.getString("token", "");
if (token.isEmpty()) {
try {
getGCMToken("1048700326431");// Project ID: xxxx Project Number: 0123456789 at https://console.developers.google.com/project/...
textView.setText(token);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
private void getGCMToken(final String senderId) throws Exception {
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
String token = "";
try {
InstanceID instanceID = InstanceID.getInstance(mContext);
token = instanceID.getToken(senderId, GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
if (token != null && !token.isEmpty()) {
SharedPreferences appPrefs = mContext.getSharedPreferences("com.example.caesar.gcm", Context.MODE_PRIVATE);
SharedPreferences.Editor prefsEditor = appPrefs.edit();
prefsEditor.putString("token", token);
prefsEditor.apply();
}
Log.i("GCM_Token", token);
textView.setText(token);
SendID(token);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}.execute();
}
public void SendID(String token){
final RequestParams params = new RequestParams();
params.put("id", token);
client.post("https://death-sarodh.c9.io/gcm", params, new JsonHttpResponseHandler() {
#Override
public void onStart() {
// called before request is started
}
public void onSuccess(int statusCode, PreferenceActivity.Header[] headers, JSONObject response) {
}
public void onFailure(int statusCode, PreferenceActivity.Header[] headers, JSONObject errorResponse, Throwable e) {
// called when response HTTP status is "4XX" (eg. 401, 403, 404)
}
#Override
public void onRetry(int retryNo) {
// called when request is retried
}
});
}
}
Replace reciever in your Manifest by receiver.
Moreover, make sure your app successfully got the token (registration device Id). Hope this helps!
My Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.gcmclient" >
<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="com.google.android.c2dm.permission.RECEIVE" />
<permission android:name="com.example.gcm.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.example.gcm.permission.C2D_MESSAGE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<receiver
android:name="com.google.android.gms.gcm.GcmReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.example.gcm" />
</intent-filter>
</receiver>
<service android:name=".service.GcmService" android:exported="false">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
<service android:name=".service.LoggingService" android:exported="false" />
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:clearTaskOnLaunch="false"
android:finishOnTaskLaunch="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Moreover, check your sever-side response after sending. Perhaps you will get response message like the following if GCM message sucessfully sent:
{"multicast_id":6371085842931382567,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1240780242421810%4c427ca6f9fd7ecd"}]}
About getting token, firstly, I check SharedPreferences, if empty, get token (device registration id) from Google server. Token will be stored in SharedPreferences for other use / providing to server-side app.
public class MainActivity extends Activity {
Context mContext = this;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
SharedPreferences appPrefs = mContext.getSharedPreferences("com.example.gcmclient_preferences", Context.MODE_PRIVATE);
String token = appPrefs.getString("token", "");
if (token.isEmpty()) {
try {
getGCMToken("0123456789"); // Project ID: xxxx Project Number: 0123456789 at https://console.developers.google.com/project/...
} catch (Exception ex) {
ex.printStackTrace();
}
}
...
}
...
private void getGCMToken(final String senderId) throws Exception {
new AsyncTask<Void, Void, Void>() {
#Override
protected String doInBackground(Void... params) {
String token = "";
try {
InstanceID instanceID = InstanceID.getInstance(mContext);
token = instanceID.getToken(senderId, GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
if (token != null && !token.isEmpty()) {
SharedPreferences appPrefs = mContext.getSharedPreferences("com.example.gcmclient_preferences", Context.MODE_PRIVATE);
SharedPreferences.Editor prefsEditor = appPrefs.edit();
prefsEditor.putString("token", token);
prefsEditor.commit();
}
Log.i("GCM_Token", token);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}.execute();
}
}
Change this line
android:name=".MyGcmListenerService"
instead of above line
android:name="your package.MyGcmListenerService"
example com.yourappname.gcm.GcmIntentService
<service
android:name=".MyGcmListenerService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
simple example code for BroadCastReceiver.
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);
}
}
IntentService
public class GcmIntentService extends IntentService {
#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 Bundles
/*
* 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)) {
Log.e(":::gcm message",extras.getString("key");
}
}
// Release the wake lock provided by the WakefulBroadcastReceiver.
GcmBroadcastReceiver.completeWakefulIntent(intent);
}
}
Remove below line from your manifest
<permission android:name="com.example.caesar.gcm.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
Manifest
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission
android:name="com.example.gcm.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.example.gcm.permission.C2D_MESSAGE" />
<receiver
android:name="com.yourappname.gcm.GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.example.gcm" />
</intent-filter>
</receiver>
<service android:name="com.yourappname.gcm.GcmIntentService" />