I am trying to get my Android app to respond to changes in the local address book and sync with it on a need basis.
I understand that in order to do that, I need to create a service to run in the background. I did.
But it isn't working... when my app runs and I try to initiate the service, it fails with :
[exec] [DEBUG] I/ActivityManager( 60): Starting activity: Intent { cmp=ti.test/my.Activity (has extras) }
[exec] [DEBUG] E/aas ( 1812): (main) [490639,495460] people uri:content://contacts/people
[exec] [DEBUG] W/ActivityManager( 60): Unable to start service Intent { cmp=ti.test/.MyService }: not found
this is how I try to run it:
startService(new Intent(activity, MyService.class));
this is part of my manifest.xml fie:
<android xmlns:android="http://schemas.android.com/apk/res/android">
<manifest android:versionCode="1" android:versionName="1">
<uses-sdk android:minSdkVersion="4"/>
<supports-screens android:anyDensity="true"
android:largeScreens="true" android:normalScreens="true" android:smallScreens="true"/>
<application>
<service android:name="ti.test.MyService"/>
</application>
</manifest>
</android>
this is the service class:
package ti.test;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import android.database.ContentObserver;
import android.provider.Contacts.People;
public class MyService extends Service
{
private static final String TAG = "MyService";
private class MyContentObserver extends ContentObserver {
public MyContentObserver() {
super(null);
}
#Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
Log.e ("DatabaseTable" , "****************************** contact database change detected *************************************");
}
#Override
public boolean deliverSelfNotifications() {
return true;
}
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
Log.d("MyService", "starting........");
MyContentObserver contentObserver = new MyContentObserver();
getContentResolver().registerContentObserver (People.CONTENT_URI, true, contentObserver);
}
#Override
public void onDestroy() {
Log.d("MyService", "stopping........");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("LocalService", "Received start id " + startId + ": " + intent);
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
#Override
public void onStart(Intent intent, int startid) {
Log.d("MyService", "onStart........");
}
}
thanks!
you should not create class in service.
you should define a contectResolver class and register it in an activity or where you want to use it.
Related
I have a requirement to show a customised screen over/on the lock screen in android. logically I want to show a screen (an activity) when phone is locked.
[]
I have tried multiple ways to achieve this functionality but no luck yet.
some links which I have followed are :
https://github.com/ShakeebM/Android-LockScreen
Create custom lockscreen for android 4.0 or above?
show web site on Android lock screen
Creating custom LockScreen in android
https://github.com/Kirk-Str/LockScreenApp
As of now I am able to show a custom screen over the lock screen when app is in foreground state but when app is in background/killed state not able to show the custom screen over the lock screen. Please suggest me what I am missing in my code snippet.
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.lockscreen">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<application
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round">
<activity
android:name=".sample2.screen.LockScreenActivity"
android:excludeFromRecents="true"
android:label="#string/app_name"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:theme="#android:style/Theme.NoTitleBar.Fullscreen"
android:showOnLockScreen="true"
android:turnScreenOn="false"
android:noHistory="true"
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=".sample2.utils.LockscreenService" >
</service>
<receiver
android:name=".sample2.utils.LockscreenIntentReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
</manifest>
LockscreenService Class:
package com.example.lockscreen.sample2.utils;
import android.app.Notification;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.util.Log;
import androidx.core.app.NotificationCompat;
import com.example.lockscreen.R;
public class LockscreenService extends Service {
private BroadcastReceiver mReceiver;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
// Register for Lockscreen event intents
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("LockScreen ::: ","onStartCommand");
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
mReceiver = new LockscreenIntentReceiver();
registerReceiver(mReceiver, filter);
startForeground();
return START_STICKY;
}
// Run service in foreground so it is less likely to be killed by system
private void startForeground() {
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle(getResources().getString(R.string.app_name))
.setTicker(getResources().getString(R.string.app_name))
.setContentText("Running")
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentIntent(null)
.setOngoing(true)
.build();
startForeground(9999,notification);
}
// Unregister receiver
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(mReceiver);
}
}
LockscreenIntentReceiver Class:
package com.example.lockscreen.sample2.utils;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import com.example.lockscreen.sample2.screen.LockScreenActivity;
public class LockscreenIntentReceiver extends BroadcastReceiver {
// Handle actions and display Lockscreen
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)
|| intent.getAction().equals(Intent.ACTION_SCREEN_ON)
|| intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
start_lockscreen(context);
}
}
// Display lock screen
private void start_lockscreen(Context context) {
Intent mIntent = new Intent(context, LockScreenActivity.class);
mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(mIntent);
}
}
LockScreenActivity Class:
package com.example.lockscreen.sample2.screen;
import android.app.Activity;
import android.app.KeyguardManager;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.view.KeyEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.Toast;
import com.example.lockscreen.R;
import com.example.lockscreen.sample2.utils.LockscreenService;
import com.example.lockscreen.sample2.utils.LockscreenUtils;
public class LockScreenActivity extends Activity implements
LockscreenUtils.OnLockStatusChangedListener {
// User-interface
private Button btnUnlock;
// Member variables
private LockscreenUtils mLockscreenUtils;
// Set appropriate flags to make the screen appear over the keyguard
#Override
public void onAttachedToWindow() {
this.getWindow().addFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
);
super.onAttachedToWindow();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.getWindow().addFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
);
setContentView(R.layout.activity_lockscreen);
init();
// unlock screen in case of app get killed by system
if (getIntent() != null && getIntent().hasExtra("kill")
&& getIntent().getExtras().getInt("kill") == 1) {
enableKeyguard();
unlockHomeButton();
}
try {
// disable keyguard
disableKeyguard();
// lock home button
lockHomeButton();
Toast.makeText(getApplicationContext(),"lockHomeButton startService", Toast.LENGTH_LONG).show();
// start service for observing intents
startService(new Intent(this, LockscreenService.class));
// listen the events get fired during the call
StateListener phoneStateListener = new StateListener();
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
telephonyManager.listen(phoneStateListener,
PhoneStateListener.LISTEN_CALL_STATE);
} catch (Exception e) {
}
}
private void init() {
mLockscreenUtils = new LockscreenUtils();
btnUnlock = (Button) findViewById(R.id.btnUnlock);
btnUnlock.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// unlock home button and then screen on button press
unlockHomeButton();
}
});
}
// Handle events of calls and unlock screen if necessary
private class StateListener extends PhoneStateListener {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
unlockHomeButton();
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
break;
case TelephonyManager.CALL_STATE_IDLE:
break;
}
}
};
// Don't finish Activity on Back press
#Override
public void onBackPressed() {
return;
}
// Handle button clicks
#Override
public boolean onKeyDown(int keyCode, android.view.KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)
|| (keyCode == KeyEvent.KEYCODE_POWER)
|| (keyCode == KeyEvent.KEYCODE_VOLUME_UP)
|| (keyCode == KeyEvent.KEYCODE_CAMERA)) {
return true;
}
if ((keyCode == KeyEvent.KEYCODE_HOME)) {
return true;
}
return false;
}
// handle the key press events here itself
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP
|| (event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_DOWN)
|| (event.getKeyCode() == KeyEvent.KEYCODE_POWER)) {
return false;
}
if ((event.getKeyCode() == KeyEvent.KEYCODE_HOME)) {
return true;
}
return false;
}
// Lock home button
public void lockHomeButton() {
mLockscreenUtils.lock(LockScreenActivity.this);
}
// Unlock home button and wait for its callback
public void unlockHomeButton() {
mLockscreenUtils.unlock();
}
// Simply unlock device when home button is successfully unlocked
#Override
public void onLockStatusChanged(boolean isLocked) {
if (!isLocked) {
unlockDevice();
}
}
#Override
protected void onStop() {
super.onStop();
unlockHomeButton();
}
#SuppressWarnings("deprecation")
private void disableKeyguard() {
KeyguardManager mKM = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
KeyguardManager.KeyguardLock mKL = mKM.newKeyguardLock("IN");
mKL.disableKeyguard();
}
#SuppressWarnings("deprecation")
private void enableKeyguard() {
KeyguardManager mKM = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
KeyguardManager.KeyguardLock mKL = mKM.newKeyguardLock("IN");
mKL.reenableKeyguard();
}
//Simply unlock device by finishing the activity
private void unlockDevice()
{
finish();
}
}
Please help me how can I achieve this?
I'm developing an android app with Unity that requires a foreground service. To do that I've made an android module with android studio. The problem is that my service is never started but at the same time there aren't errors and the aplication still running, for example after my start service I can show a toast.
Unity - C# - AndroidPluginManager.cs
I'm using this class to instantiate the module and call the function to start the service. The function StartAndroidService() is called using the onClick() feature of Unity inspector.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AndroidPluginManager : MonoBehaviour
{
private AndroidJavaObject androidPlugin = null;
private AndroidJavaObject unityContext = null;
private AndroidJavaObject unityActivity = null;
private AndroidJavaClass unityClass = null;
void Start() {
//Get unity activity and context
unityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
unityActivity = unityClass.GetStatic<AndroidJavaObject>("currentActivity");
unityContext = unityActivity.Call<AndroidJavaObject>("getApplicationContext");
//Create android plugin object
androidPlugin = new AndroidJavaObject("com.androidplugin.stepcounterlibrary.ApiStepCounter");
//Set activity and context to the module
androidPlugin.Call("setActivity", unityActivity);
androidPlugin.Call("setContext", unityContext);
}
//Start Service
public void StartAndroidService() {
androidPlugin.Call("startStepCounter");
androidPlugin.Call("showMessage", "Hello World");
}
}
Android Studio - Java - ApiStepCounter.java
For the time being I'm using this class only to start the service and create a toast to check if the module is working correctly.
package com.androidplugin.stepcounterlibrary;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class ApiStepCounter{
private Activity activity;
private Context context;
public ApiStepCounter() {}
public void setActivity(Activity activity){
this.activity = activity;
}
public void setContext(Context context){
this.context = context;
}
public void showMessage(String message){
Toast.makeText(this.context, message, Toast.LENGTH_LONG).show();
}
public void startStepCounter(){
Intent serviceIntent = new Intent(this.context, StepCounterService.class);
this.context.startService(serviceIntent);
}
}
Android Studio - Java - StepCounterService.java
This class should start the foreground service and show a notification but it doesn't. It's the first time that I try to use an Android service so I don't know if I'm doing something wrong. Also I've tried to execute some Log.d inside each method (onCreate(), onStartCommand(), onDestroy()) and no one is printed so I guess that the service is not started.
package com.androidplugin.stepcounterlibrary;
import android.app.Notification;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
import android.widget.Toast;
public class StepCounterService extends Service {
public StepCounterService(){}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "TestChannel");
builder.setSmallIcon(R.drawable.ic_android)
.setContentText("Text of notification")
.setContentTitle("Title of notification");
Notification notification = builder.build();
startForeground(1, notification);
return START_STICKY;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
Android Studio - Manifest - AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.androidplugin.stepcounterlibrary">
<application>
<service android:name=".StepCounterService"/>
</application>
</manifest>
I've been trying for 2 days how to create the foreground service using Unity with an Android module so if someone could help me I would appreciate it a lot. Feel free to ask me anything that you need, I think this is all that I need to create a foreground service but maybe I'm missing something.
i'm trying to make a very simple service that plays an audio file by putting a button that its onClick() -> starts the service which in turn plays the sound.
but when i destroy the activity the song stops ( i can't tell Service state)[that i put a toast in onDestroy method in Service class , and it didn't come out.]
Any One Can HELP ?!!
AndroidManifest
<service android:name=".ExampleService"
android:enabled="true"
android:exported="true"
></service>
ExampleService.java
public class ExampleService extends Service {
MediaPlayer mpService;
private final static String TAG="ExampleService";
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mpService.start();
return START_STICKY;
}
#Override
public void onCreate() {
super.onCreate();
mpService=MediaPlayer.create(this,R.raw.lwyashko);
Toast.makeText(this,"*** STARTED *** ",Toast.LENGTH_SHORT).show();
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
}
#Override
public void onDestroy() {
Log.d(TAG,"onDestroy was Called ");
Toast.makeText(this,"Service Destroyed",Toast.LENGTH_SHORT).show();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
MainActivity.java
playService.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
i=new Intent(getApplication(),ExampleService.class);
startService(i);
}
});
As of API 26, only foreground services will usually be allowed to run without an Activity still active. You make a service a foreground one by calling startForeground() within the service. You will need to create and provide a notification in the call. Here's the relevant documentation page.
Normally, after the service is started by startService, the service will not be destroyed after the activity is closed. However, if the user manually cleans up the task, the entire APP process will be closed and the Service will stop.
I want to have a background service, which will stay alive after the app is closed and which I can bind to again when the app is started.
For testing I made it that a counter will increase every time I bind to the service.
So theoretically the app should start, I will create the service, then bind to it -> the counter should move up.
Then I close the app and press the Bind button again and It should log a "1" and move the counter up again.
But it doesn't ...
It will display a 0 every time I restart the app and bind to it ...
This is my current Test - Service - class:
package com.programm.testapp;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
public class TestService extends Service {
/*
* Service Binder
*/
private final IBinder iBinder = new TestService.LocalConnectionService();
public class LocalConnectionService extends Binder {
public TestService getService(){
return TestService.this;
}
}
/*
* Test var
* It should increase every time the app is started.
*/
private int test;
#Override
public IBinder onBind(Intent intent) {
Log.d("mDEBUG", "Test: " + test);
test++;
return iBinder;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("mDEBUG", "Service: Start Command");
return START_STICKY;
}
}
This is my current Test - Activity:
package com.programm.testapp;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
private TestService service;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button createButton = findViewById(R.id.button_create_service);
createButton.setOnClickListener(this::createService);
Button destroyButton = findViewById(R.id.button_destroy_service);
destroyButton.setOnClickListener(this::destroyService);
Button bindButton = findViewById(R.id.button_bind_service);
bindButton.setOnClickListener(this::bindService);
Button unbindButton = findViewById(R.id.button_unbind_service);
unbindButton.setOnClickListener(this::unbindService);
}
private void createService(View v){
Intent intent = new Intent(this.getBaseContext(), TestService.class);
startService(intent);
}
private void destroyService(View v){
Intent intent = new Intent(this.getBaseContext(), TestService.class);
stopService(intent);
}
private void bindService(View v){
Intent intent = new Intent(this.getBaseContext(), TestService.class);
bindService(intent, serviceConnection, BIND_AUTO_CREATE);
}
private void unbindService(View v){
unbindService(serviceConnection);
}
private ServiceConnection serviceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d("mDEBUG", "Connection: on service connected");
MainActivity.this.service = ((TestService.LocalConnectionService) service).getService();
}
#Override
public void onServiceDisconnected(ComponentName name) {
Log.d("mDEBUG", "Connection: on service disconnected");
}
};
}
This is my AndroidManifest.xml - file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.programm.testapp">
<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>
<service
android:name=".TestService"
android:enabled="true"
android:exported="false"></service>
</application>
</manifest>
This is my output after I ...
Pressed Create Service - Button
Pressed Bind Service - Button
Pressed Unbind Service - Button
Close App and Restart it
Pressed Bind Service - Button
:
.../com.programm.testapp D/mDEBUG: Service: Start Command
.../com.programm.testapp D/mDEBUG: Test: 0
.../com.programm.testapp D/mDEBUG: Connection: on service connected
.../com.programm.testapp D/mDEBUG: Service: Start Command
.../com.programm.testapp D/mDEBUG: Test: 0
.../com.programm.testapp D/mDEBUG: Connection: on service connected
By the way the second "Service: Start Command" is called as I CLOSE the app ... after a few new Logs I noticed, that also the Constructer and the "onCreate" method of the Service - class will be called with it.
Is this normal?
Edit:
When I only minimize the App and not close it via Activity - Menu the behavior is exactly the one I want!!!
Edit 2:
A Foreground service does the job for now ...
I couldn't find any other solution for this
If you actively close the app (by closing it from the Android activity list), Android will most likely kill your service. You can see that in your apps Logcat. The only real way around that is a foreground service.
Furthermore, onBind will not be called every time you bind to the service. From the Android documentation:
You can connect multiple clients to a service simultaneously. However, the system caches the IBinder service communication channel. In other words, the system calls the service's onBind() method to generate the IBinder only when the first client binds. The system then delivers that same IBinder to all additional clients that bind to that same service, without calling onBind() again.
Secondly, just that onStartCommand is called does not mean the service is recreated. It can be called multiple times during the service life cycle. For instance, each time startService is called, onStartCommand is executed, but the service is not necessarily recreated.
Also, it looks like you do not un-bind the service when closing the activity. That makes your activity leak the ServiceConnection and your app crash. It would explain why you see the service re-created every time you close and re-start the app.
Try adding an unbind in your activity's onPause method:
#Override
void onPause() {
super.onPause()
unbindService(this.serviceConnectino)
}
A working configuration could look like below. It implements incrementing the counter using a dedicated service function, rather than onBind:
MyBoundService.kt
package com.test
import android.app.Service
import android.content.Intent
import android.os.Binder
import android.os.IBinder
import android.util.Log
class MyBoundService : Service() {
abstract class MyBinder: Binder() {
abstract fun getService(): MyBoundService
}
val iBinder: MyBinder = object: MyBinder() {
override fun getService(): MyBoundService {
return this#MyBoundService
}
}
private var counter = 0
fun increment() {
counter ++
Log.i("MyBoundService", "Counter: ${counter}")
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.i("MyBoundService", "startCommand");
return super.onStartCommand(intent, flags, startId)
}
override fun onBind(p0: Intent?): IBinder? {
counter++
Log.i("MyBoundService", "Bound: ${counter}")
return iBinder
}
override fun onUnbind(intent: Intent?): Boolean {
Log.i("MyBoundService", "Unbound")
return super.onUnbind(intent)
}
}
MainActivity.kt
package com.test
import android.content.Intent
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*
import android.content.ComponentName
import android.content.Context
import android.content.ServiceConnection
import android.os.IBinder
import android.util.Log
import com.test.MyBoundService
class MainActivity : AppCompatActivity() {
private val serviceConnection: ServiceConnection = object: ServiceConnection {
override fun onServiceDisconnected(p0: ComponentName?) {
Log.i("MainActivity", "Service disconnected")
}
override fun onServiceConnected(p0: ComponentName?, p1: IBinder?) {
Log.i("MainActivity", "Service connected")
p1?.let {
(p1 as MyBoundService.MyBinder).getService().increment()
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btn_create.setOnClickListener {
val i = Intent(this#MainActivity, MyBoundService::class.java)
startService(i)
}
btn_bind.setOnClickListener {
val i = Intent(this#MainActivity, MyBoundService::class.java)
bindService(i, serviceConnection, Context.BIND_AUTO_CREATE)
}
}
override fun onPause() {
super.onPause()
unbindService(serviceConnection)
}
}
I want to programing app for data track in background , so I use service .
I want to write a program that monitors all data sent and received by the device, and when the total volume of received or received messages reaches a specified value, the Internet device is turned off.
So I used the following code to monitor the data:
mStartRX = TrafficStats.getTotalRxBytes ();
mStartTX = TrafficStats.getTotalTxBytes ();
And I used the services to work on the background in the background.
To specify the download or upload limit from the user with edittext, I requested this limit in mainactivity and send this value to the service.
The problem is when: When I destroy the program, I will restart the service and get the NULL value and the program crashes.
My application code:
Main Activity :
package ir.alexandre9009.service;
import android.app.AlertDialog;
import android.content.Context;
import android.net.TrafficStats;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends Activity {
public static Handler mHandler = new Handler();
public static long UPP;
public static long DLL;
Button startService,stopService;
public Context context=this;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (FirstService.mStartRX == TrafficStats.UNSUPPORTED || FirstService.mStartTX == TrafficStats.UNSUPPORTED) {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("Uh Oh!");
alert.setMessage("Your device does not support traffic stat monitoring.");
alert.show();
} else {
mHandler.postDelayed(mRunnable, 1000);
}
startService=(Button)findViewById(R.id.startService);
stopService=(Button)findViewById(R.id.stopService);
startService.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
EditText UP = (EditText) findViewById(R.id.UP);
String UPPP = UP.getText().toString();
UPP=Long.parseLong(UPPP);
EditText DL = (EditText) findViewById(R.id.DL);
String DLLL = DL.getText().toString();
DLL=Long.parseLong(DLLL);
Intent intent = new Intent(getApplicationContext(), FirstService.class);
String myString = DLLL;
intent.putExtra("StringName", myString);
startService(intent);
}
});
stopService.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
stopService(new Intent(getBaseContext(),FirstService.class));
}
});
}
public final Runnable mRunnable = new Runnable() {
public void run() {
TextView RX = (TextView)findViewById(R.id.RX);
TextView TX = (TextView)findViewById(R.id.TX);
RX.setText(Long.toString(FirstService.rxBytes));
TX.setText(Long.toString(FirstService.txBytes));
mHandler.postDelayed(mRunnable, 1000);
}
};
}
Service :
package ir.alexandre9009.service;
import android.app.AlertDialog;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.TrafficStats;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.IBinder;
import android.widget.TextView;
import android.widget.Toast;
public class FirstService extends Service{
public static long mStartRX ;
public static long mStartTX ;
public static long rxBytes ;
public static long txBytes ;
public long dl=MainActivity.DLL;
Context context=this;
private final Runnable mRunnable = new Runnable() {
public void run() {
rxBytes = (TrafficStats.getTotalRxBytes()- mStartRX)/1048576;
txBytes = (TrafficStats.getTotalTxBytes()- mStartTX)/1048576;
if (rxBytes==2) {
stopService(new Intent(getBaseContext(),FirstService.class));
Intent i = new Intent(context,MainActivity.class);
context.startActivity(i);
// WifiManager wifiManager = (WifiManager)getApplicationContext().getSystemService(Context.WIFI_SERVICE);
// wifiManager.setWifiEnabled(false);
//معرفی توست برای نمایش یک پیام کوتاه به کاربر در هنگام خاموش کردن وای فای
Toast.makeText(FirstService.this, "هشدار", Toast.LENGTH_LONG).show();
}
mHandler.postDelayed(mRunnable, 1000);
}
};
private Handler mHandler = new Handler();
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this,"staart",Toast.LENGTH_LONG).show();
mStartTX=0;
mStartRX=0;
mStartRX = TrafficStats.getTotalRxBytes();
mStartTX = TrafficStats.getTotalTxBytes();
mHandler.postDelayed(mRunnable, 1000);
return Service.START_STICKY;
}
#Override
public void onDestroy() {
TrafficStats.clearThreadStatsTag();
Toast.makeText(this,"FirstService Stoped",Toast.LENGTH_LONG).show();
mStartTX=0;
mStartRX=0;
super.onDestroy();
}
}
AndroidManifest :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="ir.alexandre9009.service">
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.UPDATE_DEVICE_STATS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".FirstService"
>
</service>
</application>
</manifest>
please help me ...
The problem is with this line
public long dl=MainActivity.DLL;
You're referring to a variable in the Activity, surly when the Activity is destroyed, this variable is no longer in scope, thus you get Null Exception.
You must get this value using the intent.
The other problem is that you can't prevent any service from being killed by the system except foreground services which need to show a notification to the user. But this is not suitable for your situation.
Therefore, the best approach for you is to check whether intent is null or not. If it is not null, you get the value and save it into Preferences or Database or somewhere, if it is null, you retrieve the value from where you stored it before.