I'm trying to make a service that works 24/7 and it's been working until I updated to Android 12. I've checked the new foreground restrictions but still don't understand why it isn't working since I'm starting it from an activity.
ACTIVITY
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
public class TestActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
startForegroundService(new Intent(TestActivity.this, TestService.class));
}
}
SERVICE
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.media.MediaBrowserCompat;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import androidx.media.MediaBrowserServiceCompat;
import java.util.List;
public class TestService extends MediaBrowserServiceCompat {
#Override
public BrowserRoot onGetRoot(#NonNull String clientPackageName, int clientUid, #Nullable Bundle rootHints) { return null; }
#Override
public void onLoadChildren(#NonNull String parentId, #NonNull Result<List<MediaBrowserCompat.MediaItem>> result) { result.sendResult(null); }
#Override
public int onStartCommand(Intent ii, int flags, int startId) {
//CREATE NOTI CHANNEL
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
"test", "Test Notifications",
NotificationManager.IMPORTANCE_HIGH);
((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel);
}
//CREATE NOTI
Notification notification = new NotificationCompat.Builder(this, "test")
.setSmallIcon(R.drawable.icon)
.setContentTitle("title")
.setContentText("test")
.setChannelId("test")
.setOngoing(true)
.setSilent(true)
.build();
//START FOREGROUND
startForeground(101, notification);
return START_STICKY;
}
}
I tried creating a new app with just these lines of code and it works fine so it must be something else making the service close after a minute.
Turns out samsung put my app on deep sleep which caused it to close itself if not used for a minute. Also thanks to the people who took their time to try and help.
Even though you are correct in wanting a foreground Service here, it seems as if you want it to stay alive whenever you app in the background, or not running at all, as you don't intend your app to be running 24/7, do you?
Since it seems as if you're trying to use a MediaBrowserServiceCompat in your example, I would suggest you do so using a companion instance of a MediaSessionCompat in order to have the media session control the lifecycle of your Service on it's own.
Implementing a media Service is not the most straightforward task in Android; they're still trying to fix some of its prevailing issues with the latest release of Android 13. Therefore, I would also suggest you follow this official Android guide if you're attempting to create an audio app with a media foreground Service.
Related
package com.example.twapp.Observer;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.widget.Button;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import com.example.twapp.Notify;
import com.example.twapp.R;
import com.example.twapp.testReceiver;
public class ConcreteObserverA extends AppCompatActivity implements Observer {
NotificationManager notificationManager;
NotificationChannel channel;
Context context = this;
private String observerState;
private ConcreteSubject concreteSubject; // 持有指向 ConcreteSubject 物件的 reference
public ConcreteObserverA(ConcreteSubject concreteSubject) {
this.concreteSubject = concreteSubject;
}
#RequiresApi(api = Build.VERSION_CODES.O)
#Override
public void update() {
setContentView(R.layout.activity_notify);
notificationManager = (NotificationManager) this.getSystemService(NOTIFICATION_SERVICE);
channel=new NotificationChannel("ID","com.example.twapp",NotificationManager.IMPORTANCE_HIGH);
notificationManager.createNotificationChannel(channel);
Intent intent = new Intent(context,testReceiver.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,1,intent,PendingIntent.FLAG_UPDATE_CURRENT);
Notification.Builder builder = new Notification.Builder(context);
builder.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("訊息")
.setContentText("跌倒啦~")
.setChannelId("ID");
Notification notification=builder.build();
notificationManager.notify(1,notification);
}
}
I use the Observer pattern to implement notifications, but I have problems when my concreateObserver wants to print notifications.
When I delete this method. Simple print is feasible.Because I can't think of a way. So come to ask everyone android studio master.
This question already has an answer here:
How to play sound when a notification pops up?
(1 answer)
Closed 2 years ago.
I'm developing an app that sends notifications to the user with a message and a sound. There are two switches, 1 to turn on and off the notifications and the second to turn on and off the notification sound. I wrote the code for the notification sound but it doesn't seem to work.
Do you have any idea about how to make the notification sound to play when a notification pops up?
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.Switch;
import java.util.Set;
import androidx.annotation.RequiresApi;
import static android.app.PendingIntent.getActivity;
import static android.content.Context.NOTIFICATION_SERVICE;
import static com.example.myevents.R.drawable.notification;
public class Settings extends AppCompatActivity {
Switch simpleswitch1;
Switch simpleswitch2;
private Notification notification;
NotificationManager manager;
Notification myNotication;
boolean enableSound = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
simpleswitch1 = (Switch) findViewById(R.id.simpleswitch1);
simpleswitch2 = (Switch) findViewById(R.id.simpleswitch2);
simpleswitch1.setChecked(false);
simpleswitch2.setChecked(false);
simpleswitch1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#TargetApi(Build.VERSION_CODES.O)
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked){
int notifyID = 1;
String CHANNEL_ID = "my_channel_01";// The id of the channel.
CharSequence name = "channel 1";// The user-visible name of the channel.
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID, name, importance);
Intent intent = new Intent(Settings.this, Visitor.class);
intent.putExtra("yourpackage.notifyId", notifyID);
PendingIntent pIntent = PendingIntent.getActivity(Settings.this, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
// Create a notification and set the notification channel.
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(Settings.this, CHANNEL_ID);
notificationBuilder.setSmallIcon(R.drawable.notification);
notificationBuilder.setContentTitle("Title");
notificationBuilder.setContentText("New notification");
notificationBuilder.setContentIntent(pIntent);
notificationBuilder.setChannelId(CHANNEL_ID).build();
if (enableSound){
notificationBuilder.setSound(android.provider.Settings.System.DEFAULT_NOTIFICATION_URI);
notificationBuilder.setVibrate(new long[]{1000,100});
}
Notification notification = notificationBuilder.build();
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.createNotificationChannel(mChannel);
// Issue the notification.
mNotificationManager.notify(notifyID , notification);
}
simpleswitch2.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
enableSound = isChecked;
}
});
}});}}
UPDATED
Once you have setdefault on a notificationbuilder, it will ignore subsequent calls like setsound and setvibrate.
You have to set sound and vibration in setdefault method always.
if (shouldSound && !shouldVibrate) {
builder.setDefaults(Notification.DEFAULT_SOUND)
.setVibrate(new long[]{0L});
}
if (shouldVibrate && !shouldSound) {
builder.setDefaults(Notification.DEFAULT_VIBRATE)
.setSound(null);
}
if (shouldSound && shouldVibrate) {
builder.setDefaults(Notification.DEFAULT_ALL);
}
For a simple working example of Notifications on all versions, you can consult the following repo https://github.com/usman14/Notification
I have been learning jobscheduler in andorid. I have trying to show a toast message in the onstartjob() after every 1minute. But its not showing up. Any help will be grateful.
jobschedul_service .class:
package com.prajwal.jobscheduler;
import android.app.Service;
import android.app.job.JobParameters;
import android.app.job.JobScheduler;
import android.app.job.JobService;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;
public class jobschedul_service extends JobService {
#Override
public boolean onStartJob(JobParameters jobParameters) {
Toast.makeText(getApplicationContext(), "After 15 minutes", Toast.LENGTH_SHORT).show();
return false;
}
#Override
public boolean onStopJob(JobParameters jobParameters) {
return true;
}
}
MainActivity.class:
package com.prajwal.jobscheduler;
import androidx.appcompat.app.AppCompatActivity;
import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.ComponentName;
import android.content.Context;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
private static final int LOAD_ARTWORK_JOB_ID = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
JobScheduler jobScheduler =
(JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);
jobScheduler.schedule(new JobInfo.Builder
(LOAD_ARTWORK_JOB_ID, new ComponentName(this, jobschedul_service.class))
.setPeriodic(900000)
.build());
}
}
Manifest.xml:
<service
android:name=".jobschedul_service"
android:enabled="true"
android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE"></service>
Got the answer!
The reason was the setperiodic(long interval).
As per the ss below:
This function was added in API 21 i.e Lolipop version. Whereas I was running the app on version > Lolipop.
Whereas this new function in the image below:
was added in API 24 i.e. Nougat
Hence, if you are targetting your app below Nougat i.e < Nougat but >= Lolipop then use setPeriodic(long interval) method whereas if u r targetting >= Nougat then use setPeriodic(long interval, long flexinterval).
Solution
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.N)
{
builder.setPeriodic(900000,6000);
}
else
{
builder.setPeriodic(900000);
}
I am new to Android Studio. I have 0 Experience with Java and was still successful to send SMS using my app.
How to Send that SMS at a specific time. E.g; at 5 o'clock.
I have tried com.google.android.gms.gcm.ACTION_TASK_READY, etc but unable to get the permission to send SMS in my other task name MyTask.java
The code is used in mainactivity.java is
package com.example.ssss;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.telephony.SmsManager;
import com.google.android.gms.gcm.GcmNetworkManager;
import com.google.android.gms.gcm.PeriodicTask;
public class MainActivity extends AppCompatActivity {
int MY_PERMISSIONS_REQUEST_SEND_SMS = 1;
String SENT = "SMS_SEND";
String DELIVERED = "SMS_DELIVERED";
PendingIntent sentPI, deliveredPI;
BroadcastReceiver smsSentReceiver, smsDeliveredReceiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
GcmNetworkManager networkManager=GcmNetworkManager.getInstance(this);
String s1 = "MY MSG";
String TellNO = "THE NUMBER";
sentPI = PendingIntent.getBroadcast(this, 0, new Intent(SENT), 0);
deliveredPI = PendingIntent.getBroadcast(this, 0, new Intent(DELIVERED), 0);
if (ContextCompat.checkSelfPermission(this, Manifest.permission.SEND_SMS)
!= PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.SEND_SMS},
MY_PERMISSIONS_REQUEST_SEND_SMS);
}
else
{
SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage(TellNO, null, s1, sentPI, deliveredPI);
}
}
}
Thanks
Use alarmmanager to schedual a call to a method which fetch no. from your database and send your desired message to that number.
From android docs:
AlarmManager:This class provides access to the system alarm services. These allow you to schedule your application to be run at some point in the future. When an alarm goes off, the Intent that had been registered for it is broadcast by the system, automatically starting the target application if it is not already running.
I've Created an service for lock screen service the purpose of the service is to register and unregistered receiver but it is causing memory leak because of the my application crashes when there is not enough memory left to consume
Here is my code
package com.itstars.daynightlockscreen;
import android.app.KeyguardManager;
import android.app.KeyguardManager.KeyguardLock;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.PixelFormat;
import android.media.AudioManager;
import android.os.IBinder;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Toast;
public class LockService extends Service {
public static boolean wal;
public static boolean isRunning;
public static TimeChangeReceiver receiver;
KeyguardManager keyguardManager;
KeyguardLock lock;
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
keyguardManager = (KeyguardManager) getSystemService(Service.KEYGUARD_SERVICE);
lock = keyguardManager.newKeyguardLock(KEYGUARD_SERVICE);
lock.disableKeyguard();
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
wal = intent.getBooleanExtra("wal", false);
isRunning = intent.getBooleanExtra("locker",false);
receiver = new TimeChangeReceiver();
registerReceiver(receiver, filter);
isRunning = true;
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver);
isRunning = false;
keyguardManager = (KeyguardManager) getSystemService(Service.KEYGUARD_SERVICE);
lock = keyguardManager.newKeyguardLock(KEYGUARD_SERVICE);
lock.reenableKeyguard();
}
}
Have you define Service in Manifest? If Yes,
then Have you give permission
`android.permission.DISABLE_KEYGUARD`
in manifest ? If yes, then
Put a code in try-catch block in onStartCommand , put a debug point on first line of onStartCommand method observe line where it jump to catch block.
Because error must be in your onStartCommand method only.
START_NOT_STICKY
Constant to return from onStartCommand(Intent, int, int): if this service's process is killed while it is started (after returning from onStartCommand(Intent, int, int)), and there are no new start intents to deliver to it, then take the service out of the started state and don't recreate until a future explicit call to Context.startService(Intent).
START_STICKY
Constant to return from onStartCommand(Intent, int, int): if this service's process is killed while it is started (after returning from onStartCommand(Intent, int, int)), then leave it in the started state but don't retain this delivered intent.
Using above description decide where you want to use sticky intent or not ?