I am quite new in Android: i made some experiments and reserachs on the web, but i didn't figure from where my issue commes... I would like my app to receive the BOOT_COMPLETE broadcast message, but for an unknown reason, i don't acheive to have this working. Sympots are : it seems to work on emulator either at start or using the command
shell am broadcast -a android.intent.action.BOOT_COMPLETED -n <myapp>/.BootReceiver
However, this doesn't work in my "real TV". Even worse: i tryed other applications that uses this broadcast message and they are working (e.g. Aurora, or Launch-on-boot) on both the 'real' TV and the emulator... As their code is open, i check but i didn't found what is wrong in my code... From what i was able to found isung adb on the real TV is that the broadcast is not sent to my application, but is for others:
2020-03-25 17:25:23.800 1796-3309/? I/ActivityManager: Start proc 6054:com.aurora.store/u0a96 for broadcast com.aurora.store/.receiver.BootReceiver
2020-03-25 17:25:26.163 1796-3228/? I/ActivityManager: Start proc 6126:com.github.yeriomin.yalpstore/u0a24 for broadcast com.github.yeriomin.yalpstore/.BootReceiver
Therefore, i would like to request some help, any hint will be welcome...
Here is my manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.eds.testtvapp">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-feature
android:name="android.hardware.touchscreen"
android:required="false" />
<uses-feature
android:name="android.software.leanback"
android:required="true" />
<application
android:allowBackup="true"
android:banner="@mipmap/ic_launcher"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
android:name=".ConfigActivity"
android:theme="@style/Theme.Leanback">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".BootReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.REBOOT" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON" />
<action android:name="android.intent.action.USER_PRESENT" />
</intent-filter>
</receiver>
</application>
</manifest>
Here the broadcast receiver
package com.eds.testtvapp;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
public class BootReceiver extends BroadcastReceiver {
private static final String LOG_TAG = BootReceiver.class.getPackage() + "_" + BootReceiver.class.getSimpleName();
@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
Log.i(LOG_TAG, "onReceive");
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED) ) {
Log.i(LOG_TAG, "Start from boot");
Intent anIntent = new Intent( context, MainActivity.class);
anIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//start activity from boot, so do it silently
Bundle bundle = new Bundle();
bundle.putBoolean(context.getString(R.string.app_data_start), true);
anIntent.putExtras(bundle);
context.startActivity(anIntent);
}
}
}
My main activity (the only one)
package com.eds.testtvapp;
import android.app.Activity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.Switch;
import android.widget.Button;
import android.widget.Toast;
import com.google.android.material.snackbar.Snackbar;
import android.util.Log;
public class MainActivity extends Activity implements
View.OnClickListener,
CompoundButton.OnCheckedChangeListener {
// debugging info
private static final String LOG_TAG = MainActivity.class.getPackage() + "_" + MainActivity.class.getSimpleName();
Button mButtonToast; // button to create a toast
Button mButtonSnack; // button to create a snackbar
Switch mSwitch; // switch to select toast or snackbar at boot
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i(LOG_TAG, "Start");
mButtonToast = findViewById(R.id.button_toast);
mButtonSnack = findViewById(R.id.button_snack);
mSwitch = findViewById(R.id.switch_toast_snack);
boolean bFromBoot = false;
// retrieve config (or default)
getPreferencesData();
// register listeners (after initial set to to avoid switch initialisation to issue a message)
mSwitch.setOnCheckedChangeListener(this);
mButtonToast.setOnClickListener(this);
mButtonSnack.setOnClickListener(this);
try {
Bundle bundle = getIntent().getExtras();
if (bundle!= null) {
bFromBoot = bundle.getBoolean(getString(R.string.app_data_start));
}
} catch (Exception e) {
Log.e(LOG_TAG, "Error creating main display");
}
// if started from boot
if (bFromBoot) {
// display something according to settings
if(mSwitch.isChecked()) {
Snackbar.make(this.findViewById(android.R.id.content),
"Boot Snackbar", Snackbar.LENGTH_LONG).show();
} else {
Toast.makeText(this, "Boot Toast", Toast.LENGTH_SHORT)
.show();
}
// avoid UI to be started
finish();
}
}
@Override
protected void onResume() {
super.onResume();
// restore values
Log.i(LOG_TAG, "Resume");
getPreferencesData();
}
@Override
protected void onPause() {
super.onPause();
// store values
Log.i(LOG_TAG, "Pause");
setPreferencesData();
}
protected void getPreferencesData() {
Log.i(LOG_TAG, "Get boot type of message from configuration");
// Get from the SharedPreferences
SharedPreferences settings = getApplicationContext().getSharedPreferences(getString(R.string.app_data), MODE_PRIVATE);
// get saved switch selector value
String sBootMsgType = settings.getString(getString(R.string.config_switch_selection),getString(R.string.config_switch_Default));
boolean bBootMsgType = Boolean.parseBoolean(sBootMsgType);
// sets the UI
mSwitch.setChecked(bBootMsgType);
}
protected void setPreferencesData() {
Log.i(LOG_TAG, "Sets boot type of message in configuration");
// Get from the SharedPreferences
SharedPreferences settings = getApplicationContext().getSharedPreferences(getString(R.string.app_data), MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
// get port value and status from UI
String sBootMsgType = String.valueOf(mSwitch.isChecked());
// commit the changes
editor.putString(getString(R.string.config_switch_selection),sBootMsgType);
editor.apply();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button_toast:
Toast.makeText(this, "This is a toast", Toast.LENGTH_SHORT)
.show();
break;
case R.id.button_snack:
Snackbar.make(this.findViewById(android.R.id.content),
"This is a snack", Snackbar.LENGTH_LONG).show();
break;
}
}
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Log.i(LOG_TAG, "Selector configuration changed");
switch (buttonView.getId()) {
case R.id.switch_toast_snack:
if( isChecked ) {
Snackbar.make(this.findViewById(android.R.id.content),
"Snackbar used at boot", Snackbar.LENGTH_LONG).show();
} else {
Toast.makeText(this, "Toast used at boot", Toast.LENGTH_SHORT)
.show();
}
break;
}
} // end onCheckedChanged
}
my build.gradle file
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
defaultConfig {
applicationId "com.eds.testtvapp"
minSdkVersion 24
targetSdkVersion 29
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.leanback:leanback:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'com.google.android.material:material:1.1.0'
}
and, just to be complete my styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="@style/Theme.Leanback" />
</resources>
and strings.xml
<resources>
<string name="app_name">TestTVApp</string>
<string name="app_data">APPLICATION_DATA</string>
<string name="app_data_start">FROM_BOOT</string>
<string name="config_switch_selection">TOAST_OR_SNACK</string>
<string name="config_switch_Default">false</string>
</resources>
For what i could see, nothing is (in terms of code) wrong against implementation receiving this broadcast message. Any hint would be welcome..
Thanks!!!