I am trying to write an app that would perform following operations:
once the user unlock the phone he has 10 seconds to scan an NFC tag in order to start camera app. and the NFC tag will have a mime type of
application/com.testformat.nfcdemo
To detect screen unlock, I used a broadcast receiver to detected User present.
And this works fine.
And I started a CountdownTimer inside the broadcast receiver for 10 seconds.
And the NFC detection part did not work, I could use some help here! thank you all!
My activity:
import android.app.Activity;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
public class DisplayActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
}
}
Manifest xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.nfc"
android:versionCode="1"
android:versionName="1.0" >
<uses-feature android:name="android.hardware.nfc" android:required="true" />
<uses-permission android:name="android.permission.NFC" />
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="19" />
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity
android:name=".DisplayActivity"
android:label="#string/activity_title" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".ScreenStateReceiver">
<intent-filter>
<action android:name="android.intent.action.USER_PRESENT" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/com.testformat.nfcdemo" />
</intent-filter>
</receiver>
</application>
</manifest>
Receiver:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.nfc.NfcAdapter;
import android.os.CountDownTimer;
import android.widget.Toast;
public class ScreenStateReceiver extends BroadcastReceiver {
private boolean countdown_end = false;
NfcAdapter mNfcAdapter;
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_USER_PRESENT)) {
CharSequence text = context.getResources().getString(R.string.unlock_message);
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
startCountdown(10000);
if (intent.getAction().equals(NfcAdapter.ACTION_NDEF_DISCOVERED)) {
if (!countdown_end) {
text = context.getResources().getString(R.string.nfc_detected);
Toast nfc_toast = Toast.makeText(context, text, duration);
toast.show();
}
}else if ( intent.getAction().equals(NfcAdapter.ACTION_TAG_DISCOVERED)){
if (!countdown_end) {
text = context.getResources().getString(R.string.nfc_detected);
Toast nfc_toast = Toast.makeText(context, text, duration);
toast.show();
}
}
}
}
private void startCountdown(long milliseconds){
new CountDownTimer(milliseconds, 1000) {
#Override
public void onTick(long l) {
}
public void onFinish() {
countdown_end=true;
}
}.start();
}
}
can broadcast receiver handle ACTION_NDEF_DISCOVERED?
No. That is an activity action, used with startActivity(). It is not broadcast and therefore cannot be picked up by a BroadcastReceiver.
Related
Learning broadcast messages. The book DN Kolisnichenko - "Programming for Android" is an example of where the camera at the touch of a button starts the service. But I have it che does not work. What is the problem? Or I do not know what is the camera button (physical or on the display), or do not understand what is wrong. Here is the code of the example:
MainActivity.java
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.content.Intent;
import android.content.IntentFilter;
public class MainActivity extends AppCompatActivity {
MyReceiver iReceiver = new MyReceiver();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IntentFilter iFilter = new IntentFilter(Intent.ACTION_CAMERA_BUTTON);
iFilter.addAction(Intent.ACTION_CAMERA_BUTTON);
registerReceiver(iReceiver, iFilter);
}
#Override
protected void onDestroy() {
unregisterReceiver(iReceiver);
super.onDestroy();
}
}
MyReceiver.java
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context rcvContext, Intent rcvIntent) {
String action = rcvIntent.getAction();
if (action.equals(Intent.ACTION_CAMERA_BUTTON)) {
rcvContext.startService(new Intent(rcvContext,
MyService.class));
}
}
}
MyService.java
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;
public class MyService extends Service {
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(this,"Service started...",
Toast.LENGTH_LONG).show();
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service destroyed...",
Toast.LENGTH_LONG).show();
}
}
And manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ivarious.myapplication">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
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" />
<action android:name="android.intent.action.CAMERA_BUTTON" />
</intent-filter>
</activity>
<receiver android:name=".MyReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.CAMERA_BUTTON" />
</intent-filter>
<service android:name=".MyService"></service>
<action android:name="android.intent.action.CAMERA_BUTTON" />
<action android:name="android.intent.extra.KEY_EVENT" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
</receiver>
</application>
</manifest>
Make Sure You Added The Camera Permission to your Manifest
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
I know that when I define a Broadcast receiver from manifest in bellow of intent filter I can define category that it's optional.
<receiver android:name=".PushMessageReceiver" >
<intent-filter>
<!-- Receives the actual messages. -->
<category android:name="com.test.myAppname" />
<action android:name="com.test.client.MSGRECEIVE" />
</intent-filter>
</receiver>
I googled but cant get it what is the exact point of adding category or how I can use it. I appreciate to give me some examples.
MainActivity.java
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
/**
* send
*
*/
public class MainActivity extends Activity {
private static final String MY_ACTION = "com.chaowen.action.MY_ACTION";
private Button btn;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn = (Button)findViewById(R.id.Button01);
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent intent= new Intent();
intent.setAction(MY_ACTION);
//Intent message
intent.putExtra("msg", "ha ha");
//send
sendBroadcast(intent);
}
});
}
}
MyReceiver.java
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
/**
* receive
*
*/
public class MyReceive extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//get Intent message
String msg = intent.getStringExtra("msg");
Toast.makeText(context, msg, Toast.LENGTH_LONG).show();
}
}
main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Button
android:text="send..."
android:id="#+id/Button01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.chaowen"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="4" />
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity android:name=".MainActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name="MyReceive"
>
<intent-filter>
<action
android:name="com.chaowen.action.MY_ACTION" />
</intent-filter>
</receiver>
</application>
I need to start 2 services on bootcompleted. The first service starts correctly, but second service seems is not starting.
I don't know if I have to create two BroadcastReceiver or it's enough with one.
Here is my code. I've put the two services in one BroadcastReceiver. Please, can you tell me what I'm doing wrong?
Thank you in advance
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.pruebas.appservicelocator"
android:versionCode="1"
android:versionName="1.0"
android:installLocation="internalOnly" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="16" />
<!-- Startup service -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<!-- GPS -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- UUID -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<!-- Acceso a web service -->
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.pruebas.appservicelocator.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".Servicio">
<intent-filter>
<action android:name="com.pruebas.appservicelocator.Servicio"/>
</intent-filter>
</service>
<service android:name=".ServicioBD">
<intent-filter>
<action android:name="com.pruebas.appservicelocator.ServicioBD"/>
</intent-filter>
</service>
<receiver android:name=".Recibidor" android:enabled="true" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
</application>
</manifest>
Recibidor.java:
package com.pruebas.appservicelocator;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
public class Recibidor extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
android.os.Debug.waitForDebugger();
Toast.makeText(context, "Iniciando Recibidor", Toast.LENGTH_LONG).show();
final String TAG = "Recibidor";
Log.i(TAG, "Iniciando Recibidor");
if (intent.getAction().equalsIgnoreCase("android.intent.action.BOOT_COMPLETED")) {
Toast.makeText(context, "Iniciando Intent", Toast.LENGTH_LONG).show();
Log.i(TAG, "Iniciando Intent");
Intent servicio = new Intent();
servicio.setAction("com.pruebas.appservicelocator.Servicio");
context.startService(servicio);
Intent servicioBD = new Intent();
servicio.setAction("com.pruebas.appservicelocator.ServicioBD");
context.startService(servicioBD);
Log.i(TAG, "Iniciando Servicios");
Toast.makeText(context, "Iniciando Servicio", Toast.LENGTH_LONG).show();
}
}
}
"Servicio" service works fine, so I don't write the code. If you need, please, tell-me and I will write it.
ServicioBD.java:
package com.pruebas.appservicelocator;
import com.pruebas.utils.UsersLocationsDBHelper;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;
public class ServicioBD extends Service{
private UsersLocationsDBHelper locDBHelper = null;
private static String TAG = "ServicioBD";
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(this, "SERVICIOBD ON CREATE", Toast.LENGTH_LONG).show();
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
startForeground(0, null);
Toast.makeText(this, "SERVICIOBD ON START COMMAND", Toast.LENGTH_LONG).show();
return START_STICKY;
}
}
I've found the error.
Intent servicio = new Intent();
servicio.setAction("com.pruebas.appservicelocator.Servicio");
context.startService(servicio);
Intent servicioBD = new Intent();
servicio.setAction("com.pruebas.appservicelocator.ServicioBD");
context.startService(servicioBD);
Has to be
Intent servicio = new Intent();
servicio.setAction("com.pruebas.appservicelocator.Servicio");
context.startService(servicio);
Intent servicioBD = new Intent();
servicioBD.setAction("com.pruebas.appservicelocator.ServicioBD");
context.startService(servicioBD);
Hello i am writing an application, which is when the phone reboot, the service will auto start instead of click on the application.
Here is my code for
BootCompleteReceiver.java
package com.example.newbootservice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class BootCompleteReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent service = new Intent(context, MsgPushService.class);
context.startService(service);
}
}
MsgPushService.java
package com.example.newbootservice;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;
public class MsgPushService extends Service {
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
return Service.START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service Destroy", Toast.LENGTH_LONG).show();
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
}
MainActivity.java (not sure whether i need this)
package com.example.newbootservice;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startService(new Intent(getBaseContext(), MsgPushService.class));
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
Manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.newbootservice"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<service android:name=".MsgPushService"/>
<receiver android:name=".BootCompleteReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
I want the service to be started automatically after reboot instead of starting it manually.
You forgot about the permissions
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
Though all the above answers were correct, however from Android Oreo they put some limitation on Background Services.
Check Background Execution Limits to know more about background limits in Android O.
You can't start a Service directly from BroadCastReceiver when the application is in the background.
However, you can start a foreground service from the receiver by calling startForegroundService() or use JobIntentService as there is no such limitation with JobIntentService.
Use this code on your Broadcast Receiver class:
if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
Intent service = new Intent(context, MsgPushService.class);
context.startService(service);
}
also try these permissions,it may help you .ifyou are using htc phones then these permissions are required
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.QUICKBOOT_POWERON"/>
I am trying to display messages from C2DM so When I start an Activity from a non activity it works but only first time. My activity contains View and close button so if the user is not inside the app when he receive the push notification then it should start the app when he press view button or close it on close this works as well but when user press view button and enters the app after than I am unable to start the activity again, it seems like the activity is there but its not visible to user. My code is as below , hope you understand what I am saying. The C2DM code example used is taken from here
C2DMReceiver
package com.mks.android.example;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import com.google.android.c2dm.C2DMBaseReceiver;
import com.google.android.c2dm.C2DMessaging;
import com.mks.android.example.activity.MessageDialogActivity;
public class C2DMReceiver extends C2DMBaseReceiver {
private static String senderId = "mysenderemail#gmail.com";
String registrationId;
public C2DMReceiver() {
super(senderId);
}
#Override
public void onRegistrered(Context context, String registrationId) {
this.registrationId = registrationId;
Log.e("Error", registrationId);
}
#Override
public void onUnregistered(Context context) {
C2DMessaging.register(context, senderId);
}
#Override
public void onError(Context context, String errorId) {
Log.w("Error", errorId);
}
#Override
protected void onMessage(Context context, Intent intent) {
Log.i("Error", "MessageReceived");
Bundle bundle = intent.getExtras();
intent = new Intent();
intent.putExtra("messageBundle", bundle);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
intent.setClass(context, MessageDialogActivity.class);
startActivity(intent);
// load message display activity here
}
}
MESSAGE DIALOG ACTIVITY CLASS
package com.mks.android.example.activity;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import com.mks.android.example.R;
import com.mks.android.example.activity.list.Functions;
public class MessageDialogActivity extends Activity {
private Functions func = new Functions();
private int isAppActive = 0;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
showMessages();
}
private void showMessages(){
Bundle bundle = getIntent().getBundleExtra("messageBundle");
String title = bundle.getString("title");
String message = bundle.getString("message");
setContentView(R.layout.c2dm_message);
TextView txtTitle = (TextView) findViewById(R.id.title);
TextView txtMessage = (TextView) findViewById(R.id.message);
Button btnView = (Button) findViewById(R.id.btnView);
Button btnClose = (Button) findViewById(R.id.btnClose);
txtTitle.setText(title);
txtMessage.setText(message);
this.isAppActive = func.getAppState(this);
if(isAppActive==1){
btnView.setVisibility(View.GONE);
}
btnView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(isAppActive == 0){
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setComponent(new ComponentName("com.mks.android.example","com.mks.android.example.activity.MainActivity"));
startActivity(intent);
}
MessageDialogActivity.this.finish();
}
});
btnClose.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
}
#Override
protected void onNewIntent(Intent intent) {
setIntent(intent);
showMessages();
}
}
AndroidManifest FIle
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mks.android.example"
android:versionCode="1"
android:versionName="1.0" android:installLocation="preferExternal">
<uses-sdk android:minSdkVersion="4" />
<application android:label="#string/app_name" android:icon="#drawable/icon_launcher" android:debuggable="true">
<uses-library android:name="com.google.android.maps" />
<activity android:name=".activity.MainActivity"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:theme="#android:style/Theme.NoTitleBar" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".activity.MessageDialogActivity" android:theme="#style/DialogNoTitle" android:activity android:launchMode="singleTop" />
<service android:name=".C2DMReceiver" />
<!-- Only C2DM servers can send messages for the app. If permission is not set - any other app can generate it -->
<receiver android:name="com.google.android.c2dm.C2DMBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND">
<!-- Receive the actual message -->
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.mks.android.example" />
</intent-filter>
<!-- Receive the registration id -->
<intent-filter>
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.mks.android.example" />
</intent-filter>
</receiver>
</application>
<supports-screens android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:anyDensity="true" />
<permission android:name="com.mks.android.example.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="com.mks.android.example.permission.C2D_MESSAGE" />
<!-- This app has permission to register and receive message -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
If i remove androidLaunchMode singleTop form manifest file and add set flag to multipleTask in C2DMReciver class it works but i get lots of dialog for each message. Thanks for help .
Set flag to singletop , the code to call messagedialogactivity is as under:
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.setClass(context, MessageDialogActivity.class);