I am developing an android app that requires a foreground service to sync data over bluetooth with computers. The foreground service works perfectly during the session where it is first run by the app. However, if I restart my phone, the service will not restart upon reboot, despite me returning START_STICKY within the onStartCommand function. I want it to start as soon as possible upon reboot just like my VPN does. How can I achieve this functionality?
Here is the code in question:
package com.example.app;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.os.IBinder;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Set;
import static com.example.app.App.CONNECTED_DEVICES_CHANNEL_ID;
public class BluetoothSyncService extends Service {
private Utils utils;
private final BluetoothAdapter BLUETOOTH_ADAPTER = BluetoothAdapter.getDefaultAdapter();
private final String CONNECTED_PC_GROUP = "connectedPCS";
private final ArrayList<String> NOTIFIED_PC_ADDRESSES = new ArrayList<>();
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
utils = Utils.getInstance(this);
NotificationCompat.Builder summaryNotificationBuilder =
new NotificationCompat.Builder(this,
CONNECTED_DEVICES_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_placeholder_logo)
.setContentTitle("Sync Service Background")
.setGroup(CONNECTED_PC_GROUP)
.setGroupSummary(true)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setOngoing(true);
int SUMMARY_NOTIFICATION_ID = 69;
startForeground(SUMMARY_NOTIFICATION_ID, summaryNotificationBuilder.build());
Thread serviceThread = new Thread(() -> {
while (true) {
handleConnectedDevices();
handleNotifications();
}
});
serviceThread.start();
return START_STICKY;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
private void handleConnectedDevices() {
Set<BluetoothDevice> pairedDevices = BLUETOOTH_ADAPTER.getBondedDevices();
// Handle connected PCS
for (BluetoothDevice device : pairedDevices) {
if (isConnected(device.getAddress())) {
int deviceClass = device.getBluetoothClass().getDeviceClass();
if (deviceClass == BluetoothClass.Device.COMPUTER_LAPTOP |
deviceClass == BluetoothClass.Device.COMPUTER_DESKTOP) {
if (!utils.inPairedPCS(device.getAddress())) {
utils.addToPairedPCS(new PairedPC(device.getName(),
device.getAddress(), true));
} else {
if (utils.getPairedPCByAddress(device.getAddress()) != null) {
utils.getPairedPCByAddress(device.getAddress()).setConnected(true);
utils.savePairedPCSToDevice();
}
}
}
} else {
if (utils.inPairedPCS(device.getAddress())) {
if (utils.getPairedPCByAddress(device.getAddress()) != null) {
utils.getPairedPCByAddress(device.getAddress()).setConnected(false);
utils.savePairedPCSToDevice();
}
}
}
}
}
private void handleNotifications() {
NotificationManagerCompat notificationManager = NotificationManagerCompat
.from(this);
for (PairedPC pairedPC : utils.getPairedPCS()) {
int CONNECTION_NOTIFICATION_ID = 420;
if (pairedPC.isConnected()) {
if (pairedPC.isActive() && !NOTIFIED_PC_ADDRESSES.contains(pairedPC.getAddress())) {
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(
this, CONNECTED_DEVICES_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_pc)
.setContentTitle("Syncing PC")
.setContentText(pairedPC.getName())
.setGroup(CONNECTED_PC_GROUP)
.setPriority(NotificationCompat.PRIORITY_MIN)
.setOngoing(true);
notificationManager.notify(pairedPC.getAddress(),
CONNECTION_NOTIFICATION_ID, notificationBuilder.build());
NOTIFIED_PC_ADDRESSES.add(pairedPC.getAddress());
} else if (!pairedPC.isActive()) {
notificationManager.cancel(pairedPC.getAddress(), CONNECTION_NOTIFICATION_ID);
NOTIFIED_PC_ADDRESSES.remove(pairedPC.getAddress());
}
} else {
if (NOTIFIED_PC_ADDRESSES.contains(pairedPC.getAddress())) {
notificationManager.cancel(pairedPC.getAddress(), CONNECTION_NOTIFICATION_ID);
NOTIFIED_PC_ADDRESSES.remove(pairedPC.getAddress());
}
}
}
}
private boolean isConnected(String address) {
Set<BluetoothDevice> pairedDevices = BLUETOOTH_ADAPTER.getBondedDevices();
for (BluetoothDevice device : pairedDevices) {
if (device.getAddress().equals(address)) {
Method method = null;
try {
method = device.getClass().getMethod("isConnected", (Class[]) null);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
boolean connected = false;
try {
assert method != null;
Object methodInvocation = method.invoke(device, (Object[]) null);
if (methodInvocation != null) {
connected = (boolean) methodInvocation;
} else {
connected = false;
}
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return connected;
}
}
return false;
}
}
EDIT:
So I have tried using a broadcast receiver as suggested. Yet it is still not working. Here is the code for the receiver:
package com.example.app;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class BootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
Intent syncServiceIntent = new Intent(context, BluetoothSyncService.class);
context.startService(syncServiceIntent);
}
}
}
And here is my manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.app">
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<application
android:allowBackup="false"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:name=".App"
android:theme="#style/Theme.App">
<receiver android:name=".BootReceiver" android:enabled="true" android:exported="true">
<intent-filter>
<category android:name="android.intent.category.DEFAULT"/>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.QUICKBOOT_POWERON"/>
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
</intent-filter>
</receiver>
<activity android:name=".PermissionsActivity" />
<activity android:name=".MainActivity" />
<activity android:name=".StartupActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".BluetoothSyncService"/>
</application>
</manifest>
EDIT 2:
SOLVED! Had to change context.startService(syncServiceIntent); to context.startForegroundService(syncServiceIntent);
Related
I want that each time that the user unlock his phone my app automatically do a socket connection in background to see if the user had receive a message, and if yes show a notification.
the code to do a socket connection and do a notification works in the MainActivity class but I could find out to make that the android device execute the code in the UserPresentBroadcastReceiver class automatically even if the app has not been open.
android 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"
package="com.example.notification">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<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/Theme.Notification">
<receiver android:name=".UserPresentBroadcastReceiver" >
<intent-filter>
<category android:name="android.intent.category.DEFAULT"/>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.QUICKBOOT_POWERON"/>
<!--For HTC devices-->
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
</intent-filter>
</receiver>
<service android:name="UserPresentBroadcastReceiver" >
</service>
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
and the UserPresentBroadcastReceiver class
package com.example.notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
import androidx.core.app.NotificationCompat;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class UserPresentBroadcastReceiver extends BroadcastReceiver {
private Socket client;
private PrintWriter printwriter;
private String message_sortant;
private BufferedReader in_bufferedReader;
private String message_entrant;
private InputStreamReader in_streamReader;
#Override
public void onReceive(Context arg0, Intent intent) {
/*Sent when the user is present after
* device wakes up (e.g when the keyguard is gone)
* */
if(intent.getAction().equals(Intent.ACTION_USER_PRESENT)){
while(true) {
try {
//Log.d("Connexion","Demande de connexion");
Socket client = new Socket("192.168.1.13", 1580);// connect to the server
////// ENVOIE D'UN MESSAGE SORTANT ///////
Log.d("Connexion", "Envoie de A");
printwriter = new PrintWriter(client.getOutputStream(), true);
printwriter.write("<meet>/notification/"); // write the message to output stream
printwriter.flush();
in_bufferedReader = new BufferedReader(new InputStreamReader(client.getInputStream()));
message_entrant = in_bufferedReader.readLine();
client.close();
} catch (Exception e) {
}
NotificationManager mNotificationManager =
(NotificationManager) arg0.getSystemService(Context.NOTIFICATION_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel("YOUR_CHANNEL_ID",
"YOUR_CHANNEL_NAME",
NotificationManager.IMPORTANCE_DEFAULT);
channel.setDescription("YOUR_NOTIFICATION_CHANNEL_DESCRIPTION");
mNotificationManager.createNotificationChannel(channel);
}
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(arg0.getApplicationContext(), "YOUR_CHANNEL_ID")
.setSmallIcon(R.mipmap.ic_launcher) // notification icon
.setContentTitle("hello") // title for notification
.setContentText(String.valueOf(message_entrant))// message for notification
.setAutoCancel(true); // clear notification after click
intent = new Intent(arg0.getApplicationContext(), MainActivity.class);
PendingIntent pi = PendingIntent.getActivity(arg0, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(pi);
mNotificationManager.notify(0, mBuilder.build());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/*Device is shutting down. This is broadcast when the device
* is being shut down (completely turned off, not sleeping)
* */
else if (intent.getAction().equals(Intent.ACTION_SHUTDOWN)) {
}
}
}
Thanks for helping.
I notice that they change something with android Oreo but I couldn't find out how to fix it.
I'm trying to implement an app that allows me to record the audio of calls, activating the service via a toggle button. I can't figure out what is wrong with my code as once I set the toggle button to ON and initiate the call, there is no file saved.
I don't understand if the problem is in saving (maybe I'm looking for the file in the wrong directory?), Or in the fact that it doesn't actually record.
I'm using AndroidStudio 4.0 and i'm trying my app on my Samsung S9.
Thanks in andvance for helping !
RecordService.java
package com.example.registrachiamate;
import android.app.MediaRouteButton;
import android.app.Service;
import android.content.Intent;
import android.media.MediaRecorder;
import android.os.Environment;
import android.os.IBinder;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.text.format.DateFormat;
import java.io.File;
import java.io.IOException;
import java.util.Date;
public class RecordService extends Service {
private MediaRecorder rec;
private File file;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//return super.onStartCommand(intent, flags, startId);
file= Environment.getExternalStorageDirectory();
Date date=new Date();
CharSequence sdf= DateFormat.format("MM-dd-yy-hh-mm--ss",date.getTime());
rec=new MediaRecorder();
rec.setAudioSource(MediaRecorder.AudioSource.MIC);
rec.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
rec.setOutputFile(file.getAbsolutePath()+"/"+sdf+"rec.3gp");
rec.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
TelephonyManager manager=(TelephonyManager) getApplicationContext().getSystemService(getApplicationContext().TELEPHONY_SERVICE);
assert manager != null;
manager.listen(new PhoneStateListener(){
#Override
public void onCallStateChanged(int state, String phoneNumber) {
//super.onCallStateChanged(state, phoneNumber) {
if (TelephonyManager.CALL_STATE_IDLE==state){
rec.stop();
rec.reset();
rec.release();
stopSelf();
}else if(TelephonyManager.CALL_STATE_OFFHOOK==state && rec==null){
try {
rec.prepare();
} catch (IOException e) {
e.printStackTrace();
}
rec.start();
}
}
},PhoneStateListener.LISTEN_CALL_STATE);
return START_STICKY;
}
}
ActivityButton1.java
package com.example.registrachiamate;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import android.widget.ToggleButton;
import androidx.appcompat.app.AppCompatActivity;
public class ActivityButton1 extends AppCompatActivity {
ToggleButton startandoff;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.button1);
startandoff=(ToggleButton)findViewById(R.id.toggleButton);
}
public void tooglebutton(View view)
{
boolean checked=((ToggleButton)view).isChecked();
if (checked){
Intent intent=new Intent(this,RecordService.class);
startService(intent);
Toast.makeText(getApplicationContext(),"Call Record STARTED",Toast.LENGTH_SHORT).show();
}else {
Intent intent=new Intent(this,RecordService.class);
stopService(intent);
Toast.makeText(getApplicationContext(),"Call Record STOPPED",Toast.LENGTH_SHORT).show();
}
}
}
AndroidManifest.xml, if i put the RecordService, in it stops running
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.registrachiamate">
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<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"
tools:ignore="GoogleAppIndexingWarning">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
<action android:name="android.intent.action.PHONE_STATE"/>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ActivityButton1"></activity>
<activity android:name=".ActivityButton2"></activity>
<activity android:name=".ActivityButton3"></activity>
<activity android:name=".ActivityButton4"></activity>
<activity android:name=".RecordService"></activity>
</application>
</manifest>
I want to send data from my Wear to the PhoneApp. I created a phone app with this AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="sh.evolutio.car">
<uses-feature
android:name="android.software.leanback"
android:required="true" />
<application
android:allowBackup="false"
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=".services.ListenerService" >
<intent-filter>
<action android:name="com.google.android.gms.wearable.MESSAGE_RECEIVED" />
<action android:name="com.google.android.gms.wearable.DATA_CHANGED" />
<!-- <data android:scheme="wear" android:host="*" android:pathPrefix="/updatecar" /> -->
</intent-filter>
</service>
<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" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
my ListenerService:
package sh.evolutio.car.services;
import android.content.Intent;
import android.util.Log;
import com.google.android.gms.wearable.MessageEvent;
import com.google.android.gms.wearable.WearableListenerService;
public class ListenerService extends WearableListenerService {
private static final String TAG = "ListenerService";
private static final String MESSAGE_PATH = "/updatecar";
#Override
public void onCreate() {
Log.d(TAG, "ListenerService created");
}
#Override
public void onMessageReceived(MessageEvent messageEvent) {
Log.d(TAG, "onMessageReceived");
if (messageEvent.getPath().equals(MESSAGE_PATH)) {
Log.d(TAG, "good message");
} else {
Log.d(TAG, "bad message");
}
}
}
my MainActivity with this onCreate:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
startService(new Intent(MainActivity.this, ListenerService.class));
}
When I start the App on my phone I got in the Logcat:
26131-26131/sh.evolutio.car D/ListenerService: ListenerService created
When I send with the wearapp some data to my phone, my ListenerService didn't fire the onMessageReceived method..
Here is my AndroidManifest from the wearapp:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="sh.evolutio.carwear">
<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.wearable.standalone"
android:value="false" />
<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>
</application>
</manifest>
The MainActivity from the wearapp looks like this:
package sh.evolutio.carwear;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.wearable.activity.WearableActivity;
import android.util.Log;
import android.view.View;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.android.gms.wearable.MessageApi;
import com.google.android.gms.wearable.Node;
import com.google.android.gms.wearable.NodeApi;
import com.google.android.gms.wearable.Wearable;
public class MainActivity extends WearableActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private static String TAG = "MainActivity";
private static final String MESSAGE_PATH = "/updatecar";
Node mNode; // the connected device to send the message to
GoogleApiClient mGoogleApiClient;
private boolean mResolvingError = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Connect the GoogleApiClient
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Wearable.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
sendMessage("test");
// Enables Always-on
setAmbientEnabled();
}
#Override
protected void onStart() {
super.onStart();
if (!mResolvingError) {
mGoogleApiClient.connect();
}
}
/**
* Resolve the node = the connected device to send the message to
*/
private void resolveNode() {
Log.d(TAG, "resolveNode");
Wearable.NodeApi.getConnectedNodes(mGoogleApiClient)
.setResultCallback(new ResultCallback<NodeApi.GetConnectedNodesResult>() {
#Override
public void onResult(NodeApi.GetConnectedNodesResult nodes) {
for (Node node : nodes.getNodes()) {
Log.d(TAG, "resolvedNode: " + node);
mNode = node;
}
}
});
}
#Override
public void onConnected(Bundle bundle) {
resolveNode();
}
#Override
public void onConnectionSuspended(int i) {}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d(TAG, "connectionResult: " + connectionResult);
}
/**
* Send message to mobile handheld
*/
private void sendMessage(String Key) {
if (mNode != null && mGoogleApiClient!= null && mGoogleApiClient.isConnected()) {
final String messageKey = Key;
Log.d(TAG, "isConnected: " + mGoogleApiClient.isConnected());
Log.d(TAG, "connected to: " + mNode.getId());
Task<Integer> sendTask = Wearable.getMessageClient(MainActivity.this).sendMessage(mNode.getId(), MESSAGE_PATH, messageKey.getBytes());
sendTask.addOnSuccessListener(new OnSuccessListener<Integer>() {
#Override
public void onSuccess(Integer integer) {
Log.d(TAG, "onSuccess: " + integer);
}
});
sendTask.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.d(TAG, "onFailure: " + e.getMessage());
}
});
Wearable.MessageApi.sendMessage(mGoogleApiClient, mNode.getId(), MESSAGE_PATH, messageKey.getBytes()).setResultCallback(
new ResultCallback<MessageApi.SendMessageResult>() {
#Override
public void onResult(#NonNull MessageApi.SendMessageResult sendMessageResult) {
if (sendMessageResult.getStatus().isSuccess()) {
Log.v(TAG, "Message: { " + messageKey + " } sent to: " + mNode.getDisplayName());
} else {
// Log an error
Log.v(TAG, "ERROR: failed to send Message");
}
}
}
);
}
}
}
When I the message got send, i got this in the logcat from the wearapp:
sh.evolutio.carwear D/MainActivity: isConnected: true
sh.evolutio.carwear D/MainActivity: connected to: 778d0d53
sh.evolutio.carwear V/MainActivity: Message: { forward } sent to: HUAWEI Mate 10 Pro
sh.evolutio.carwear D/MainActivity: onSuccess: 17282
so the message was sent to my Mate 10 Pro. But why my Mate 10 Pro App can't receive the Message? Where is my mistake? I didn't find it.
In your mobile activity, do not start the service manually.
The service will be started automatically by Android on reception of the message.
And you need to uncomment your data pathPrefix definition in the AndroidManifest.
I am new to android stack. I am trying to start android service from the launcher activity. Service and Activity are defined in separate packages but it is not being started. In the logcat there is no exception or error. I have checked many questions on stackoverflow regarding this issue but that didn't worked. Below are the source code of my app. I have spent almost 8 hours on this issue. Any help would be great appreciation.
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="nl.test.app">
<supports-screens
android:anyDensity="true"
android:largeScreens="true"
android:normalScreens="true"
android:resizeable="true"
android:smallScreens="true"
android:xlargeScreens="true" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".ui.LoginActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".messaging.AlertService"
android:enabled="true"
android:exported="true">
</service>
</application>
</manifest>
AlertService.java:
package nl.test.app.messaging;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;
public class AlertService extends Service {
public AlertService() {
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(getApplicationContext(), "on create called\n", Toast.LENGTH_LONG).show();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
}
LoginActivity.java
package nl.test.app.ui;
import android.content.ComponentName;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.Toast;
import nl.test.app.R;
public class LoginActivity extends AppCompatActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
}
// function for service testing
public void onStartButtonClick(View view) {
Intent myIntentToStartAlertListActivity = new Intent();
String pkg = "nl.test.app.messaging";
String cls = "nl.test.app.messaging.AlertService";
myIntentToStartAlertListActivity.setComponent(new ComponentName(pkg, cls));
if (startService(myIntentToStartAlertListActivity) != null) {
Log.i("Service Started","Service started");
Toast.makeText(getApplicationContext(), "Service is running\n", Toast.LENGTH_LONG).show();
}
else {
Toast.makeText(getApplicationContext(), "Service is not running\n", Toast.LENGTH_LONG).show();
}
}
#Override
protected void onStop() {
super.onStop();
}
}
Try this
public void onStartButtonClick(View view) {
Intent myIntentToStartAlertListActivity = new Intent(LoginActivity.this, AlertService.class);
if (startService(myIntentToStartAlertListActivity) != null) {
Log.i("Service Started","Service started");
Toast.makeText(getApplicationContext(), "Service is running\n", Toast.LENGTH_LONG).show();
}
else {
Toast.makeText(getApplicationContext(), "Service is not running\n", Toast.LENGTH_LONG).show();
}
}
// function for service testing
public void onStartButtonClick(View view) {
Intent myIntentToStartAlertListActivity = new Intent(LoginActivity.this,AlertService.class);
String pkg = "nl.test.app.messaging";
String cls = "nl.test.app.messaging.AlertService";
myIntentToStartAlertListActivity.setComponent(new ComponentName(pkg, cls));
//startService(myIntentToStartAlertListActivity)
if (startService(myIntentToStartAlertListActivity) != null) {
Log.i("Service Started","Service started");
Toast.makeText(getApplicationContext(), "Service is running\n", Toast.LENGTH_LONG).show();
}
else {
Toast.makeText(getApplicationContext(), "Service is not running\n", Toast.LENGTH_LONG).show();
}
}
My app was working fine and was receiving push notifications, today I added some new layout and also change some other activity. But Now the app is not receiving any push notifications. I installed the old apk and tested, and still its not receiving any Push notifications.
So, Registered the device again with new IDs, and when i checked the Gcm manifest its shows :
{"multicast_id":7626883831612562770,"success":2,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1410175055111515%ae2db952f9fd7ecd"},{"message_id":"0:1410175055111884%ae2db952f9fd7ecd"}]}
Both are newly registered ID's, but its still not working.
LogCat for the App :
09-08 16:44:58.360 7151-7244/in.wirefreeworld.wfw D/111﹕ Device registered, registration ID=APA91bF3BhiliA8Xrtkh7HfUSHlpq9UrkhbAkIPY_poWjWBcAlgnIkF2Hbd38KakR43fucTxfHOcCH4zfyLEd7Q2uLRZIupMD-erk4gUoSpX2rk1YbMIDHLIZ7cFopHUdJ8ocLQM4X2hDajLml0vJVvp4M9hodKecw
09-08 16:44:58.490 7151-7172/in.wirefreeworld.wfw D/dalvikvm﹕ GC_FOR_ALLOC freed 1322K, 8% free 15664K/17016K, paused 23ms, total 25ms
09-08 16:44:58.880 7151-7151/in.wirefreeworld.wfw D/Volley﹕ [1] 4.onResponse: MainActivity
GcmBroadcastReceiver.java Class
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.support.v4.content.WakefulBroadcastReceiver;
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
ComponentName comp = new ComponentName(context.getPackageName(),
GCMNotificationIntentService.class.getName());
startWakefulService(context, (intent.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
}
}
GCMNotificationIntentService.java
import android.app.IntentService;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.SystemClock;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import com.google.android.gms.gcm.GoogleCloudMessaging;
public class GCMNotificationIntentService extends IntentService {
public static final int NOTIFICATION_ID = 1;
private NotificationManager mNotificationManager;
NotificationCompat.Builder builder;
public GCMNotificationIntentService() {
super("GcmIntentService");
}
public static final String TAG = "GCMNotificationIntentService";
#Override
protected void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
String messageType = gcm.getMessageType(intent);
if (!extras.isEmpty()) {
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());
} else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE
.equals(messageType)) {
for (int i = 0; i < 3; i++) {
Log.i(TAG,
"Working... " + (i + 1) + "/5 # "
+ SystemClock.elapsedRealtime());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
}
Log.i(TAG, "Completed work # " + SystemClock.elapsedRealtime());
sendNotification("New Product: "
+ extras.get(Config.MESSAGE_KEY));
Log.i(TAG, "Received: " + extras.toString());
}
}
GcmBroadcastReceiver.completeWakefulIntent(intent);
}
private void sendNotification(String msg) {
Log.d(TAG, "Preparing to send notification...: " + msg);
mNotificationManager = (NotificationManager) this
.getSystemService(Context.NOTIFICATION_SERVICE);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, MainActivity.class), 0);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
this).setSmallIcon(R.drawable.ic_notif);
mBuilder.setTicker("Wire Free World");
mBuilder.setContentTitle("Wire Free World");
mBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(msg));
mBuilder.setContentText(msg);
long[] pattern = {500,500,500,500,500,500,500,500,500};
mBuilder.setVibrate(pattern);
Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
if(alarmSound == null){
alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
}
mBuilder.setSound(alarmSound);
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "TAG");
wl.acquire(5000);
mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
Log.d(TAG, "Notification sent successfully.");
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="info.androidhive.listviewfeed"
android:versionCode="3"
android:versionName="1.2" >
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<permission
android:name="info.androidhive.listviewfeed.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="info.androidhive.listviewfeed.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.VIBRATE" />
<application
android:name=".app.AppController"
android:allowBackup="true"
android:icon="#drawable/ic_notif"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<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>
<activity
android:name=".product"
android:label="#string/title_activity_product"
android:parentActivityName=".MainActivity" >
</activity>
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<activity
android:name=".Register"
android:label="#string/title_activity_register"
android:theme="#style/Theme.AppCompat">
</activity>
<receiver
android:name=".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="info.androidhive.listviewfeed" />
</intent-filter>
</receiver>
<service android:name=".GCMNotificationIntentService" />
</application>
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
</manifest>