I'm trying to active my service with StartService(), and it should go next to the onStartCommand() function, but it doesn't.
I tried many ways to not use the onStartCommand() function, but I need the information from the Intent in my service.
Here is the code:
MainAcitivty - OnCreate:
dbHelper = new DBHelper(this);
listTasks = (ListView)findViewById(R.id.list_todo);
loadTaskList();
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG).setAction("Action", null).show();
eventIntent = new Intent(view.getContext(), NewEventActivity.class);
startActivityForResult(eventIntent, ADD_EVENT_REQUEST);
}
});
Intent serviceIntent = new Intent(this, MyService.class);
serviceIntent.putExtra("dbHelper", (Parcelable)dbHelper);
if (!isMyServiceRunning(MyService.class))
{
startService(serviceIntent);
}
}
//gets any service class and check if its alive (running)
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
MyService:
DBHelper dbHelper;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
startServiceThread();
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Bundle extras = intent.getExtras();
if (extras != null) {
dbHelper = (DBHelper)extras.get("dbHelper");
}
return super.onStartCommand(intent, flags, startId);
}
Manifest:
(Here i also tried to add the service just with name=".MyService", but it did not change anything)
<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"
android:name=".MyApplication">
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
</activity>
<activity android:name=".NewEventActivity" />
<activity android:name=".LockApp">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="com.example.user.project.MyService" />
</application>
It is crash in startServiceThread() because it can't get the information from the intent
Then perhaps you should not be starting the thread until onStartCommand().
Anyway, the onStartCommand() does not calls after the startService()
That is because you are crashing on onCreate(). Stop crashing in onCreate(), and you should have better luck with onStartCommand().
Related
I want to have an app that do s.th in specific time even phone is on sleep mode. I used these code but receiver dosent work correctly. The Log just show some times. for example every two or three minute Log showed. what should I do that app work when time changed on phone.
I also tried wakeLock and alertManager class but nothing changed.
public class MyService extends Service {
private static final String CHANNEL_ID = "1";
private static final int NOTIFICATION_ID = 1;
private static final CharSequence CHANNEL_NAME = "channel name";
private TimeChange timeChange;
private CharSequence notificationContent = "hi";
private NotificationManager manager;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
createNotification();
startNotification();
timeChange = new TimeChange();
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
filter.addAction(Intent.ACTION_TIME_TICK);
registerReceiver(timeChange, filter);
return START_STICKY;
}
public class TimeChange extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
Log.d("4040", "hi");
}
}
private void startNotification() {
// run activity when notification clicked
Intent mainActivity = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0,
mainActivity, PendingIntent.FLAG_UPDATE_CURRENT);
// show notification
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentText(notificationContent)
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentIntent(pendingIntent)
.build();
startForeground(NOTIFICATION_ID, notification);
}
private void createNotification() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(CHANNEL_ID , CHANNEL_NAME,
NotificationManager.IMPORTANCE_HIGH);
manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel);
}
}
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(timeChange);
}
}
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent serVice = new Intent(MainActivity.this, MyService.class);
ContextCompat.startForegroundService(this, serVice);
}
}
<?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.android.prj.myapplication">
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
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_round"
android:supportsRtl="true"
android:theme="#style/Theme.MyApplication"
tools:targetApi="31">
<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>
<service android:name=".MyService"
android:enabled="true"
android:exported="true"/>
<receiver android:name=".MyService$TimeChange"
android:enabled="true"
android:exported="true"
tools:ignore="Instantiatable" />
</application>
</manifest>
I am trying to send string from app to app.
First app called "send" has only "MainActivity" class and layout:
private void sendMsg(){
final TextView msg = (TextView) findViewById(R.id.sendText);
Button snd = (Button)findViewById(R.id.sendButton);
snd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(!msg.getText().toString().trim().equals("")){
Intent intent = new Intent("Updated");
intent.setAction(Intent.ACTION_SEND);
intent.putExtra("TEXT", msg.getText().toString().trim());
intent.setType("text/plain");
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
intent.setComponent(new ComponentName("com.example.rec","com.example.rec.broadcastReciver"));
getApplicationContext().sendBroadcast(intent);
}else{
Toast.makeText(getApplicationContext(), "Write text that You want to broadcast!", Toast.LENGTH_LONG).show();
}
}
});
}
Second app called "rec" has two classes "broadcastReciver" and "MainActivity".
MainActivity:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
zoviBroadCast();
}
private void zoviBroadCast(){
broadcastReciver brcv = new broadcastReciver();
registerReceiver(brcv,
new IntentFilter("action"));
}
}
broadcastReciver:
public class broadcastReciver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent)
{
//String data = intent.getStringExtra("TEXT").trim();
if (intent != null)
{
String sIntentAction = intent.getAction();
if (sIntentAction != null && sIntentAction.equals("action"))
{
String data = intent.getStringExtra("TEXT").trim();
Toast.makeText(context, data, Toast.LENGTH_LONG).show();
}
else {
Toast.makeText(context,"Something went wrong",Toast.LENGTH_SHORT).show();
}
}
}
}
I also added lines between tag "receiver" in "AndroidManifest.xml":
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.rec">
<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>
<receiver
android:name=".broadcastReciver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="action" />
</intent-filter>
</receiver>
</application>
</manifest>
What application should do is when I type something in first application and send it another over button it should "broadcast" (show) toast at second app.
My second application is not showing any data when run.
Nowadays it is essential to specify an action in intent filter of your broadcast receiver.
<receiver android:name="MyReceiver" >
<intent-filter>
<action android:name="android.intent.action.MY_ACTION">
</action>
</intent-filter>
</receiver>
When sending the broadcast, you need to set exactly the same action to the intent you send.
Intent i = new Intent();
i.setAction("android.intent.action.MY_ACTION");
context.sendBroadcast(i);
Notation of action name may be not very important to get your code working, but I recommend to give names related to the package of your sending app.
For example: "com.username.example.myApplication.ACTION_EXAMPLE"
I'm trying to use the transition API to detect user activity so I defined a pending intent and built a service for it to run but it just doesn't run.
Also, I don't know if it matters much but anyway, the service is supposed to communicate with a server I built once it detects that the device is still, but if I debug the program with breakpoints it just looks like it doesn't even enter the service.
It only started the service when I wrote the line pendingIntent.send() but it just wouldn't help me anyway since the intent didn't receive any data anyway.
The onCreate method in which the intent is also defined:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_running);
// Go fullscreen
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
mContext = this;
activityRecognitionClient = ActivityRecognition.getClient(mContext);
Intent intent = new Intent(this, TransitionIntentService.class);
pendingIntent = PendingIntent.getService(this, 100, intent, PendingIntent.FLAG_UPDATE_CURRENT);
configureSettingsButton();
}
The activity detection build:
public void registerHandler(final View view) {
transitions = new ArrayList<>();
transitions.add(new ActivityTransition.Builder()
.setActivityType(DetectedActivity.STILL)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
.build());
transitions.add(new ActivityTransition.Builder()
.setActivityType(DetectedActivity.STILL)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
.build());
transitions.add(new ActivityTransition.Builder()
.setActivityType(DetectedActivity.IN_VEHICLE)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
.build());
transitions.add(new ActivityTransition.Builder()
.setActivityType(DetectedActivity.IN_VEHICLE)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
.build());
transitions.add(new ActivityTransition.Builder()
.setActivityType(DetectedActivity.WALKING)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
.build());
transitions.add(new ActivityTransition.Builder()
.setActivityType(DetectedActivity.WALKING)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
.build());
transitions.add(new ActivityTransition.Builder()
.setActivityType(DetectedActivity.RUNNING)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
.build());
transitions.add(new ActivityTransition.Builder()
.setActivityType(DetectedActivity.RUNNING)
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
.build());
ActivityTransitionRequest activityTransitionRequest = new ActivityTransitionRequest(transitions);
Task<Void> task = activityRecognitionClient.requestActivityTransitionUpdates(activityTransitionRequest, pendingIntent);
task.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
textView = findViewById(R.id.textView4);
scan = findViewById(R.id.startSearching);
textView.setVisibility(View.VISIBLE);
scan.setVisibility(View.INVISIBLE);
Toast.makeText(mContext, "Started scanning", Toast.LENGTH_LONG).show();
}
});
task.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(mContext, "Failed to build transition object", Toast.LENGTH_LONG).show();
e.printStackTrace();
}
});
}
The service itself:
public class TransitionIntentService extends IntentService {
String answer;
//boolean gotMatch = false;
boolean stopScanning = false;
public void onCreate() {
super.onCreate();
Log.d("TransitionIntentService", ">>>onCreate()");
}
public TransitionIntentService() {
super("TransitionIntentService");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, startId, startId);
Log.i("LocalService", "Received start id " + startId + ": " + intent);
return START_STICKY;
}
#Override
protected void onHandleIntent(Intent intent) {
if (null != intent) {
if (ActivityTransitionResult.hasResult(intent)) {
ActivityTransitionResult result = ActivityTransitionResult.extractResult(intent);
for (ActivityTransitionEvent event : result.getTransitionEvents()) {
if(event.getActivityType() == 3) //user is still
{
if(event.getTransitionType() == 0) //the user has entered a still state
{
SendDriving sendDriving = new SendDriving();
sendDriving.start();
while (sendDriving.isAlive()){}
GetMatch getMatch = new GetMatch();
getMatch.start();
}
else if (event.getTransitionType() == 1) //the user has left the still state
{
stopScanning = true;
SendDrivingEnd sendDrivingEnd = new SendDrivingEnd();
sendDrivingEnd.start();
}
}
}
}
}
}
Thanks in advance!
Edit: my manifest file:
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.CALL_PHONE"/>
<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"
tools:ignore="GoogleAppIndexingWarning">
<activity android:name=".profile" />
<activity android:name=".settingInterests" />
<activity android:name=".languages" />
<activity android:name=".settings" />
<activity android:name=".Login" />
<service android:name=".TransitionIntentService"></service>
<activity android:name=".running" />
<activity android:name=".SignupPage2" />
<activity android:name=".SignupPage1" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
I have a service that listens for an event posted by a Particle Photon (microcontroller) and then gives a notification to the user. The event listener is registered when the Service is started in the onStartCommand function in a separate thread (Because the action requires that it not be started in the main thread) Everything works fine even when the app isn't running but after about 5 minutes it just stops. The service from what I can tell is never destroyed (I have it display something if it gets destroyed and it never has) so my gut feeling is the event listener stops working. Any help would be appreciated! The code is below!
Note: Event listener does use an internet connection if that is of any consequence
Service Code below:
public class NotificationService extends Service implements ParticleEventHandler{
//private long weightChangeSubscriptionID;
private long lockedChangeSubscriptionID;
#Override
public int onStartCommand(final Intent intent, int flags, int startId) {
final String deviceID;
final SharedPreferences sharedPreferences = this.getSharedPreferences("justintime.com.productscale", Context.MODE_PRIVATE);
deviceID = sharedPreferences.getString("deviceID"," ");
ParticleCloudSDK.init(this);
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
if(!deviceID.equals(" ")) {
//weightChangeSubscriptionID = ParticleCloudSDK.getCloud().subscribeToDeviceEvents("weightChange", deviceID, NotificationService.this);
lockedChangeSubscriptionID = -1;
lockedChangeSubscriptionID = ParticleCloudSDK.getCloud().subscribeToDeviceEvents("lockWtChange", deviceID, NotificationService.this);
if(lockedChangeSubscriptionID != -1){
sharedPreferences.edit().putBoolean("serviceRunning", true).apply();
}
}
else
Log.w("Error", "Not started! Possible no deviceID available");
} catch (IOException e) {
e.printStackTrace();
}
}
});
t.start();
return START_STICKY;
}
#Override
public void onDestroy() {
final SharedPreferences sharedPreferences = this.getSharedPreferences("justintime.com.productscale", Context.MODE_PRIVATE);
Thread t = new Thread(new Runnable() {
#Override
public void run() {
//try {
//ParticleCloudSDK.getCloud().unsubscribeFromEventWithID(weightChangeSubscriptionID);
//ParticleCloudSDK.getCloud().unsubscribeFromEventWithID(lockedChangeSubscriptionID);
sharedPreferences.edit().putBoolean("serviceRunning", false).apply();
Log.w("Subsction", "unsibscribed from lockedWeightchange");
//} catch (ParticleCloudException e) {
// e.printStackTrace();
//}
}
});
t.start();
super.onDestroy();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onEventError(Exception e) {
Log.wtf("error", "error on event");
}
#Override
public void onEvent(String eventName, ParticleEvent particleEvent) {
//if(eventName.equals("weightChange")) {
// DisplayActivity.updateScaleReading();
//}
if(eventName.equals("lockWtChange")) {
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.scale)
.setContentTitle("Scale change!")
.setContentText("Scales Value Has Changed While Locked!!")
.setPriority(Notification.PRIORITY_HIGH)
.setVibrate(new long[]{500, 1000, 500})
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setCategory(Notification.CATEGORY_EVENT)
.setAutoCancel(true)
.setSound(Settings.System.DEFAULT_NOTIFICATION_URI)
.setColor(Color.GREEN);
Intent resultIntent = new Intent(this, MainScreen.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(MainScreen.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(1234, mBuilder.build());
}
}
}
I am running the service from the main activity by checking if it is already running or not and then running it using the following code: (It is also run on boot using a boot reciever class)
#Override
protected void onResume() {
super.onResume();
updateScaleReading();
updateLockValue();
subscribeToEvents();
if (!isMyServiceRunning()){
Intent serviceIntent = new Intent(getApplicationContext(), justintime.com.productscale.NotificationService.class);
getApplicationContext().startService(serviceIntent);
}else{
Log.w("Service", "Service is already running!");
}
}
isMyServiceRunning() function:
private boolean isMyServiceRunning() {
SharedPreferences sharedPreferences = this.getSharedPreferences("justintime.com.productscale", Context.MODE_PRIVATE);
//return sharedPreferences.getBoolean("serviceRunning", false);
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (NotificationService.class.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
Manifest File:
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="true"
android:icon="#mipmap/scale_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/scale_launcher"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".MainScreen"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".DisplayActivity"
android:screenOrientation="portrait" />
<activity android:name=".SelectionActivity"
android:screenOrientation="portrait"/>
<service android:enabled="true" android:exported="false" android:name=".NotificationService">
<intent-filter>
<action android:name="justintime.com.productscale.NotificationService" />
</intent-filter>
</service>
<receiver
android:name=".BootReceiver"
android:enabled="true"
android:exported="true"
android:label="BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
I have running service (previously successfuly binded, started and unbinded with main activity):
Intent startingIntent = new Intent(this, SturkoPlayerService.class);
startingIntent.setAction(SturkoPlayerService.PLAYER_START);
bindService(startingIntent, connection, Context.BIND_AUTO_CREATE);
When I successfuly close mainactivity (service is unbinded and keeps running) and want to reopen mainactivity with notification intent:
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
intent.putExtra("Service", 1);
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); //tried also another flags
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
and then try to bind my running service
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
if (getIntent() != null && getIntent().hasExtra("Service")) {
if (!bound) {
bindService(new Intent(this, SturkoPlayerService.class), connection, 0);
}
}
}
the onServiceConnected function of my Connection variable is not called
private ServiceConnection connection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
SturkoPlayerService.LocalBinder mBinder = (SturkoPlayerService.LocalBinder) service;
sturkoService = mBinder.getService();
bound = true;
sturkoService.registerClient(MainActivity.this);
}
#Override
public void onServiceDisconnected(ComponentName name) {
bound = false;
}
};
Manifest:
...
<activity android:name=".MainActivity"
android:screenOrientation="portrait"
android:launchMode="singleTask"> //tried other modes too
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".Service.SturkoPlayerService"
android:enabled="true"
android:exported="true"
android:singleUser="true">
</service>
...
P.S.: Catlog did not show somthing
A service will only be running if:
There are 1+ clients bound to it, or
You called startService() on it and nothing has stopped it (e.g., stopSelf(), stopService())
Otherwise, once the last bound connection is unbound, the service stops.