In my application i want a Recording Screen and for this I write below code.
After running application, there's no call to my Recorder service and after using Log.e it still does not show me logs?
I write Recording code into onActivityResult.
For this I used countDownTimer and I want, when this timer has finished, for the recording to start.
For checking if it works I used Log.e and it shows a log into onFinished code (for timer), but does not show any logs into onActivtyResult code
My Activity code:
public class RecordingActivity extends BaseActivity {
private TextView txtTesterCounter;
Thread thread;
private int counter;
private CountDownTimer countDownTimer;
private MediaProjection mMediaProjection;
private MediaProjectionManager mProjectionManager;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tester_tutorial_count_down);
init();
reverseTimer(4).start();
//Create video direction
createDir();
}
private void init() {
txtTesterCounter = findViewById(R.id.txtTesterCounter);
counter = 3;
//Acquiring media projection service to start screen mirroring
mProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
}
private CountDownTimer reverseTimer(int second) {
return countDownTimer = new CountDownTimer(second * 1000, 1000) {
#SuppressLint("SetTextI18n")
#Override
public void onTick(long millisUntilFinished) {
if (millisUntilFinished <= 800) {
onFinish();
} else {
int second = (int) (millisUntilFinished / 1000);
txtTesterCounter.setText(App.enToFa(second + ""));
}
}
#Override
public void onFinish() {
if (mMediaProjection == null && !isServiceRunning(RecorderService.class)) {
//Request Screen recording permission
startActivityForResult(mProjectionManager.createScreenCaptureIntent(), ConstKeys.SCREEN_RECORD_REQUEST_CODE);
Log.e("RecordingLog","OnFinished");
} else if (isServiceRunning(RecorderService.class)) {
//stop recording if the service is already active and recording
}
finish();
}
};
}
//Create application directory
public static void createDir() {
File appDir = new File(Environment.getExternalStorageDirectory() + File.separator + ConstKeys.APPDIR);
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) && !appDir.isDirectory()) {
appDir.mkdirs();
}
}
private boolean isServiceRunning(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;
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.e("RecordingLog","OnActivityResult");
//The user has denied permission for screen mirroring. Let's notify the user
if (resultCode == RESULT_CANCELED && requestCode == ConstKeys.SCREEN_RECORD_REQUEST_CODE) {
return;
}
Intent recorderService = new Intent(this, RecorderService.class);
recorderService.setAction(ConstKeys.SCREEN_RECORDING_START);
recorderService.putExtra(ConstKeys.RECORDER_INTENT_DATA, data);
recorderService.putExtra(ConstKeys.RECORDER_INTENT_RESULT, resultCode);
startService(recorderService);
Log.e("RecordingLog","Recorder Service");
}
}
How can i fix this?
onActivityResult called when the child activity is finished. In your case after you start an activity, you finish the RecordingActivity.
#Override
public void onFinish() {
if (mMediaProjection == null && !isServiceRunning(RecorderService.class)) {
//Request Screen recording permission
startActivityForResult(mProjectionManager.createScreenCaptureIntent(), ConstKeys.SCREEN_RECORD_REQUEST_CODE);
Log.e("RecordingLog","OnFinished");
} else if (isServiceRunning(RecorderService.class)) {
//stop recording if the service is already active and recording
}
finish(); // what does this method do?
}
I assume that finish method finished your activity. If it does so, onActivityResult will never be called because you finish parent activity.
Related
I'm developing a simple app for WearOS. This app consists of the app itself, which just shows an image and two services. One is a service, does NFC card emulation and the other simply listens for the off body event, and resets some values, whenever the watch is taken off. This works well while I'm debugging and also for a some time when started normally.
However, after a few hours, the watch can be taken off, without my app getting the event. I suspect, that the OS is killing the service and not restarting it, despite the START_STICKY flag. The watch is not coupled with a phone and is not running other apps.
This is the code of my service:
public class MySensorService extends Service
{
private static final String TAG = "MySensorService";
private SensorManager sensorManager;
private Sensor mOffBody;
public MySensorService()
{
Log.i(TAG, "Sensor service was created.");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.i(TAG, "Sensor service starting.");
sensorManager = (SensorManager) getApplicationContext().getSystemService(SENSOR_SERVICE);
mOffBody = sensorManager.getDefaultSensor(TYPE_LOW_LATENCY_OFFBODY_DETECT, true);
if (mOffBody != null) {
sensorManager.registerListener(mOffbodySensorListener, mOffBody,
SensorManager.SENSOR_DELAY_NORMAL);
}
Log.i(TAG, "Sensor service was started.");
return START_STICKY;
}
private void onWatchRemoved()
{
Log.i(TAG, "Watch is not worn anymore");
Intent intent = new Intent(this, MyAPDUService.class);
intent.putExtra("UserID", 0);
Log.d(TAG,"starting service");
startService(intent);
}
private void onWatchAttached()
{
Log.i(TAG, "Watch is now worn");
}
private final SensorEventListener mOffbodySensorListener = new SensorEventListener()
{
#Override
public void onSensorChanged(SensorEvent event)
{
if (event.values.length > 0)
{
if (event.values[0] == 0) // 0 = Watch is not worn; 1 = Watch is worn
{
onWatchRemoved();
}
else
{
onWatchAttached();
}
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int i)
{
}
};
#Override
public void onDestroy()
{
super.onDestroy();
Log.i(TAG, "Sensor Service destroyed");
}
}
I want to play 6 different sounds triggered by 6 different buttons in background, so that if the app is on background the sound keeps playing.
When one sound is already playing, pressing another button will stop it and play its own sound,
Tapping the same button 2K times it stops, 2K+1 times: starts again.. (K is a non-null integer)
All of the code is done and seems to be working correctly, except that the player stops after one and a half minute. (This is not because of low memory)
Can anyone please tell me what am I doing wrong?
public class PlayService extends Service {
private MediaPlayer player;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
player = new MediaPlayer();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
int btnId = intent.getExtras().getInt("ID");
Toast.makeText(this, "onStart service" + btnId, Toast.LENGTH_SHORT).show();
selectResId(btnId);
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service destroyed", Toast.LENGTH_SHORT).show();
if (player != null) {
player.stop();
player.release();
}
player = null;
}
#Override
public void onLowMemory() {
super.onLowMemory();
Toast.makeText(this, "Low mem", Toast.LENGTH_SHORT).show();
}
private void selectResId(int resId){
switch (resId){
case 1: playMediaFromResource(R.raw.number_one);
case 2: playMediaFromResource(R.raw.number_two);
case 3: playMediaFromResource(R.raw.number_three);
case 4: playMediaFromResource(R.raw.number_four);
case 5: playMediaFromResource(R.raw.number_five);
case 6: playMediaFromResource(R.raw.number_six);
default: break;
}
}
private void playMediaFromResource(int resId) {
Uri mediaPath = Uri.parse("android.resource://" + getPackageName() + "/" + resId);
try {
player.setDataSource(getApplicationContext(), mediaPath);
player.setLooping(true);
player.prepare();
player.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
And the MainActivity:
public class MainActivity extends AppCompatActivity {
private Button btnStart1;
private Button btnStart2;
private Button btnStart3;
private Button btnStart4;
private Button btnStart5;
private Button btnStart6;
private Intent intent;
private int previousID = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewsByIds();
setOnClickListeners();
}
private void findViewsByIds() {
btnStart1 = findViewById(R.id.btn_start_1);
btnStart2 = findViewById(R.id.btn_start_2);
btnStart3 = findViewById(R.id.btn_start_3);
btnStart4 = findViewById(R.id.btn_start_4);
btnStart5 = findViewById(R.id.btn_start_5);
btnStart6 = findViewById(R.id.btn_start_6);
}
private void setOnClickListeners() {
btnStart1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
checkIntentState(1);
}
});
btnStart2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
checkIntentState(2);
}
});
btnStart3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
checkIntentState(3);
}
});
btnStart4.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
checkIntentState(4);
}
});
btnStart5.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
checkIntentState(5);
}
});
btnStart6.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
checkIntentState(6);
}
});
}
private void checkIntentState(int ID) {
if (intent == null) {
createNewIntent(ID);
} else {
stopService(intent);
intent = null;
if (ID != previousID) {
createNewIntent(ID);
}
}
}
private void createNewIntent(int ID) {
intent = new Intent(MainActivity.this, PlayService.class);
intent.putExtra("ID", ID);
startService(intent);
previousID = ID;
}
}
I want to answer to my own question just in case anyone else runs into the problem.
It turns out, that Android added some new features (restricted access to background resources for battery life improvement purposes since Oreo(i.e. Android 8.0+ || API level 26)).
As the documentation says:
"Apps that are running in the background now have limits on how freely they can access background services."
So, in this case we will need to use foreground services.
I am currently working on an Android App which informs the number of screen unlocks he/she has done over a day. This example can be seen on stock android devices with API Level P or higher in the feature named Digital Wellbeing. I would like to know how does it work.
You can use Event stats to get unlock count. Try the following code snippet
void getdailyUsageStatistics(long start_time, long end_time){
int unlockcount=0;
UsageEvents.Event currentEvent;
UsageStatsManager mUsageStatsManager = (UsageStatsManager)
getApplicationContext().getSystemService(Context.USAGE_STATS_SERVICE);
if (mUsageStatsManager != null) {
UsageEvents usageEvents = mUsageStatsManager.queryEvents(start_time, end_time);
while (usageEvents.hasNextEvent()) {
currentEvent = new UsageEvents.Event();
usageEvents.getNextEvent(currentEvent);
if (currentEvent.getEventType() == UsageEvents.Event.KEYGUARD_HIDDEN)
{
++unlockcount;
}
}
} else {
Toast.makeText(getApplicationContext(), "Sorry...", Toast.LENGTH_SHORT).show();
}
Log.e("UNLOCK COUNT",unlockcount+" ");
}
You can add reciever like this in your Activity :
private LockScreenStateReceiver mLockScreenStateReceiver;
int count = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLockScreenStateReceiver = new LockScreenStateReceiver();
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_USER_PRESENT);
registerReceiver(mLockScreenStateReceiver, filter);
}
public class LockScreenStateReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
// screen is turn off
//("Screen locked");
} else {
//Handle resuming events if user is present/screen is unlocked
count++;
textView.setText(""+count);
//("Screen unlocked");
}
}
}
#Override
public void onDestroy() {
unregisterReceiver(mLockScreenStateReceiver);
super.onDestroy();
}
Here's code for a timer that plays a sound once it reaches 0 (timer works fine). The problem is the sound persists even through onPause() in MainActivity.java called.
I implemented onDestroy() in SimpleIntentService.java to stop the sound, but apparently it's never called even with finish() in the calling Activity. How am I supposed to make the sound stop when the app is paused?
Here's my MainActivity.java
public class MainActivity extends Activity {
private BroadcastReceiver broadcastReceiver;
NumberPicker picker;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
picker = (NumberPicker) findViewById(minutePicker);
Log.i("TurnToTech", "Project Name - SimpleBackgroundService");
picker.setMinValue(0);
picker.setMaxValue(20);
broadcastReceiver = new BroadcastReceiver(){
#Override
public void onReceive(Context arg0, Intent intent) {
String text = intent.getStringExtra(SimpleIntentService.PARAM_OUT_MSG);
Toast.makeText(getApplicationContext(),
text, Toast.LENGTH_SHORT).show();
}
};
}
Intent msgIntent;
public void startTimer(View view) {
setContentView(R.layout.activity_main);
msgIntent = new Intent(this, SimpleIntentService.class);
msgIntent.putExtra(SimpleIntentService.PARAM_IN_MSG, "Alarm: ");
msgIntent.putExtra("time", picker.getValue());
startService(msgIntent);
}
public void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter(SimpleIntentService.ACTION_RESP);
filter.addCategory(Intent.CATEGORY_DEFAULT);
registerReceiver(broadcastReceiver,filter);
}
public void onPause() {
finish();
unregisterReceiver(broadcastReceiver);
super.onPause();
}
}
And the SimpleIntentService.java
public class SimpleIntentService extends IntentService {
public static final String PARAM_IN_MSG = "in_msg";
public static final String PARAM_OUT_MSG = "out_msg";
int time;
public static final String ACTION_RESP = "org.turntotech.intent.action.MESSAGE_PROCESSED";
public SimpleIntentService() {
super("SimpleIntentService");
}
#Override
protected void onHandleIntent(Intent intent) {
System.out.println("SimpleIntentService Called");
String msg = intent.getStringExtra(PARAM_IN_MSG);
int time = intent.getIntExtra("time", 0);
// Timer implementation
if (time == 0 ){
playSound();
}
while(time > 0){
SystemClock.sleep(5000); // 5 seconds
time -= 5;
String resultTxt = msg + time + " seconds remaining";
Intent broadcastIntent = new Intent();
broadcastIntent.setAction(ACTION_RESP);
broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
broadcastIntent.putExtra(PARAM_OUT_MSG, resultTxt);
broadcastIntent.putExtra("time", time);
sendBroadcast(broadcastIntent);
if (time == 0) {
playSound();
}
}
}
Uri alert;
public void playSound(){
alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), alert);
r.play();
}
public void onDestroy() {
Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), alert);
r.stop();
super.onDestroy();
}
}
In your IntentService you're not really stopping the same alarm in your onDestroy function. Because each time you're getting a new instance of it.
So I would like to suggest to keep a public static variable of Ringtone so that it can be accessed from everywhere. Declare them in your MainActivity.
public static Ringtone r;
public static Uri alert;
Initialize them in the onCreate function of your MainActivity.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// ... Other statements
// Initialize ringtone here
initializeRingtone();
}
private void initializeRingtone() {
alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
r = RingtoneManager.getRingtone(getApplicationContext(), alert);
}
Now the onPause() function of your MainActivity should look like this
public void onPause() {
unregisterReceiver(broadcastReceiver);
r.stop();
super.onPause();
}
And if you want to play the sound after you resume the application from background and then the timer runs out, you might consider doing something like this in the onResume function of your MainActivity
public void onResume() {
super.onResume();
registerReceiver(broadcastReceiver);
initializeRingtone(); // Initialize it again.
}
And the playSound() function in the IntentService might look like this.
public void playSound(){
// Initialize the alert and ringtone again.
MainActivity.alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
MainActivity.r = RingtoneManager.getRingtone(getApplicationContext(), alert);
MainActivity.r.play();
}
public void onDestroy() {
MainActivity.r.stop();
super.onDestroy();
}
Hope that helps!
I have created an application in which when I turn on bluetooth a toast is shown and a new activity starts. This is my broadcast receiver class:
public class BroadCast extends BroadcastReceiver {
String prefs="myPrefs";
String count="myCount";
static int counter=0;
Intent i;
#Override
public void onReceive(Context arg0, Intent arg1) {
String bluth = arg1.getAction();
if (bluth.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
if(arg1.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1) == BluetoothAdapter.STATE_ON){
SharedPreferences sp = arg0.getSharedPreferences(prefs, Context.MODE_PRIVATE);
Editor ed = sp.edit();
ed.putInt(count, counter);
ed.commit();
counter++;
Toast.makeText(arg0, "Bluetooth on " + sp.getInt(count, 0), Toast.LENGTH_LONG).show();
i = new Intent(arg0, Indicators.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
arg0.startActivity(i);
Indicators.on.setVisibility(View.VISIBLE);
} else if (arg1.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1) == BluetoothAdapter.STATE_OFF) {
} else if (arg1.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1) == BluetoothAdapter.STATE_TURNING_OFF) {
} else if (arg1.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1) == BluetoothAdapter.STATE_TURNING_ON) {
}
}
}
}
Now there is no problem. The activity is starting but in the above code when I put
Indicators.on.setVisibility(View.VISIBLE);
And run the app, It crashes!
Actually on is a textview obj which I have defined in Indicators class as follows:
public class Indicators extends Activity {
static TextView on, off, opening, closing;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.textviewbluetooth);
opening = (TextView)findViewById(R.id.textView1);
on = (TextView)findViewById(R.id.textView2);
closing = (TextView)findViewById(R.id.textView3);
off = (TextView)findViewById(R.id.textView4);
opening.setVisibility(View.INVISIBLE);
on.setVisibility(View.INVISIBLE);
off.setVisibility(View.INVISIBLE);
closing.setVisibility(View.INVISIBLE);
}
}
How should I remove this error?
class YourActivity extends xxxx {
private static YourActivity mInst;
public static YOurActivity instance() {
return mInst;
}
/// Do your task here.
public void setViewText(xxxx) ;
#Override
public void onStart() {
...
mInst = this;
}
#Override
public void onStop() {
...
mInst = null;
}
}
And in your BroadcastReceiver:
YOurActivity inst = YOurActivity.instance();
if(inst != null) { // your activity can be seen, and you can update it's context
inst.setViewText...
}
Put this line
on.setVisibility(View.VISIBLE);
Inside the Activity -> onCreate() method.
Do not use static references to the Activity class members like TextViews from outside the Activity itself as it might have been destroyed, or not have been created yet. This is bad practice in general.
Edit: Add an extra to the Activity starter intent if you need a flag to show the indicator.