Xposed doesn't hook the method - xposed-framework

I need to make "Hello world" app for Xposed. I tried to change IMEI by Xposed. Some methods it hooked, some not. The question is how to hook them all?
I made test app that takes IMEI from TelephonyManager and shows it:
telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
tv.setText(telephonyManager.getDeviceId());
Than I write method to replace the method:
private void replaceImei(final XC_LoadPackage.LoadPackageParam loadPackageParam,
final String className,
final String methodName)
{
try {
XC_MethodHook.Unhook u =
XposedHelpers.findAndHookMethod(
className,
loadPackageParam.classLoader,
methodName,
new XC_MethodReplacement() {
#Override
protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
XposedBridge.log("happy replaced " + methodHookParam.method.getName()
+ " at " + methodHookParam.method.getDeclaringClass().getName());
return "123456789012345";
}
}
);
if (u != null) {
XposedBridge.log("happy hooked " + u.getHookedMethod().getName() + " "
+ u.getHookedMethod().getDeclaringClass().getCanonicalName());
}
} catch (Exception e) {
XposedBridge.log("happy error " + e.getMessage());
e.printStackTrace();
}
}
And used it:
#Override
public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
XposedBridge.log("happy loaded app: " + loadPackageParam.packageName);
replaceImei(loadPackageParam,
"android.telephony.TelephonyManager",
"getDeviceId");
}
It works!
But when I look at IMEI at the Settings app, it is unchanged. Ok, I took APK of the Settings app, extracted sources by apktool and found the following:
.line 86
const-string v1, "imei"
invoke-interface {v0}, Lcom/android/internal/telephony/Phone;->getImei()Ljava/lang/String;
move-result-object v2
invoke-direct {p0, v1, v2}, Lcom/android/settings/deviceinfo/ImeiInformation;->setSummaryText(Ljava/lang/String;Ljava/lang/String;)V
So, it uses getImei() method from the com.android.internal.telephony.Phone interface. Because it's impossible to hook methods of interface, I found in sources all implementations of this interface:
replaceImei(loadPackageParam,
"com.android.internal.telephony.PhoneProxy",
"getImei");
replaceImei(loadPackageParam,
"com.android.internal.telephony.PhoneBase",
"getImei");
replaceImei(loadPackageParam,
"com.android.internal.telephony.gsm.GSMPhone",
"getImei");
replaceImei(loadPackageParam,
"com.android.internal.telephony.imsphone.ImsPhone",
"getImei");
replaceImei(loadPackageParam,
"com.android.internal.telephony.cdma.CDMAPhone",
"getImei");
Logs has record that getImea() in PhoneProxy in the Settings app was hooked (look at the sources above):
I/Xposed ( 6800): happy loaded app: com.android.settings
I/Xposed ( 6800): happy hooked getDeviceId android.telephony.TelephonyManager
I/Xposed ( 6800): happy hooked getImei com.android.internal.telephony.PhoneProxy
But nothing happens, IMEI in Settings was unchanged. Of course, I installed the app and rebooted the phone every iteration.
Ok, I tried to bruteforce this task: I found some other methods and hooked them also. But it doesn't help.
replaceImei(loadPackageParam,
"com.android.internal.telephony.gsm.GSMPhone",
"getPhoneId");
replaceImei(loadPackageParam,
"com.android.internal.telephony.imsphone.ImsPhone",
"getPhoneId");
replaceImei(loadPackageParam,
"com.android.internal.telephony.cdma.CDMAPhone",
"getPhoneId");
replaceImei(loadPackageParam,
"com.android.internal.telephony.PhoneSubInfoController",
"getDeviceId");
replaceImei(loadPackageParam,
"com.android.internal.telephony.PhoneSubInfoController",
"getImeiForSubscriber");
replaceImei(loadPackageParam,
"com.android.internal.telephony.PhoneSubInfoController",
"getDeviceIdForPhone");
replaceImei(loadPackageParam,
"com.android.internal.telephony.PhoneSubInfo",
"getDeviceId");
replaceImei(loadPackageParam,
"com.android.internal.telephony.PhoneSubInfo",
"getImei");
replaceImei(loadPackageParam,
"com.android.internal.telephony.PhoneSubInfoProxy",
"getImeiForSubscriber");
replaceImei(loadPackageParam,
"com.android.internal.telephony.PhoneSubInfoProxy",
"getImei");
replaceImei(loadPackageParam,
"com.android.internal.telephony.PhoneBase",
"getPhoneId");
Is there any ideas? What wrong? And what to do?
All experiments was on Nexus 4 with Android 5.1.1.
The full source from this question is here: https://gist.github.com/tseglevskiy/d100898468b286e1fff214778c9609b3
Update 1
Next part of the experiment. I found that it is possible to hook some methods on early stage of the Zygote by implementing the IXposedHookZygoteInit interface. Ok, I did it:
private void replaceImeiInitZygote(final String className,
final String methodName)
{
try {
final Class<?> foundClass = XposedHelpers.findClass(className, null);
if (foundClass != null) {
XC_MethodHook.Unhook u = XposedHelpers.findAndHookMethod(foundClass, methodName,
new XC_MethodReplacement() {
#Override
protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
XposedBridge.log("happy replaced " + methodHookParam.method.getName()
+ " at " + methodHookParam.method.getDeclaringClass().getName());
return "123456789099999";
}
});
if (u != null) {
XposedBridge.log("happy hooked from initZygote " + u.getHookedMethod().getName() + " "
+ u.getHookedMethod().getDeclaringClass().getCanonicalName());
}
}
} catch (Exception e) {
XposedBridge.log("happy error " + e.getMessage());
e.printStackTrace();
}
}
And used it:
#Override
public void initZygote(StartupParam startupParam) throws Throwable {
replaceImeiInitZygote(
"android.telephony.TelephonyManager",
"getDeviceId");
replaceImeiInitZygote(
"com.android.internal.telephony.PhoneProxy",
"getImei");
replaceImeiInitZygote(
"com.android.internal.telephony.PhoneBase",
"getImei");
replaceImeiInitZygote(
"com.android.internal.telephony.gsm.GSMPhone",
"getImei");
replaceImeiInitZygote(
"com.android.internal.telephony.imsphone.ImsPhone",
"getImei");
replaceImeiInitZygote(
"com.android.internal.telephony.cdma.CDMAPhone",
"getImei");
}
By logs it hooks a few methods:
I/Xposed ( 198): happy hooked from initZygote getDeviceId android.telephony.TelephonyManager
I/Xposed ( 198): happy hooked from initZygote getImei com.android.internal.telephony.PhoneProxy
But id doesn't change IMEI in the Settings app also. What's wrong?

Well, you almost did it! You trying to hook getImei(), but actually it is never invoked by system. Use getDeviceId() instead, it returns the same data.
To change IMEI in settings try out this snippet, it works like a charm:
findAndHookMethod(
"com.android.internal.telephony.gsm.GSMPhone",
lpparam.classLoader,
"getDeviceId",
new XC_MethodReplacement() {
#Override
protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
XposedBridge.log("NEW IMEI!!! com.android.internal.telephony.gsm.GSMPhone.getDeviceId()");
return "111111111111111";
}
}
);
By the way, you can hook these methods too:
com.android.internal.telephony.PhoneSubInfo.getDeviceId()
com.android.internal.telephony.gsm.GSMPhone.getDeviceId()
com.android.internal.telephony.cdma.CDMAPhone.getDeviceId()
com.android.internal.telephony.imsphone.ImsPhone.getDeviceId()
com.android.internal.telephony.sip.SipPhone.getDeviceId()
Cheers!

Related

How to return object from retrofit api get call

I am trying to get list of objects from api call with retrofit but i just cant find the way to do so :(
This is the function i built:
private List<Business> businesses getBusinesses()
{
List<Business> businessesList = new ArrayList<>();
Call<List<Business>> call = jsonPlaceHolderApi.getBusinesses();
call.enqueue(new Callback<List<Business>>() {
#Override
public void onResponse(Call<List<Business>> call, Response<List<Business>> response) {
if(!response.isSuccessful())
{
textViewResult.setText("Code: " + response.code());
return;
}
List<Business> businesses = response.body();
for(Business business : businesses)
{
String content = "";
content += "ID: " + business.getId() + "\n";
content += "Name: " + business.getName() + "\n";
content += "On promotion: " + business.isOnPromotion() + "\n\n";
textViewResult.append(content);
}
businessesList = businesses;
}
#Override
public void onFailure(Call<List<Business>> call, Throwable t) {
call.cancel();
textViewResult.setText(t.getMessage());
}
});
}
I am trying to get the businesses response and return it.
can anyone help me?
Feeling frustrated :(
The way your executing the Retrofit call is asynchronous - using call.enqueue. there's nothing wrong with this approach. In fact it's perhaps the best option, since network calls can take a while and you don't want to block unnecessarily.
Unfortunately, this means you cannot return the result from the function. In most scenarios, if you did, the call would likely finish after the return making your return useless.
There are several ways to deal with this, the simplest one is to use callbacks. For example:
interface OnBusinessListReceivedCallback {
void onBusinessListReceived(List<Business> list);
}
private void businesses getBusinesses(OnBusinessListReceivedCallback callback){
Call<List<Business>> call = jsonPlaceHolderApi.getBusinesses();
call.enqueue(new Callback<List<Business>>() {
#Override
public void onResponse(Call<List<Business>> call, Response<List<Business>> response) {
if(!response.isSuccessful()){
textViewResult.setText("Code: " + response.code());
return;
}
callback.onBusinessListReceived(response.body());
}
#Override
public void onFailure(Call<List<Business>> call, Throwable t) {
call.cancel();
textViewResult.setText(t.getMessage());
}
});
}
You can then call it like so:
getBusinesses(new OnBusinessListReceivedCallback() {
public void onBusinessListReceived(List<Business> list){
// list holds your data
}
});

Real time GPS UWP

I really want to know how do I can update the position of the user in the map while the UWP app was running in bakground
Here is my code right now
private async void PinPoints()
{
//Pin point to the map
Windows.Devices.Geolocation.Geopoint position = await Library.Position();
double lat = position.Position.Latitude;
double lon = position.Position.Longitude;
//Geoposition alttest = await Library.Temp();
//alt = alttest.Coordinate.Altitude;
DependencyObject marker = Library.Marker(""
//+ Environment.NewLine + "Altitude " + alt
);
Display.Children.Add(marker);
Windows.UI.Xaml.Controls.Maps.MapControl.SetLocation(marker, position);
Windows.UI.Xaml.Controls.Maps.MapControl.SetNormalizedAnchorPoint(marker, new Point(0.5, 0.5));
Display.LandmarksVisible = true;
Display.ZoomLevel = 16;
Display.Center = position;
}
This function will pinpoint the current location for me but it will do only when user open this page due to I've put it in the public Map() {}
Current : Get the location when open map page and when I walk the map still be the same place
What I want : The position keep changing while I move on and also run on background (If application is close location data still changed)
Is there any code to solve this location problem if I have to add code where should I fix and what should I do?
Additional now I perform the background (Not sure is it work or not) by create the Window Runtime Component (Universal) with class like this
*I already put this project as the reference of the main one
namespace BackgroundRunning
{
public sealed class TaskBG : IBackgroundTask
{
BackgroundTaskDeferral _deferral = null;
Accelerometer _accelerometer = null;
Geolocator _locator = new Geolocator();
public void Run(IBackgroundTaskInstance taskInstance)
{
_deferral = taskInstance.GetDeferral();
try
{
// force gps quality readings
_locator.DesiredAccuracy = PositionAccuracy.High;
taskInstance.Canceled += taskInstance_Canceled;
_accelerometer = Windows.Devices.Sensors.Accelerometer.GetDefault();
_accelerometer.ReportInterval = _accelerometer.MinimumReportInterval > 5000 ? _accelerometer.MinimumReportInterval : 5000;
_accelerometer.ReadingChanged += accelerometer_ReadingChanged;
}
catch (Exception ex)
{
// Add your chosen analytics here
System.Diagnostics.Debug.WriteLine(ex);
}
}
void taskInstance_Canceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
{
_deferral.Complete();
}
async void accelerometer_ReadingChanged(Windows.Devices.Sensors.Accelerometer sender, Windows.Devices.Sensors.AccelerometerReadingChangedEventArgs args)
{
try
{
if (_locator.LocationStatus != PositionStatus.Disabled)
{
try
{
Geoposition pos = await _locator.GetGeopositionAsync();
}
catch (Exception ex)
{
if (ex.HResult != unchecked((int)0x800705b4))
{
System.Diagnostics.Debug.WriteLine(ex);
}
}
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex);
}
}
public void Dispose()
{
if (_accelerometer != null)
{
_accelerometer.ReadingChanged -= accelerometer_ReadingChanged;
_accelerometer.ReportInterval = 0;
}
}
}
}
Your Solution :
Make 3 projects in your solution.
1> Background Task "references App_Code"
2> App_Code "contains calculations,mostly Backend Code"
3> Map(Main Project) "references App_Code"
Register a background Task to your project and specify the time interval after which it should run again
Scenario 1> App Open,User Requests Update
Trigger Your background Task from code behind.
Scenario 2> App Closed,Not Being Used
Run your background task!
So basically keep your backgroundTask simple(make it a class in whose run method you just call the proper App_Code Classes Method) and all calculations that you want to happen in the background keep them in App_Code. Also, if I am no wrong the minimum interval between which a background Task is triggered by itself cannot be set below 15 minutes.
For real-time you could look at SignalR ( can't help any further here)

Unpredictable result of DriveId.getResourceId() in Google Drive Android API

The issue is that the 'resourceID' from 'DriveId.getResourceId()' is not available (returns NULL) on newly created files (product of 'DriveFolder.createFile(GAC, meta, cont)'). If the file is retrieved by a regular list or query procedure, the 'resourceID' is correct.
I suspect it is a timing/latency issue, but it is not clear if there is an application action that would force refresh. The 'Drive.DriveApi.requestSync(GAC)' seems to have no effect.
UPDATE (07/22/2015)
Thanks to the prompt response from Steven Bazyl (see comments below), I finally have a satisfactory solution using Completion Events. Here are two minified code snippets that deliver the ResourceId to the app as soon as the newly created file is propagated to the Drive:
File creation, add change subscription:
public class CreateEmptyFileActivity extends BaseDemoActivity {
private static final String TAG = "_X_";
#Override
public void onConnected(Bundle connectionHint) { super.onConnected(connectionHint);
MetadataChangeSet meta = new MetadataChangeSet.Builder()
.setTitle("EmptyFile.txt").setMimeType("text/plain")
.build();
Drive.DriveApi.getRootFolder(getGoogleApiClient())
.createFile(getGoogleApiClient(), meta, null,
new ExecutionOptions.Builder()
.setNotifyOnCompletion(true)
.build()
)
.setResultCallback(new ResultCallback<DriveFileResult>() {
#Override
public void onResult(DriveFileResult result) {
if (result.getStatus().isSuccess()) {
DriveId driveId = result.getDriveFile().getDriveId();
Log.d(TAG, "Created a empty file: " + driveId);
DriveFile file = Drive.DriveApi.getFile(getGoogleApiClient(), driveId);
file.addChangeSubscription(getGoogleApiClient());
}
}
});
}
}
Event Service, catches the completion:
public class ChngeSvc extends DriveEventService {
private static final String TAG = "_X_";
#Override
public void onCompletion(CompletionEvent event) { super.onCompletion(event);
DriveId driveId = event.getDriveId();
Log.d(TAG, "onComplete: " + driveId.getResourceId());
switch (event.getStatus()) {
case CompletionEvent.STATUS_CONFLICT: Log.d(TAG, "STATUS_CONFLICT"); event.dismiss(); break;
case CompletionEvent.STATUS_FAILURE: Log.d(TAG, "STATUS_FAILURE"); event.dismiss(); break;
case CompletionEvent.STATUS_SUCCESS: Log.d(TAG, "STATUS_SUCCESS "); event.dismiss(); break;
}
}
}
Under normal circumstances (wifi), I get the ResourceId almost immediately.
20:40:53.247﹕Created a empty file: DriveId:CAESABiiAiDGsfO61VMoAA==
20:40:54.305: onComplete, ResourceId: 0BxOS7mTBMR_bMHZRUjJ5NU1ZOWs
... done for now.
ORIGINAL POST, deprecated, left here for reference.
I let this answer sit for a year hoping that GDAA will develop a solution that works. The reason for my nagging is simple. If my app creates a file, it needs to broadcast this fact to its buddies (other devices, for instance) with an ID that is meaningful (that is ResourceId). It is a trivial task under the REST Api where ResourceId comes back as soon as the file is successfully created.
Needles to say that I understand the GDAA philosophy of shielding the app from network primitives, caching, batching, ... But clearly, in this situation, the ResourceID is available long before it is delivered to the app.
Originally, I implemented Cheryl Simon's suggestion and added a ChangeListener on a newly created file, hoping to get the ResourceID when the file is propagated. Using classic CreateEmptyFileActivity from android-demos, I smacked together the following test code:
public class CreateEmptyFileActivity extends BaseDemoActivity {
private static final String TAG = "CreateEmptyFileActivity";
final private ChangeListener mChgeLstnr = new ChangeListener() {
#Override
public void onChange(ChangeEvent event) {
Log.d(TAG, "event: " + event + " resId: " + event.getDriveId().getResourceId());
}
};
#Override
public void onConnected(Bundle connectionHint) { super.onConnected(connectionHint);
MetadataChangeSet meta = new MetadataChangeSet.Builder()
.setTitle("EmptyFile.txt").setMimeType("text/plain")
.build();
Drive.DriveApi.getRootFolder(getGoogleApiClient())
.createFile(getGoogleApiClient(), meta, null)
.setResultCallback(new ResultCallback<DriveFileResult>() {
#Override
public void onResult(DriveFileResult result) {
if (result.getStatus().isSuccess()) {
DriveId driveId = result.getDriveFile().getDriveId();
Log.d(TAG, "Created a empty file: " + driveId);
Drive.DriveApi.getFile(getGoogleApiClient(), driveId).addChangeListener(getGoogleApiClient(), mChgeLstnr);
}
}
});
}
}
... and was waiting for something to happen. File was happily uploaded to the Drive within seconds, but no onChange() event. 10 minutes, 20 minutes, ... I could not find any way how to make the ChangeListener to wake up.
So the only other solution, I could come up was to nudge the GDAA. So I implemented a simple handler-poker that tickles the metadata until something happens:
public class CreateEmptyFileActivity extends BaseDemoActivity {
private static final String TAG = "CreateEmptyFileActivity";
final private ChangeListener mChgeLstnr = new ChangeListener() {
#Override
public void onChange(ChangeEvent event) {
Log.d(TAG, "event: " + event + " resId: " + event.getDriveId().getResourceId());
}
};
static DriveId driveId;
private static final int ENOUGH = 4; // nudge 4x, 1+2+3+4 = 10seconds
private static int mWait = 1000;
private int mCnt;
private Handler mPoker;
private final Runnable mPoke = new Runnable() { public void run() {
if (mPoker != null && driveId != null && driveId.getResourceId() == null && (mCnt++ < ENOUGH)) {
MetadataChangeSet meta = new MetadataChangeSet.Builder().build();
Drive.DriveApi.getFile(getGoogleApiClient(), driveId).updateMetadata(getGoogleApiClient(), meta).setResultCallback(
new ResultCallback<DriveResource.MetadataResult>() {
#Override
public void onResult(DriveResource.MetadataResult result) {
if (result.getStatus().isSuccess() && result.getMetadata().getDriveId().getResourceId() != null)
Log.d(TAG, "resId COOL " + result.getMetadata().getDriveId().getResourceId());
else
mPoker.postDelayed(mPoke, mWait *= 2);
}
}
);
} else {
mPoker = null;
}
}};
#Override
public void onConnected(Bundle connectionHint) { super.onConnected(connectionHint);
MetadataChangeSet meta = new MetadataChangeSet.Builder()
.setTitle("EmptyFile.txt").setMimeType("text/plain")
.build();
Drive.DriveApi.getRootFolder(getGoogleApiClient())
.createFile(getGoogleApiClient(), meta, null)
.setResultCallback(new ResultCallback<DriveFileResult>() {
#Override
public void onResult(DriveFileResult result) {
if (result.getStatus().isSuccess()) {
driveId = result.getDriveFile().getDriveId();
Log.d(TAG, "Created a empty file: " + driveId);
Drive.DriveApi.getFile(getGoogleApiClient(), driveId).addChangeListener(getGoogleApiClient(), mChgeLstnr);
mCnt = 0;
mPoker = new Handler();
mPoker.postDelayed(mPoke, mWait);
}
}
});
}
}
And voila, 4 seconds (give or take) later, the ChangeListener delivers a new shiny ResourceId. Of course, the ChangeListener becomes thus obsolete, since the poker routine gets the ResourceId as well.
So this is the answer for those who can't wait for the ResourceId. Which brings up the follow-up question:
Why do I have to tickle metadata (or re-commit content), very likely creating unnecessary network traffic, to get onChange() event, when I see clearly that the file has been propagated a long time ago, and GDAA has the ResourceId available?
ResourceIds become available when the newly created resource is committed to the server. In the case of a device that is offline, this could be arbitrarily long after the initial file creation. It will happen as soon as possible after the creation request though, so you don't need to do anything to speed it along.
If you really need it right away, you could conceivably use the change notifications to listen for the resourceId to change.

GCM works on 4.1 but doesn't work on 2.3 android version

I am having problem with GCM, it works just fine on Nexus 7 but when I run it on any device with Gingerbread version onRegistered method is never called.
See my code implementation belowe:
GMCIntentService
public class GCMIntentService extends GCMBaseIntentService {
private static final String TAG = "GCMIntentService";
private RestHelper restRegisterGCM;
private String userRegisterGCMUrl = "User/SetGcm";
public GCMIntentService() {
super(AppSettings.SENDER_ID);
}
/**
* Method called on device registered
**/
#Override
protected void onRegistered(Context context, String registrationId) {
Log.i(TAG, "Device registered: regId = " + registrationId);
// Util.displayMessage(context, "Your device registred with GCM");
if (!GCMRegistrar.isRegisteredOnServer(this)) {
restRegisterGCM = new RestHelper(userRegisterGCMUrl, RequestMethod.POST, context);
restRegisterGCM.setHeader("UserName", AppSettings.getInstance().getUsername(context));
restRegisterGCM.setHeader("Password", AppSettings.getInstance().getPassword(context));
restRegisterGCM.setParameter("regId", registrationId);
restRegisterGCM.execute();
}
}
/**
* Method called on device un registred
* */
#Override
protected void onUnregistered(Context context, String registrationId) {
Log.i(TAG, "Device unregistered");
}
/**
* Method called on Receiving a new message
* */
#Override
protected void onMessage(Context context, Intent intent) {
Log.i(TAG, "Received message");
String message = intent.getExtras().getString("Message");
// notifies user
generateNotification(context, message);
}
/**
* Method called on receiving a deleted message
* */
#Override
protected void onDeletedMessages(Context context, int total) {
Log.i(TAG, "Received deleted messages notification");
}
/**
* Method called on Error
* */
#Override
public void onError(Context context, String errorId) {
Log.i(TAG, "Received error: " + errorId);
Toast.makeText(context, getString(R.string.gcm_error, errorId), Toast.LENGTH_SHORT).show();
}
#Override
protected boolean onRecoverableError(Context context, String errorId) {
// log message
Log.i(TAG, "Received recoverable error: " + errorId);
Toast.makeText(context, getString(R.string.gcm_recoverable_error, errorId), Toast.LENGTH_SHORT).show();
return super.onRecoverableError(context, errorId);
}
GMC registration method
private void registerGCM() {
// Make sure the device has the proper dependencies.
GCMRegistrar.checkDevice(this);
Boolean accountExists = false;
AccountManager am = AccountManager.get(getApplicationContext());
Account[] accounts = am.getAccounts();
for (Account account : accounts) {
if (account.type.equals("com.google")) {
accountExists = true;
break;
}
}
if (accountExists) {
// Get GCM registration id
String regId = GCMRegistrar.getRegistrationId(this);
// Check if regid already presents
if (regId.equals("")) {
// Registration is not present, register now with GCM
GCMRegistrar.register(this, AppSettings.SENDER_ID);
} else {
// Device is already registered on GCM
if (!GCMRegistrar.isRegisteredOnServer(this)) {
restRegisterGCM = new RestHelper(userRegisterGCMUrl, RequestMethod.POST, EvadoFilipActivity.this);
restRegisterGCM.setHeader("UserName", AppSettings.getInstance().getUsername(EvadoFilipActivity.this));
restRegisterGCM.setHeader("Password", AppSettings.getInstance().getPassword(EvadoFilipActivity.this));
restRegisterGCM.setParameter("regId", regId);
restRegisterGCM.setPostExecuteMethod(2);
restRegisterGCM.execute();
}
}
} else
Toast.makeText(this, R.string.gcm_google_account_missing, Toast.LENGTH_SHORT).show();
}
UPDATE:
I have renamed packages and forget to change it in my class:
public class GCMBroadcastReceiver extends com.google.android.gcm.GCMBroadcastReceiver{
#Override
protected String getGCMIntentServiceClassName(Context context) {
return "com.mypackage.services.GCMIntentService";
}
}
I had the very same problem.My code would work on nexus4(Kitkat) but would fail to get me a notification from the appln server(via gcm server).#Fr0g is correct for versions less that 4.0.4 you should make sure that you have your google account setup on your device for gcm to work.
I had google account on my galaxy ace(2.3.4) but the mistake I made was that my Account and Sync settings in my galaxy ace was 'Off'.When I turned it ON and ran my code, i received the notification.
Ensure that you have set up a user account on the device that you are testing on. GCM requires that a google account must be setup on the device that is registering for GCM, (also I think that this requirements is for android versions < 4.0)

Load external properties files into EJB 3 app running on WebLogic 11

Am researching the best way to load external properties files from and EJB 3 app whose EAR file is deployed to WebLogic.
Was thinking about using an init servlet but I read somewhere that it would be too slow (e.g. my message handler might receive a message from my JMS queue before the init servlet runs).
Suppose I have multiple property files or one file here:
~/opt/conf/
So far, I feel that the best possible solution is by using a Web Logic application lifecycle event where the code to read the properties files during pre-start:
import weblogic.application.ApplicationLifecycleListener;
import weblogic.application.ApplicationLifecycleEvent;
public class MyListener extends ApplicationLifecycleListener {
public void preStart(ApplicationLifecycleEvent evt) {
// Load properties files
}
}
See: http://download.oracle.com/docs/cd/E13222_01/wls/docs90/programming/lifecycle.html
What would happen if the server is already running, would post start be a viable solution?
Can anyone think of any alternative ways that are better?
It really depends on how often you want the properties to be reloaded. One approach I have taken is to have a properties file wrapper (singleton) that has a configurable parameter that defines how often the files should be reloaded. I would then always read properties through that wrapper and it would reload the properties ever 15 minutes (similar to Log4J's ConfigureAndWatch). That way, if I wanted to, I can change properties without changing the state of a deployed application.
This also allows you to load properties from a database, instead of a file. That way you can have a level of confidence that properties are consistent across the nodes in a cluster and it reduces complexity associated with managing a config file for each node.
I prefer that over tying it to a lifecycle event. If you weren't ever going to change them, then make them static constants somewhere :)
Here is an example implementation to give you an idea:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.*;
/**
* User: jeffrey.a.west
* Date: Jul 1, 2011
* Time: 8:43:55 AM
*/
public class ReloadingProperties
{
private final String lockObject = "LockMe";
private long lastLoadTime = 0;
private long reloadInterval;
private String filePath;
private Properties properties;
private static final Map<String, ReloadingProperties> instanceMap;
private static final long DEFAULT_RELOAD_INTERVAL = 1000 * 60 * 5;
public static void main(String[] args)
{
ReloadingProperties props = ReloadingProperties.getInstance("myProperties.properties");
System.out.println(props.getProperty("example"));
try
{
Thread.sleep(6000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println(props.getProperty("example"));
}
static
{
instanceMap = new HashMap(31);
}
public static ReloadingProperties getInstance(String filePath)
{
ReloadingProperties instance = instanceMap.get(filePath);
if (instance == null)
{
instance = new ReloadingProperties(filePath, DEFAULT_RELOAD_INTERVAL);
synchronized (instanceMap)
{
instanceMap.put(filePath, instance);
}
}
return instance;
}
private ReloadingProperties(String filePath, long reloadInterval)
{
this.reloadInterval = reloadInterval;
this.filePath = filePath;
}
private void checkRefresh()
{
long currentTime = System.currentTimeMillis();
long sinceLastLoad = currentTime - lastLoadTime;
if (properties == null || sinceLastLoad > reloadInterval)
{
System.out.println("Reloading!");
lastLoadTime = System.currentTimeMillis();
Properties newProperties = new Properties();
FileInputStream fileIn = null;
synchronized (lockObject)
{
try
{
fileIn = new FileInputStream(filePath);
newProperties.load(fileIn);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if (fileIn != null)
{
try
{
fileIn.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
properties = newProperties;
}
}
}
public String getProperty(String key, String defaultValue)
{
checkRefresh();
return properties.getProperty(key, defaultValue);
}
public String getProperty(String key)
{
checkRefresh();
return properties.getProperty(key);
}
}
Figured it out...
See the corresponding / related post on Stack Overflow.