I am creating a lockscreen app with facial recognition. As a first step I am creating a simple lockscreen that unlocks on Button click. The lockscreen should start when Switch on MainActivity is turned on. I created a Service which starts my lockscreen activity, but the activity does not show again once I turn off and then turn on my screen.
I am a beginner in android and don't understand what to do. I would be happy if i could get some help.
The java files are:
MainActivity.java
package com.sanket.droidlockersimple;
import android.content.Intent;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.widget.CompoundButton;
import android.widget.Switch;
public class MainActivity extends ActionBarActivity {
private Switch enableLocker;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
enableLocker = (Switch) findViewById(R.id.enableLocker);
enableLocker.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(enableLocker.isChecked()) {
Intent intent = new Intent(MainActivity.this, DroidLockerService.class);
startService(intent);
}
}
});
}
}
DroidLockerService.java
package com.sanket.droidlockersimple;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class DroidLockerService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Intent intent1 = new Intent(this, LockScreen.class);
intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent1);
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
LockScreen.java
package com.sanket.droidlockersimple;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
public class LockScreen extends ActionBarActivity {
private Button unlock;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
setContentView(R.layout.activity_lock_screen);
Button unlock = (Button) findViewById(R.id.button);
unlock.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
}
}
I believe that what you need is a BroadcastReceiver
You have a service running, but something needs to tell the service that the screen has turned on or off. Android accomplishes this by issuing broadcast events whenever certain things occur (i.e. phone call received, system turned on, etc). Any registered broadcast receiver that has included the relevant BroadcastIntent will be informed that the event has occurred.
Your Broadcast Receiver can then tell your service that the event has occured and your service can respond appropriately.
I think that the particular broadcast events that you need to register for are "ACTION_SCREEN_ON" and "ACTION_SCREEN_OFF". See the Intent developer reference page for details.
Also read the developer guide for intents and intent filters in Android, and here is the BroadcastReceiver reference page. (StackOverflow won't let me post more than 2 links yet...just search for it on the Android developer website.)
Related
I am studying services, and I have written a code to bind a service by clicking on a button, run a method of the service by clicking on another button and unbinding service by clicking on a third button.
If I try to run the method of the service before binding. I get, obviously, an error message, while if I first bind the service the method is normally called.
The question is, If I click on the third button to unbind the service, despite the service native method on Unbind(Intent intent) gives me a positive feedback, I'm still able to call the service method from the main activity like if it should still be bound.
Here is the Service code
package com.antonello.tavolaccio4;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.support.annotation.Nullable;
/**
* Created by Antonello on 14/05/2017.
*/
public class Servizio extends Service{
public IBinder binder=new MyBinder();
#Nullable
#Override
public IBinder onBind(Intent intent) {
return binder;
}
#Override
public boolean onUnbind(Intent intent){
System.out.println("unbinded");
return false;
}
public class MyBinder extends Binder{
Servizio getService(){
return Servizio.this;
}
}
public void metodo(){
System.out.println("Metodo del service");
}
}
and here is the Main Activity code:
package com.antonello.tavolaccio4;
import android.app.Activity;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.widget.Button;
public class MainActivity extends Activity {
ServiceConnection serviceConnection;
Servizio servizio;
Button button;
Button button2;
Button button3;
boolean bound;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button=(Button)findViewById(R.id.button);
button2=(Button)findViewById(R.id.button2);
button3=(Button)findViewById(R.id.button3);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent=new Intent(getApplicationContext(),Servizio.class);
bindService(intent,serviceConnection, Service.BIND_AUTO_CREATE);
}
});
button2.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
servizio.metodo();
}
});
button3.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
Intent intent=new Intent(getApplicationContext(),Servizio.class);
unbindService(serviceConnection);
}
});
serviceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
Servizio.MyBinder binder=(Servizio.MyBinder)service;
servizio=binder.getService();
bound=true;
System.out.println(bound);
}
#Override
public void onServiceDisconnected(ComponentName name) {
}
};
}
}
Is there anything wrong in my unbindService method?
Thank you for any help.
Is there anything wrong in my unbindService method?
You do not have an unbindService() method. You are calling the one that you are inheriting from Context.
It is your job, as part of calling unbindService(), to also set to null any fields tied to the bound connection (in your case, servizio). As it stands, you are leaking memory, and any inherited methods that your service tries calling may throw exceptions because the service is destroyed.
I'm trying to create a service in my android project.but the service seems not starting at all.
package serviceexample.javatechig.com.serviceexample;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class HelloService extends Service {
#Override
public void onCreate() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return Service.START_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onDestroy() {
}
}
manifest.xml:
<service android:name="serviceexample.javatechig.HelloService" android:exported="false"/>
and main activity:
package serviceexample.javatechig.com.serviceexample;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
public class MyActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
findViewById(R.id.start_service).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MyActivity.this, HelloService.class);
startService(intent);
}
});
findViewById(R.id.stop_Service).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MyActivity.this, HelloService.class);
stopService(intent);
}
});
}
}
no errors but when I press the buttons the service won't get started.onCreate and onStartCommand events not raising.
The package your Service is in:
package serviceexample.javatechig.com.serviceexample;
The class name you use in the Manifest:
<service android:name="serviceexample.javatechig.HelloService" android:exported="false"/>
Those should be same in order for Service to work.
You are using the wrong package name in the AndroidManifest.xml
Replace:
serviceexample.javatechig.HelloService
with
serviceexample.javatechig.com.serviceexample.HelloService
Basically the path name should be same for service activities and all
I finaly found the problem. the service tag in manifest.xml wasn't a child of application tag.If I showed the whole manifest.xml you would find the problem in a minute :)
I'm quite new to programming.
I'm trying to make a simple app with two activities, where the second activity can change the text of the first. I know it can be done using intents, but I was wondering if there is a more direct way of doing it, for example using the second activity to call a function from the first activity?
Here's the code I have so far:
The MainActivity, which contains a TextView and a button to open the second activity:
public class MainActivity extends Activity {
TextView textview;
Button button;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textview = (TextView) findViewById(R.id.et2);
button = (Button) findViewById(R.id.b1);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent(MainActivity.this, ChangeText.class);
startActivity(intent);
}
});
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
}
public void changetext(String message) {
textview.setText(message);
}
}
And the second activity, ChangeText, which contains an EditText and a button which should change the text of the TextView in MainActivity and then finish itself:
public class ChangeText extends Activity{
EditText edittext;
Button button;
private MainActivity mainclass;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.change_text);
edittext = (EditText)findViewById(R.id.et2);
button = (Button)findViewById(R.id.b2);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
String message = edittext.getText().toString();
mainclass.changetext(message);
finish();
}
});
}
}
As you can see I tried to make the app work by making a public function in MainActivity which receives a string and sets the TextView with it, and then I call this function from the ChangeText activity.
The problem: it keeps crashing! Can anyone tell me how I can make this work?
Seems like I answered almost exactly the same question a week or so ago, so this is probably a duplicate, but I can't seem to find the original question.
The short answer is no - you can't call a method in an Activity from another Activity. The issue is that for normal programming purposes, only one Activity exists at a time*.
If you do something to circumvent this, then you're risking causing some major issues, including high memory usage, null pointer exceptions, etc.
The correct way to do this is indeed through the Intent system.
* Activities may or may not actually get destroyed when they become inactive, depending on things like how you use the back stack.
However, you should always program is if they do get destroyed when they become inactive - read, understand, and respect the Activity lifecycle.
For something as simple as your app, the "most direct" approach is to use the intent and startActivityForResult and them implement an onActivityResult in your main activity.
The problem you'll run into, even if you correctly pass you Activity references around is they are not guaranteed to be running at the same time.
Other ways aside from Intents, is to use a class(s) not involved with the Activity. Either a background service or a static variable in a class that extends Application. I rarely use Application classes anymore in favor of services and binding Activities them.
If I use an EventBus in projects, they can send Sticky events, which will hold the data until cleared.
Android uses a messaging mechanism to communicate between its components. This messaging mechnism is essential to Android, so you should use it. And as you already said, the messaging is implemented by Intents. ;-)
If you want something more complex, use an EventBus or implement a your own subscribe/publish mechanism that does what you want.
Use static variable
Example
In your MainActivity define
public static String msg = null;
then in your ChangeText activity assign changed text to it like
MainActivity.msg = edittext.getText().toString();
now in your main activity override the onResume() methode
if(msg != null){
textview.setText(msg);
msg = null;
}
You must LocalBroadCast Manager to do so
Here is the MainActivity which has the TextView which has to updated by another Activity
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends Activity {
TextView txt;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txt=(TextView)findViewById(R.id.txt1);
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
new IntentFilter("custom-event-name"));
}
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String s1= intent.getStringExtra("myString");
getIt(s1);
}
};
#Override
protected void onDestroy() {
// Unregister since the activity is about to be closed.
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
super.onDestroy();
}
public void getIt(String s)
{
System.out.println(s);
txt.setText(s);
}
public void go(View view)
{
Intent intent = new Intent(this,WriteText.class);
startActivity(intent);
}
}
And This is the Activity which contains the EditText which updates the TextView in the previous activity
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
public class WriteText extends Activity {
EditText ed1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_write_text);
ed1 = (EditText)findViewById(R.id.textView);
}
public void come(View view){
Intent intent = new Intent("custom-event-name");
intent.putExtra("myString", ed1.getText().toString());
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
}
This Worked for me , Hope it works for you too
I'm a beginner with programming in Android OS that is why I've decided to ask your help. My problem is related to PhoneStateListener which should be called depending on toggle button status:
togglebtn==ON - If ServiceStateChanges or DataConnectionStateChanges -> print a Toast on the screen
togglebtn==OFF - do not check ServiceStateChanges or DataConnectionStateChanges
I've found that in order to stop listening i should send LISTEN_NONE as parameter to listen method, but it does not work
Here's the simplest version of my code:
package network.com.example;
import android.app.Activity;
import android.os.Bundle;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import android.view.View;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;
public class MainActivity extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
ToggleButton button_on_off=(ToggleButton)findViewById(R.id.toggleButton1);
button_on_off.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
{
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
if (isChecked)
{
nw_update(tm , "onCRE");
tm.listen(new PhoneStateListener() {
#Override
public void onServiceStateChanged(ServiceState serviceState) {
nw_update(tm , "onSSC");
}
#Override
public void onDataConnectionStateChanged(int state) {
nw_update(tm , "onDCC");
}
}, PhoneStateListener.LISTEN_SERVICE_STATE | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE);
}
else
{
tm.listen(null, PhoneStateListener.LISTEN_NONE | PhoneStateListener.LISTEN_NONE );
}
}
}); // end of button on/off
} // end of onCreate
private final void nw_update(TelephonyManager tm , String rodzaj) {
String _rodzaj = rodzaj;
Toast.makeText(getApplicationContext(), _rodzaj, Toast.LENGTH_SHORT).show();
}
} // end of main activity
Any ideas?
I am looking forward to hearing from you.
Quoting the documentation for listen(), with added emphasis:
To unregister a listener, pass the listener object and set the events argument to LISTEN_NONE (0).
You are not passing the listener object -- you are passing null. You need to pass the same PhoneStateListener instance as you used with the original listen() call.
I'm developing a simple game where 3 activities (menu, settings and ranking list) needs one background music that should play smoothly in the background even if for example user leaves menu and goes into settings and then back.
For that I created service which works perfectly. There is only one major problem: when app is closed (user press home button for example), music doesn't stop playing.
I have tried with onDestroy, onStop, onPause but the problem is not solved.
Service:
package com.android.migame;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.IBinder;
public class Meni_music extends Service implements OnCompletionListener {
private static final String TAG = null;
MediaPlayer player;
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
player = MediaPlayer.create(this, R.raw.menu);
player.setLooping(true); // Set looping
}
public int onStartCommand(Intent intent, int flags, int startId) {
player.start();
return 1;
}
public IBinder onUnBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onDestroy() {
player.stop();
player.release();
stopSelf();
}
#Override
public void onLowMemory() {
}
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
}
}
Menu:
package com.android.migame;
import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
public class Meni extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.meni);
startService(new Intent(Meni.this,Meni_music.class));
}
#Override
protected void onPause() {
super.onPause();
}
#Override
protected void onResume() {
super.onResume();
}
}
I think this behavior is most logically addressed by creating your own application class. Register this class in your manifest using:
<application
android:name="MyApplication"
Let the MyApplication class look something like this:
public class MyApplication extends Application
implements ActivityLifecycleCallbacks, Runnable
{
private Handler h;
#Override public void onCreate()
{
h = new Handler();
registerActivityLifecycleCallbacks(this);
}
public void onActivityCreated(Activity activity, Bundle savedInstanceState) { }
public void onActivityStarted(Activity activity) { }
public void onActivityStopped(Activity activity) { }
public void onActivitySaveInstanceState(Activity activity, Bundle outState) { }
public void onActivityDestroyed(Activity activity) { }
public void onActivityResumed(Activity activity)
{
h.removeCallbacks(this);
startService(new Intent(this, Meni_music.class));
}
public void onActivityPaused(Activity activity);
{
h.postDelayed(this, 500);
}
public void run()
{
stopService(new Intent(this, Meni_music.class));
}
}
Try this it will work .Make a ActivityLifecycleCallback class that will check if your application is in background or running.On onActivityStopped call stop your service.
public class MyLifecycleHandler implements ActivityLifecycleCallbacks {
private int resumed;
private int paused;
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
public void onActivityDestroyed(Activity activity) {
}
public void onActivityResumed(Activity activity) {
++resumed;
}
public void onActivityPaused(Activity activity) {
++paused
if(resumed == paused)
stopService(new Intent(this, Meni_music.class));
}
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
public void onActivityStarted(Activity activity) {
}
public void onActivityStopped(Activity activity) {
}
}
register your callback class -
registerActivityLifecycleCallbacks(new MyLifecycleHandler());
I had a similar requirement, and here's how I solved it:
Create a class that implements Application.ActivityLifecycleCallbacks, and have your application register it with registerActivityLifecycleCallbacks in it's onCreate method. This class will be notified every time an activity is paused or resumed.
Have this class maintain a count of the number of active activities - start at 0, add one for each resumed activity, and subtract one for each paused activity. In practice, your counter will always be zero or one.
In your onActivityPaused method, after decrementing the counter, check to see if the count is zero. Note that there is a short period of time between an Activity being paused and the next one being resumed when you transition between activities, during which the count will be zero. If, after waiting some reasonable amount of time from the onActivityPaused, your count is still zero, then your application has been put completely into the background, and you should stop your service.
This is what you can do,
Create a static helper class, add a static variable msActivityCount in it and add following 2 methods in it.
increaseActivityCount() - increment the msActivityCount value. If msActivityCount == 1 start the service. Call this function from onStart() of each activity.
decreaseActivityCount() - decrement the msActivityCount value. If msActivityCount == 0 stop the service. Call this function from onStop() of each activity.
This should solve your issue without any problems.
Easy solutions:
Just use one activity! Use Fragments for each screen that you are displaying.
Use a static counter. Increment the counter when you call startActivity(). Decrement the counter onPause() of all activities. When an activity pauses, and your counter is 0, then stop the music.
Start your service when Menu activity resumes and stop it when the activity stops. So the Menu activity should look like something like this:
package com.android.migame;
import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
public class Meni extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.meni);
}
#Override
protected void onPause() {
super.onPause();
stopService(new Intent(Meni.this,Meni_music.class));
}
#Override
protected void onResume() {
super.onResume();
startService(new Intent(Meni.this,Meni_music.class));
}
}
You declare your Intent outside the function in activity class and stop the service inside this class, call stop or ondestroy
like this:
public class Meni extends Activity {
private Intent i=new Intent();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.meni);
i=new Intent(Meni.this,Meni_music.class);
startService(i);
}
#Override
protected void onDestroy() {
stopService(i);
super.onDestroy();
}
#Override
protected void onStop() {
stopService(i);
super.onStop();
}
}
Background Music without using Services:
http://www.rbgrn.net/content/307-light-racer-20-days-61-64-completion