Null Pointer Exception on Query Inventory - javascript

I am trying to set up in-app billing in my application. I have it in alpha testing. I keep getting crash reports from all my testers with the same logcat, shown here:
java.lang.RuntimeException: Unable to start activity
ComponentInfo{autonote.six.padc.autonote/autonote.six.padc.autonote.SaveScreen}:
java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2305)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2359)
at android.app.ActivityThread.access$700(ActivityThread.java:165)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1326)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5455)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1187)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at autonote.six.padc.autonote.SaveScreen.onCreate(SaveScreen.java:59)
at android.app.Activity.performCreate(Activity.java:5372)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1104)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2267)
... 11 more
It seems like a simple solution, just go to Line Line 59, right? Wrong. When I go there, the line that is throwing the exception is:
mHelper.queryInventoryAsync(mGotInventoryListener);
And this is where I lose it.
Here are the relevant parts of my code:
public class SaveScreen extends ActionBarActivity {
Button EMAIL_NOTES;
IabHelper mHelper;
String UPGRADE_CODE = "upgrade_autonote";
public static int VERSION_NUMBER = 534985739;
boolean mIsPremium;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_savescreen);
//Query Inventory to see if user is premium
IabHelper.QueryInventoryFinishedListener mGotInventoryListener
= new IabHelper.QueryInventoryFinishedListener() {
public void onQueryInventoryFinished(IabResult result,
Inventory inventory) {
if (result.isFailure()) {
// handle error here
}
else {
// does the user have the premium upgrade?
mIsPremium = inventory.hasPurchase(UPGRADE_CODE);
VERSION_NUMBER = 434975736;
}
}
};
mHelper.queryInventoryAsync(mGotInventoryListener);
//^^^^^^^^^^^^^^^null pointer^^^^^^^^^^^^^^^^^^^^^^^^
EMAIL_NOTES.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(VERSION_NUMBER == 534985736){
Toast.makeText(getBaseContext(), "You must upgrade to unlock this feature", Toast.LENGTH_LONG).show();
}else if(VERSION_NUMBER == 434975739){
Intent EMAIL_NOTES = new Intent(getBaseContext(), Email_Notes.class);
EMAIL_NOTES.putExtra("serialized",cNotes_serialized);
EMAIL_NOTES.putExtra("class_Name", cName);
startActivity(EMAIL_NOTES);
}
}
});
}
Any ideas how to fix this issue? For the record I already went in and bought the product. It said the purchase was successful. Thanks everyone!

here:
mHelper.queryInventoryAsync(mGotInventoryListener);
NPE because mHelper is null.
Initialize mHelper object by calling IabHelper constructor with current Acitivty context and with public key:
mHelper = new IabHelper(this, base64EncodedPublicKey);
For more information What is base64EncodedPublicKey? see:
Preparing Your In-app Billing Application

Related

How to draw over other apps in React-native?

I need to have something similar to Facebook Messenger's chat heads in my app, basically a bubble that can be viewed over other apps. I can't find anything online on this topic besides this question. So is there any way to make something like this with RN?
this feature is not support directly from react native and also this is not supported in ios therefore only you could implement it with java native code in android. to do that you should write a service in android which handle this element life cycle.
You could find here simple implementation of that in an android project. it's such a straightforward example and you can use it's service for your react native project and just change it's xml file to customize your view.
And just to start your service you must write a very simple react native module look like this
#ReactMethod
public void startService(Promise promise) {
String result = "Success";
Activity activity = getCurrentActivity();
if (activity != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(getReactApplicationContext())) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getCurrentActivity().getPackageName()));
getCurrentActivity().startActivityForResult(intent, MainActivity.DRAW_OVER_OTHER_APP_PERMISSION_REQUEST_CODE);
}
}
try {
Intent intent = new Intent(FloatingWidgetService.FLOATING_WIDGET_ID);
intent.setClass(this.getReactApplicationContext(), FloatingWidgetService.class);
getReactApplicationContext().startService(intent);
FloatingWidgetService.setUri(uri);
} catch (Exception e) {
promise.reject(e);
return;
}
promise.resolve(result);
}
in Android-8Oreo you must ask for canDrawOverlays and you can wait for result in your MainActivity like this:
private static final int DRAW_OVER_OTHER_APP_PERMISSION_REQUEST_CODE = 1222;
....
private void startFloatingWidgetService() {
if (!mStarted) {
Intent intent = new Intent(this, FloatingWidgetService.class);
ContextCompat.startForegroundService(this, intent);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
this.startForegroundService(intent);
}else{
startService(intent);
}
mStarted = true;
finish();
}
}
....
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == DRAW_OVER_OTHER_APP_PERMISSION_REQUEST_CODE) {
//Check if the permission is granted or not.
if (resultCode == RESULT_OK)
//If permission granted start floating widget service
startFloatingWidgetService();
else
//Permission is not available then display toast
Toast.makeText(this,
getResources().getString(R.string.draw_other_app_permission_denied),
Toast.LENGTH_SHORT).show();
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
And after that to come back again to your app from that service with the same appstate(not to create new activity) first define your activity launchmode as a singleInstance in manifest:
<activity
...
android:launchMode="singleInstance"
...
>
And use this kind of intent(!) in your service:
ReactApplicationContext reactContext = VideoViewModule.getReactContext();
Intent activityIntent = createSingleInstanceIntent();
reactContext.startActivity(activityIntent);
private Intent createSingleInstanceIntent() {
ReactApplicationContext reactContext = VideoViewModule.getReactContext();
String packageName = reactContext.getPackageName();
Intent launchIntent = reactContext.getPackageManager().getLaunchIntentForPackage(packageName);
String className = launchIntent.getComponent().getClassName();
Intent activityIntent = null;
try {
Class<?> activityClass = Class.forName(className);
activityIntent = new Intent(reactContext, activityClass);
activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
} catch (Exception e) {
stopCurrentService();
Log.e("POIFOIWEGBF", "Class not found", e);
}
return activityIntent;
}
I hope it helps.

Android - Issue on removing node from Firebase database

The following function is called from an addChildEventListener to remove a specific node from my Firebase database when it's needed.
The issue here is that the function launches the "Item removed." toast, indicating the task was successfully executed, but the node keeps existing on the database.
Can someone tell me what is wrong?
private void showData(DataSnapshot ds) {
String keyValue = null;
if(ds.hasChildren()) {
keyValue = ds.getKey();
Toast.makeText(getActivity().getApplicationContext(), "Removing item...", Toast.LENGTH_SHORT).show();
ds.getRef().child(keyValue).removeValue().addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Toast.makeText(getActivity().getApplicationContext(), "Item removed.", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getActivity().getApplicationContext(), "Something bad happened while removing item.", Toast.LENGTH_SHORT).show();
}
}
});
}
}
EDIT
If it helps, my query is the following:
orderItemsByTime = db.getInstance().getReference().child("items").orderByChild("time");
A likely explanation is that ds.getRef().child(keyValue) is not pointing to the location you intend. When remove() is performed on a non-existent location, it's not an error. task.isSuccessful() returns true.
Add some debug logging (or toasting) to show the path for ds.getRef().child(keyValue):
Toast.makeText(getActivity().getApplicationContext(), "Removing item at " +
ds.getRef().child(keyValue), Toast.LENGTH_SHORT).show();
or
Log.d(TAG, "Removing item at " + ds.getRef().child(keyValue));

c# web browser Invoke Script in event handler not working [duplicate]

Why I'm getting this error?
System.InvalidCastException was unhandled by user code
Message=Specified cast is not valid.
Source=System.Windows.Forms
StackTrace:
at System.Windows.Forms.UnsafeNativeMethods.IHTMLDocument2.GetLocation()
at System.Windows.Forms.WebBrowser.get_Document()
at System.Windows.Forms.WebBrowser.get_DocumentStream()
at System.Windows.Forms.WebBrowser.get_DocumentText()
at SiteBot.MainWindow.backgroundWorker1_DoWork(Object sender, DoWorkEventArgs e) in D:\Documents\Visual Studio 2010\Projects\SiteBot\MainWindow.cs:line 35
at System.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs e)
at System.ComponentModel.BackgroundWorker.WorkerThreadStart(Object argument)
InnerException:
The following solves your cross thread issue.
public delegate string GetStringHandler();
public string GetDocumentText()
{
if (InvokeRequired)
return Invoke(new GetStringHandler(GetDocumentText)) as string;
else
return webBrowser.DocumentText;
}
if (regAddId.IsMatch(GetDocumentText()))
{
}
I get a threading exception with this test:
public class Test
{
private readonly WebBrowser wb;
public Test()
{
wb = new WebBrowser();
var bw = new BackgroundWorker();
bw.DoWork += DoWork;
bw.RunWorkerAsync();
while (bw.IsBusy)
{
Thread.Sleep(10);
Application.DoEvents();
}
}
private void DoWork(object sender, DoWorkEventArgs e)
{
wb.Navigate(#"www.clix-cents.com/pages/clickads");
Thread.Sleep(1000);
var regex = new Regex("onclick=\\'openad\\(\"([\\d\\w]+\"\\);");
regex.IsMatch(wb.DocumentText);
}
}
public class Program
{
[STAThread]
public static void Main(string[] args)
{
new Test();
}
}
The exception looks like this:
Since WebBrowser is really just a wrapper around IE's ActiveX control, you'll need to be careful about threading issues. I think what you really want to use here is a WebClient and not a WebBrowser, but I'm just guessing about your application.
[EDIT]
Like #Fun states you can just Invoke over to the GUI thread (assuming thats where the control was created. I'd still recommend using a WebClient.

Disabling Splash screen on pressing a button

I have designed a splash screen. The Java code is as below. In that screen, I have a button named "Do not show this screen again future". On pressing this button, the splash screen must never been shown in future, no matter how many times the app is started. How can I achieve this? Thanks in advance.
public class Qz1 extends Activity {
MyThread thread;
private class MyThread extends Thread
{
public boolean bRun = true;
#Override
public void run()
{
try
{
sleep(3200);
if (bRun)
{
startActivity(new Intent(getApplicationContext(), Qone.class));
Qz1.this.overridePendingTransition(R.anim.newright,
R.anim.newleft);
}
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_qz1);
thread = new MyThread();
thread.start();
}
public void round1(View v){
Intent i = new Intent(Qz1.this, Qone.class);
startActivity(i);
this.overridePendingTransition(R.anim.newright,
R.anim.newleft);
}
}
Use SharedPreferences for this.
You can save a persisted boolean value by calling
getPreferences(MODE_PRIVATE).edit().putBoolean("no_splash", true).commit();
Then you can check that value by calling
boolean noSplash = getPreferences(MODE_PRIVATE).getBoolean("no_splash", false);
If noSplash is true then launch your main Activity immediately rather than starting the Thread.
User shared Preferences to achieve this, create a class
public class Preference {
private SharedPreferences sharedPreferences;
private SharedPreferences.Editor editor;
public Preference(Context context) {
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
}
public void writePreference(String key, Object value) {
if(value instanceof Boolean) {
editor = sharedPreferences.edit();
editor.putBoolean(key, (Boolean) value);
editor.commit();
}
}
public Object readPreference(String key , Object defValue) {
if(defValue instanceof Boolean)
return sharedPreferences.getBoolean(key, (Boolean) defValue);
else
return null;
}
public Boolean getDisableSplash() {
return (Boolean) readPreference("disable", false);
}
public void disableSplash(Boolean value)) {
writePreference("disable", valve);
}
}
and in your main create an object of Preference to read and write preference
Preference preference = new Preference(YourActivity.this);
Boolean result = preference.getDisableSplash();
if(!result) {
// dissable you splash activity here and move to next one
}
and when you want to disable it simply
Preference preference = new Preference(YourActivity.this);
preference.disableSplash(true);
You can solve this by creating delegate activity, make an empty activity an set it as launcher activity,
On the delegate activity oncreate check your preference if you should show the splash finish the delegate activity and show it else show your home screen.

Cordova #Intent-BroadcastReceiver

First of all, I'm working with some specific API ( Grand Stream GXV3275 phone ) which requires that Intent - BroadcastReceiver combo breaker.
When my device is on landscape orientation it works good so the problem came with Intent - BroadcastReceiver.
So I need that IntentFilter to know my HOOKEVENT ans then receive it with that BroadcastReceiver.
I just want to know why it doesn't even show the alert or don't work at all.
Is that possible to deal with IntentFilter on CordovaPlugin? With BroadcastReceiver?
I made some test on my CordovaActivity and HOOKEVENT ; updating a text-view.
So I assume that's a problem with CordovaPlugin.
I also tried to do:
CordovaActivity activity = (CordovaActivity) this.cordova.getActivity();
activity.getJs();
Which normally allow me to get string that works on my activity but gave me NPE..
public class Toast extends CordovaPlugin {
private String javascript = "";
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
initHookEvent();
switch (action) {
case "reversed":
reversedTest();
return true;
}
return false;
}
private Activity getActivity() { return this.cordova.getActivity();}
private void reversedTest(){
Configuration configuration = getActivity().getResources().getConfiguration();
if(configuration.orientation == Configuration.ORIENTATION_LANDSCAPE){
webView.sendJavascript("javascript:document.getElementById(\"combi\").innerHTML=\"Landscape\";");
}
webView.sendJavascript(javascript);
}
public void initHookEvent() {
IntentFilter filter = new IntentFilter("com.base.module.phone.HOOKEVENT");
getActivity().registerReceiver(broadcastReceiver, filter);
}
public BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
webView.sendJavascript("javascript:alert(\"test\");");
if (intent.getBooleanExtra("hookoff", false)){
javascript = "javascript:document.getElementById(\"combi\").innerHTML=\"decroche\";";
}
else{
javascript = "javascript:document.getElementById(\"combi\").innerHTML=\"raccroche\";";
}
}
};
I found myself my problem.
I create a specific plugin only for that after.
You just needed to :
webView.sendJavascript("javascript:document.getElementById(\"combi\").innerHTML=\"decroche\";");
And
getActivity().getApplicationContext().registerReceiver(broadcastReceiver_hook, filter_hook);
Here's my final plugin :
public class Hook extends CordovaPlugin {
#Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
initHookEvent();
return false;
}
/**
* Use to get the current Cordova Activity
* #return your Cordova activity
*/
private Activity getActivity() { return this.cordova.getActivity();}
/**
* Initializing GXV 3275 Hook Event
* You ABSOLUTELY need to precise getActivity().getApplicationContext()
* before registerReceiver() otherwise it won't get the good context.
*/
public void initHookEvent() {
IntentFilter filter_hook = new IntentFilter("com.base.module.phone.HOOKEVENT");
getActivity().getApplicationContext().registerReceiver(broadcastReceiver_hook, filter_hook);
}
/**
* BroadcastReceiver is also needed with GXV 3275 Hook Event
* Just sendJavascript for each cases
* /!\ webView /!\
* Is natively created by extending CordovaPlugin
*/
public BroadcastReceiver broadcastReceiver_hook = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if ( intent.getBooleanExtra("hookoff", false)){
webView.sendJavascript("javascript:document.getElementById(\"combi\").innerHTML=\"decroche\";");
webView.sendJavascript("javascript:document.getElementById(\"combi\").style.opacity = 1;");
}
else{
webView.sendJavascript("javascript:document.getElementById(\"combi\").innerHTML=\"raccroche\";");
webView.sendJavascript("javascript:document.getElementById(\"combi\").style.opacity = 1;");
}
}
};
}

Categories

Resources