I have the following Reciever and I get an app crash on device boot.
Since it happens on boot I cannot attach the debug via eclipse nor see anything in the logcat.
How would you suggest for me to see the error causing the crash?
public class BootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context arg0, Intent intent) {
// TODO Auto-generated method stub
if (intent != null) {
String action = intent.getAction();
if (action != null) {
if (action.equalsIgnoreCase(Intent.ACTION_BOOT_COMPLETED)) {
// GeoPushService geoPs = new GeoPushService();
ZoomerLocationService locService = new ZoomerLocationService();
locService.startService(new Intent());
// Log.d("receiver","action is: boot");
}
}
}
}
}
I have tried adding this try-catch
public class BootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context arg0, Intent intent) {
// TODO Auto-generated method stub
if (intent != null) {
String action = intent.getAction();
try {
if (action != null) {
if (action.equalsIgnoreCase(Intent.ACTION_BOOT_COMPLETED)) {
// GeoPushService geoPs = new GeoPushService();
ZoomerLocationService locService = new ZoomerLocationService();
locService.startService(new Intent());
// Log.d("receiver","action is: boot");
}
}
} catch (Exception ex) {
Log.e(MyLogger.TAG, ex.getStackTrace().toString());
}
}
}
}
but it didn't help
I have tried to send BOOT_COMPLETE intent and i got permissions denial
You might be able to use ADB in a command line to record the logcat when your device is booting up.
http://developer.android.com/tools/help/logcat.html
http://www.herongyang.com/Android/Debug-adb-logcat-Command-Option-Log-Buffer.html
Make sure to increase the amount of data the command window can display or else use the options to save the log to a file.
Using this method you might be able to see the crash in the log on startup.
EDIT: I have tried this and it is possible, this should work for you
Related
I want to update my app immediately every time I publish an update. I followed the instructions from the official android documentation on how to test the auto update feature , but nothing happens. I placed some logs in order to check whether these functions initialize, but the logcat shows nothing either. Is this a problem in my syntax, or should I place these functions somewhere else? Currently, all my update code is written inside the main, starting class of the app.
On create method of the class
private static final int REQUEST_APP_UPDATE = 560;
private AppUpdateManager appUpdateManager;
private InstallStateUpdatedListener installStateUpdatedListener;
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
appUpdateManager = AppUpdateManagerFactory.create(this);
installStateUpdatedListener = new
InstallStateUpdatedListener() {
#Override
public void onStateUpdate(InstallState state) {
if (state.installStatus() == InstallStatus.DOWNLOADED){
} else if (state.installStatus() == InstallStatus.INSTALLED){
if (appUpdateManager != null){
appUpdateManager.unregisterListener(installStateUpdatedListener);
}
} else {
Log.i(TAG, "InstallStateUpdatedListener: state: " + state.installStatus());
}
}
};
appUpdateManager
.getAppUpdateInfo()
.addOnSuccessListener(
appUpdateInfo -> {
Log.d("TAG", "here");
// Checks that the platform will allow the specified type of update.
if ((appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE)
&& appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE))
{
// Request the update.
try {
Log.d("TAG", "here");
appUpdateManager.startUpdateFlowForResult(
appUpdateInfo,
AppUpdateType.IMMEDIATE,
this,
REQUEST_APP_UPDATE);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
}
});
appUpdateManager.registerListener(installStateUpdatedListener);
...
On resume and on stop handling methods:
#Override
protected void onResume() {
super.onResume();
appUpdateManager
.getAppUpdateInfo()
.addOnSuccessListener(
appUpdateInfo -> {
if (appUpdateInfo.updateAvailability()
== UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS) {
// If an in-app update is already running, resume the update.
try {
appUpdateManager.startUpdateFlowForResult(
appUpdateInfo,
AppUpdateType.IMMEDIATE,
this,
REQUEST_APP_UPDATE);
Log.d("TAG", "tu");
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
}
});
}
#Override
protected void onStop() {
super.onStop();
if (appUpdateManager != null) {
appUpdateManager.unregisterListener(installStateUpdatedListener);
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_APP_UPDATE) {
if (resultCode != RESULT_OK) {
Log.d("TAG", "Update flow failed! Result code: " + resultCode);
// If the update is cancelled or fails,
// you can request to start the update again.
}
}
}
I suggest you to move all your AppUpdateInfo retrieving to onResume() since it is more reliable entry point of an activity (for example, if Activity has came to background and then was opened again by user). OnCreate method will be called only if activity was destroyed, since that, you may not see update dialog after reopening application if it was minimized.
#Override
public void onResume() {
super.onResume();
appUpdateManager.getAppUpdateInfo().addOnSuccessListener( info -> {
boolean isStalledUpdate = info.updateAvailability() == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS;
boolean isReadyForUpdate =
info.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
&& info.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE;
if (isReadyForUpdate || isStalledUpdate) {
appUpdateManager.startUpdateFlowForResult(
info,
AppUpdateType.IMMEDIATE,
this,
REQ_CODE
);
}
}
Sometimes app is not automatically synchronized with Play Store updates, so you need to do the following:
Make sure you have an update available manually - go to Play Store, check for updates and make sure that you have an update available for your application.
After that open your app (your activity, that calls update manager in onResume) and you will see immediate update dialog.
Also, one tip for you - make your Activity implement InstallStateUpdateListener and override method onStateUpdate like this to handle different events.
#Override
public void onResume() {
// All previous logic
// If update is available or was stalled call this
appUpdateManager.registerListener(this);
}
#Override
public void onStateUpdate(InstallState state) {
if (state == null) return;
switch (state.installStatus()) {
case InstallStatus.INSTALLED:
appUpdateManager.unregisterListener(this)
return;
case InstallStatus.FAILED:
appUpdateManager.unregisterListener(this)
return;
case InstallStatus.CANCELED:
appUpdateManager.unregisterListener(this)
return;
default:
// provide your own logic
return;
}
}
This will help you to avoid calling separate instance of listener in activity lifecycle methods.
The code that I provided was working, the problem of not updating was a matter of the device itself not knowing whether an update is available. After refreshing the update list on the Play Store, the app update manager initialized the auto update window when starting the app.
I'm trying to check if an app is accessing the camera (even in the background) in Android, and I'm using a service to do that.
That's my service code:
public class BackgroundService extends Service {
#Nullable
Context context;
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
Toast.makeText(this, "Service started!", Toast.LENGTH_LONG).show();
if (isCameraUsedbyApp()){
Toast.makeText(this, "Camera is used!", Toast.LENGTH_LONG).show();
}
}
#Override
public void onDestroy() {
Toast.makeText(this, "Service stopped!", Toast.LENGTH_LONG).show();
}
public boolean isCameraUsedbyApp() {
Camera camera = null;
try {
camera = Camera.open();
} catch (RuntimeException e) {
return true;
} finally {
if (camera != null) camera.release();
}
return false;
}
}
I've followed the answers to these questions:
How to check if camera is opened by any application
How to check if android.hardware.Camera is released?
But without success, in fact the service always says that camera is used, also when it isn't.
In addition, I'm trying to get the app that is using camera (if it is used), but I cannot find some references to that in Android developers docs (official one).
Can you please help me? If you need further information you've only to ask
Regards,
F.
Background
I am creating a service that syncs a local Realm database (stored on phone) with an online database. The database stores users and measurements.
I initialise the service by calling 'startService(new Intent(this, SyncService.class));' during the splash activity's onCreate() method, and specify in the manifest that the service should run for the length of the application.
The service has a broadcast receiver. When the receiver detects a network change from 'not connected' to 'connected', it fires a method called syncDatabases().
This method finds all measurements recorded locally after the timestamp of the last API callback, and sends them to the database. The API responds to a request by returning the object + a unique ID.
When a measurement is made whilst the device is offline, it is stored locally. When an internet connection is made, the syncDatabases() method should be called in order to update the online server with the local measurements.
My steps...
Steps when debugging the project:
With wifi I open the app and with an external device make a new measurement. This appears on both the app and in the database. I then turn wifi off and make another measurement - this appears on the device.
I attach the debugger.
I turn back on wifi and this triggers the services' receivers' onReceive() method. I step through this and it all works according to plan. I reach the syncDatabases() method, and from there I receive the callback from the API, and it then updates the Realm database with the new ID value.
The problem...
If I don't attach the debugger, nothing happens. The new measurements aren't pushed to the database, and none of my Log.e calls are printed.
Why is this happening? And is there an alternative solution / fix for this problem?
Code
Service class
public class SyncService extends Service {
private static final String TAG = "SYNCSERVICE";
private boolean mConnected = false;
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getExtras() != null) {
final ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo();
if (netInfo != null) {
switch (netInfo.getState()) {
case CONNECTED:
if (!mConnected) {
Log.e("NETWORK", "Network " + netInfo.getTypeName() + " now connected");
syncDatabases();
mConnected = true;
}
break;
default:
mConnected = false;
break;
}
} else mConnected = false;
}
}
};
#Override
public void onCreate() {
super.onCreate();
initReceiver();
ConnectivityManager connectivityManager = (ConnectivityManager) getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivityManager.getActiveNetworkInfo() != null) {
mConnected = true;
}
android.util.Log.e(TAG, "onCreate: SyncService created");
}
#Override
public void onDestroy() {
super.onDestroy();
unInitReceiver();
android.util.Log.e(TAG, "onDestroy: SyncService destroyed");
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
android.util.Log.e(TAG, "onBind: SyncService bound");
return null;
}
#Override
public boolean onUnbind(Intent intent) {
android.util.Log.e(TAG, "onUnbind: SyncService unbound");
return super.onUnbind(intent);
}
#Override
public void onRebind(Intent intent) {
super.onRebind(intent);
android.util.Log.e(TAG, "onRebind: SyncService rebound");
}
private void initReceiver() {
IntentFilter filters = new IntentFilter();
filters.addAction("android.net.wifi.WIFI_STATE_CHANGED");
filters.addAction("android.net.wifi.STATE_CHANGE");
registerReceiver(mReceiver, filters);
}
private void unInitReceiver() {
unregisterReceiver(mReceiver);
}
public void syncDatabases() {
RealmResults<UserDB> users = RealmDB.getInstance(getApplicationContext()).where(UserDB.class).findAll();
if (users.size() > 0) {
int userId = users.get(0).getmUserID();
Log.e("MESSAGE", PreferenceUtils.getInstance().getLastSyncDate());
Date lastSync = null;
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.getDefault());
try {
lastSync = sdf.parse(PreferenceUtils.getInstance().getLastSyncDate());
}
catch (ParseException e) {
e.printStackTrace();
try {
lastSync = BaseFragment.FORMAT.parse(PreferenceUtils.getInstance().getLastSyncDate());
}
catch (ParseException e1) {
e1.printStackTrace();
}
}
if (lastSync != null) {
Date lastSyncOffset = new Date(lastSync.getTime() + 1000);
/** Get all local results which have been made after the last sync date
**/
RealmResults<MeasurementDB> newLocalMeasurements = RealmDB.getInstance(getApplicationContext())
.where(MeasurementDB.class).equalTo("user_ID", userId)
.greaterThan("dateCreated", lastSyncOffset)
.findAll();
/** For each measurement made after the last sync, add it to the server
**/
for (MeasurementDB measurement : newLocalMeasurements) {
TemperatureListener mListener = new TemperatureListener(measurement);
ApiRequest.getInstance(getApplicationContext()).registerNewMeasurement(measurement.getAverage(),
measurement.getDateCreated().toString(), mListener, mListener);
}
}
}
}
/**
* Temperature listener receives the local copy of the temperature item. onResponse can then
* directly mutate the object instead of searching local db
*/
private class TemperatureListener implements Response.Listener<Measurement>, Response.ErrorListener {
private MeasurementDB measurement;
public TemperatureListener(MeasurementDB measurement) {
this.measurement = measurement;
}
#Override
public void onErrorResponse(VolleyError error) {
Log.e("OnResponse", "Failure");
}
#Override
public void onResponse(Measurement response) {
Log.e("OnResponse", "Success");
/** Update our local measurement's ID value (supplied by server)
**/
RealmDB.getInstance(getApplicationContext()).beginTransaction();
measurement.setMeasurement_ID(response.getmMeasurementId());
RealmDB.getInstance(getApplicationContext()).commitTransaction();
/** Update the last sync date
**/
PreferenceUtils.getInstance().setLastSyncDate(response.getmDateCreated());
}
}
}
Initialisation of Service in splash activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
mTimedOut = true;
finishActivity();
}
}, DURATION);
/** Will sync application / cloud databases in background of app when network connected. **/
startService(new Intent(this, SyncService.class));
doApiWork();
}
Manifest entry
Stop with task to kill the service at the same time as the app.
Exported 'false' stops other apps from using the service.
<service
android:name=".network.SyncService"
android:stopWithTask="true"
android:enabled="true"
android:exported="false"/>
EDIT
I removed the service and left a receiver class, registered in the manifest, which triggers methods on another class when needed. However the receiver is only triggered in debug mode.
I am making a simple client-server application which can be used to transfer integers, strings or characters.
My application compiled successfully, but no client-server connection is there.
When I try to search for a server, it gives the NullPointerException on the line
bluetooth.startDiscovery();
However, when I start the server it gives no exception.
Also, when I start a server on one device and look for a server on another, a connection is not established either due to a problem in server running correctly or a problem in the client.
I have already got an instance of BluetoothAdapter using
bluetooth = BluetoothAdapter.getDefaultAdapter();
I think that probably a null pointer is given because i am calling the method startDiscovery() inside an onclickListener, this one,
private void setupSearchButton() {
Button searchButton = (Button) findViewById(R.id.button_search);
searchButton.setOnClickListener(new OnClickListener() {
public void onClick(View view) {
registerReceiver(discoveryResult, new IntentFilter(BluetoothDevice.ACTION_FOUND));
if (!bluetooth.isDiscovering()) {
try { foundDevices.clear();
bluetooth.startDiscovery(); } catch(Exception e)
{
Context c = getApplicationContext();
Toast.makeText(c, e.toString(),Toast.LENGTH_LONG).show();
}
}
}
});
}
The code for declaring a server is posted here :
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == DISCOVERY_REQUEST) {
boolean isDiscoverable = resultCode > 0;
if (isDiscoverable) {
String name = "bluetoothserver";
try {
final BluetoothServerSocket btserver = bluetooth.listenUsingRfcommWithServiceRecord(name, uuid);
AsyncTask<Integer, Void, BluetoothSocket> acceptThread = new AsyncTask<Integer, Void, BluetoothSocket>() {
#Override
protected BluetoothSocket doInBackground(Integer... params) {
try {
socket = btserver.accept(params[0] * 1000);
return socket;
} catch (Exception e) {
Log.d("BLUETOOTH SERVER EXCEPTION : ", e.getMessage());
}
return null;
}
#Override
protected void onPostExecute(BluetoothSocket result) {
if (result != null) {
switchUI();
}
}
};
acceptThread.execute(resultCode);
} catch (IOException e) {
Log.d("BLUETOOTH", e.getMessage());
}
}
}
}
Can someone tell me what is the problem ? I am using two buttons, one to start a bluetooth server and other to search for a bluetooth server. The method that runs on clicking the start bluetooth server button triggers startActivityForResult, as a result of which the method onActivityResult is executed as shown here. The OnClickListener for search server button is already shown here.
public class Unistallreceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
String action = intent.getAction();
if (action == null)
Log.e("uninstall ", "Action==null!");
else if ("android.intent.action.BOOT_COMPLETED".equals(action)) {
Log.e("uninstall ", "action :"+action);
}
}
}
Doing something like this, but can't get notification.Reference said :
public static final String ACTION_PACKAGE_REMOVED
Since: API Level 1
Broadcast Action: An existing application package has been removed from the device. The data contains the name of the package. The package that is being installed does not receive this Intent
A need this intent to set uninstall password.
Any suggestions??
Get rid of the "set uninstall password" requirement.