My problem is that I don't know how to make a download of the upgrade version possible and I don't know where I must put the code of the upgrade version.
This is my code from https://github.com/anjlab/android-inapp-billing-v3:
BillingProcessor bp;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.upgrade);
setTitle("Upgrade");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
bp = new BillingProcessor(this, "/*Here's my license key from GooglePlay*/", this);
Button buy = (Button) findViewById((R.id.buy));
buy.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick (View view) {
bp.purchase(upgrade.this, "upgrade");
}
});
}
// IBillingHandler implementation
#Override
public void onBillingInitialized() {
/*
* Called when BillingProcessor was initialized and it's ready to purchase
*/
}
#Override
public void onProductPurchased(String productId, TransactionDetails details) {
/*
* Called when requested PRODUCT ID was successfully purchased
*/
}
#Override
public void onBillingError(int errorCode, Throwable error) {
/*
* Called when some error occurred. See Constants class for more details
*
* Note - this includes handling the case where the user canceled the buy dialog:
* errorCode = Constants.BILLING_RESPONSE_RESULT_USER_CANCELED
*/
}
#Override
public void onPurchaseHistoryRestored() {
/*
* Called when purchase history was restored and the list of all owned PRODUCT ID's
* was loaded from Google Play
*/
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (!bp.handleActivityResult(requestCode, resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
}
}
#Override
public void onDestroy() {
if (bp != null) {
bp.release();
}
super.onDestroy();
}
My question is now how to make a download of this upgrade possible? Where must be the code of the upgrade version?
Thanks for answering!
Related
I have two class (not activities), and one interface with single method with parameter.
In first class, I'm sending data in parameter.
private void sendProviderData(General provider) {
Singleton.getInstance().setProviderId(provider.getId());
Singleton.getInstance().setProviderIcon(provider.getIcon());
Singleton.getInstance().setProviderName(provider.getName());
//Listener
ResultListener resultListener;
resultListener = this;
resultListener.onActivityResult(CommonUtils.PICK_PROVIDER_CODE, CommonUtils.RESULT_OKAY);
dialog.dismiss();
}
Second class(I just implemented listener, any other things I have to do?), I want to get acknowledge that listener is called, so that I can get data:
#Override
public void onActivityResult(int requestCode, int resultCode) {
showLog("???");
if (resultCode == RESULT_OKAY) {
switch (requestCode) {
case PICK_PROVIDER_CODE:
showLog("worked!");
/* providerId = data.getLongExtra(PROVIDER_ID, 0);
inputBillProvider.setText(data.getStringExtra(PROVIDER_NAME));
selected = data.getStringExtra(PROVIDER_NAME);
setProviderValidation(selected);*/
break;
}
}
First class
private ResultListener resultListener;
----
---
public void setResultListener(ResultListener listener) {
this.resultListener = listener;
}
public void sendProviderData(General provider) {
Singleton.getInstance().setProviderId(provider.getId());
Singleton.getInstance().setProviderIcon(provider.getIcon());
Singleton.getInstance().setProviderName(provider.getName());
resultListener.onActivityResult(CommonUtils.PICK_PROVIDER_CODE, CommonUtils.RESULT_OKAY);
dialog.dismiss();
}
in Second class, let's say you have FirstClass instance name firstInstance, you need to set Second class as the listener. after creating the First class instance. So you can get the response
FirstClass firstInstance = new FirstClass();
firstInstance.setResultListener(this)
firstInstance.sendProviderData(provider);
.......
....
..
#Override
public void onActivityResult(int requestCode, int resultCode) {
showLog("???");
if (resultCode == RESULT_OKAY) {
switch (requestCode) {
case PICK_PROVIDER_CODE:
showLog("worked!");
/* providerId = data.getLongExtra(PROVIDER_ID, 0);
inputBillProvider.setText(data.getStringExtra(PROVIDER_NAME));
selected = data.getStringExtra(PROVIDER_NAME);
setProviderValidation(selected);*/
break;
}
}
I wrote some codes to check user if she/he bought the premium version, but after purchasing , again it check the user and this process use about 15 second(every time that the user open the app) and also after purchase when the user is offline and it can not check if the user purchased the app or not(but actually the user bought it before) it consider it as a demo version and the user can not use full content. what should i do? i want when the user buy the full version then can use if anytime offline.
public class MainActivity extends AppCompatActivity implements IabHelper.OnIabSetupFinishedListener
, IabHelper.QueryInventoryFinishedListener{
private ProgressDialog progressDialog;
private CoordinatorLayout coordinatorLayout;
private IabHelper iabHelper;
private static final String PRODUCT_PREMIUM_ACCOUNT="testapk";
public boolean isPremiumAccount=false;
private Button upgradeToPremiumButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressDialog =new ProgressDialog(this);
progressDialog.setTitle("checking purches status");
progressDialog.setMessage("please wiat...");
progressDialog.setCancelable(false);
progressDialog.show();
coordinatorLayout=(CoordinatorLayout)findViewById(R.id.coor_main);
upgradeToPremiumButton=(Button)findViewById(R.id.button_main_upgrade);
upgradeToPremiumButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
purchasePremiumAccount();
} });
checkAccount();}
public void btnTblcontentClick(View v){
if(isPremiumAccount){
Intent i = new Intent(this,tblOfcontent.class);
startActivity(i);
}else{
Toast.makeText(getApplicationContext(), "buy full version ",
Toast.LENGTH_LONG).show();}}
public void btnSearchClick(View v){
if(isPremiumAccount){
Intent i = new Intent(this,search.class);
startActivity(i);
}else{
Toast.makeText(getApplicationContext(), "buy full version ",}}
Toast.LENGTH_LONG).show();
private void checkAccount(){
iabHelper=new IabHelper(this,"my RSA key");
iabHelper.startSetup(this);}
#Override
public void onIabSetupFinished(IabResult result) {
if (result.isSuccess()){
List<String> products = new ArrayList<>();
products.add(PRODUCT_PREMIUM_ACCOUNT);
iabHelper.queryInventoryAsync(true,products,this);
}else {
showError("sorry...process not complete");}}
#Override
public void onQueryInventoryFinished(IabResult result, Inventory inv) {
if (result.isSuccess()){
Purchase purchase= inv.getPurchase(PRODUCT_PREMIUM_ACCOUNT);
if (purchase!=null){
changeStateToPremium();
}
}else {
showError(" you just can use demo version");}
progressDialog.hide();}
private void showError(String message){
Snackbar.make(coordinatorLayout,message,Snackbar.LENGTH_LONG).show();}
private void changeStateToPremium(){
isPremiumAccount=true;
upgradeToPremiumButton.setVisibility(View.GONE);}
#Override
protected void onDestroy() {
super.onDestroy();
if(iabHelper!=null){
iabHelper.dispose();
iabHelper=null;}}
private void purchasePremiumAccount(){
iabHelper.launchPurchaseFlow(this, PRODUCT_PREMIUM_ACCOUNT, 1001, new IabHelper.OnIabPurchaseFinishedListener() {
#Override
public void onIabPurchaseFinished(IabResult result, Purchase info) {
if (result.isSuccess()){
if(info!=null){
changeStateToPremium();
}
}else {
showError("purches not complete");}}});}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode==1001){
iabHelper.handleActivityResult(requestCode,resultCode,data);
}else {
super.onActivityResult(requestCode,resultCode,data);}}}
When the transaction is successful then you can save Boolean flag to SharedPreference. If you find that Boolean flag true, then bypass checking methods.
Things to check.
If user clear cache then api would be called again.
First change SharedPreference flag when item is purchased then second when you know user has already purchased item.
If your item is subscription type then also save expire time with item id.
I have simple activity with one button. When button is clicked, I'm firing intent to pick image from gallery. Something strange is going on when I fire intent and then rotate the screen. Here are the steps:
Click button. "Open with" system dialog appears.
Rotate screen. Activity gets recreated, dialog is still shown. Note - I don't call startActivityForResult(Intent, int) again on my activity recreate.
Tap back button. "Open with" dialog disappear, but there is another one beneath it.
So it seems even though I don't call startActivityForResult(Intent, int), new instance of dialog gets created every orientation change, and old instance don't getting destroyed.
Does anyone facing this issue? How to get rid of these duplicate dialogs?
Update 1:
So, here is some sample code:
public class MainActivity extends AppCompatActivity
{
private boolean mIsStarted = false;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState != null)
{
mIsStarted = savedInstanceState.getBoolean("key");
}
if (!mIsStarted)
{
mIsStarted = true;
Intent intent = new Intent(Intent.ACTION_PICK).setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, MimeType.IMAGE);
startActivityForResult(intent, 1);
}
}
#Override
protected void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
outState.putBoolean("key", mIsStarted);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
mIsStarted = false;
}
}
I also tried to set android:configChanges="orientation|keyboardHidden|keyboard|screenSize|mcc|mnc" and still every time I rotate the screen, new copy of dialog (actually this is not a dialog, this is ResolverActivity) being showed on top of previous one. Is this some Android bug or it's just me doing something wrong?
Update 2: so I tried another approach - call finishActivity(int) inside my Activity.onStop(). Result is pretty strange - now I've got only 2 copies of ChooserActivity. After second copy is created, it starts rotating fine.
Here is the code:
public class MainActivity extends AppCompatActivity
{
private static final String LOG_TAG = MainActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState)
{
Log.d(LOG_TAG, "onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.make_photo).setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
Intent intent = new Intent(Intent.ACTION_PICK).setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, MimeType.IMAGE);
startActivityForResult(intent, 1);
}
});
}
#Override
protected void onStop()
{
Log.d(LOG_TAG, "onStop");
super.onStop();
finishActivity(1);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
Log.d(LOG_TAG, String.format("onActivityResult[requestCode:%d, resultCode:%d, data:%s]",
requestCode, resultCode, data != null ? data.toString() : "NULL"));
}
}
Still wonder why second copy is being created.
Add this to the activity declatation in your androidmanifest.xml
android:configChanges="orientation|screenSize"
This will prevent the activity from getting recreated and resolve the issue of duplicate dialog.
Find out this was silly mistake in my base Activity class. I end up with deriving all my Activities which works with intents from this base IntentProcessingActivity class.
/**
* Base activity for all activities which process intents. This activity saves processing state
* during recreation, so derived activities can get rid of this. This is useful for not showing
* "Open with" dialogs multiple times.
* <p />
* Derived activities can check if some intent is currently processing with {#link
* #isProcessingIntent()} function.
* <p />
* Created by Maksimov Stanislav (s.maks04#gmail.com) on 25.01.16
*/
public class IntentProcessingActivity extends AppCompatActivity
{
private static final String KEY_IS_PROCESSING_INTENT = "IsProcessingIntent";
private boolean mIsProcessingIntent;
#CallSuper
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if (savedInstanceState != null)
{
mIsProcessingIntent = savedInstanceState.getBoolean(KEY_IS_PROCESSING_INTENT, false);
}
}
#CallSuper
#Override
protected void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
outState.putBoolean(KEY_IS_PROCESSING_INTENT, mIsProcessingIntent);
}
#CallSuper
#Override
public void startActivityForResult(Intent intent, int requestCode, Bundle options)
{
mIsProcessingIntent = true;
super.startActivityForResult(intent, requestCode, options);
}
#CallSuper
#Override
public void startActivityForResult(Intent intent, int requestCode)
{
mIsProcessingIntent = true;
super.startActivityForResult(intent, requestCode);
}
#CallSuper
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
mIsProcessingIntent = false;
super.onActivityResult(requestCode, resultCode, data);
}
protected final boolean isProcessingIntent()
{
return mIsProcessingIntent;
}
}
On child Activities I just check
if (!isProcessingIntent())
{
startActivityForResult(...);
}
EDIT-----: So I did manage to make it show me users and be able to select some, and to send me back the selected users to my app but there is a slight problem. "Uri.parse("picker://friend");" doesn't give me the list of my friends, but only a list of the friends that I have and have my app installed.
I followed this example: https://developers.facebook.com/docs/android/scrumptious/show-friends but I am trying to modify it, so basically I took out the selectionActivity and Fragment. So I have from my activity a button that calls the PickerActivity which contains FriendPickerFragment. I can select my friends from there, but back in my activities onActivityResult i get back "data" as null.
I have an Application class in my app, where i save the FB session, and also have the login function in there.
In my MainActivity onCreate I have this:
MyApp.getInstance().facebookLogin(PSAddFriendsActivity.this, new CrudStateCallback() {
#Override
public void onResponse(final String string) {
Log.i("", "session : session is opened? : " + MyApp.getInstance().fbSession.getAccessToken());
}
});
After having logged in, I instantiate a list with the current friends I have in my app, and the first position of this list is a FB button:
#Override
protected void onListItemClick(ListView l, View v, int position, long id){
super.onListItemClick(l, v, position, id);
if(position == 0){
startPickerActivity(PSPickerActivity.FRIEND_PICKER, 0);
}else if(position ==1){
//TODO: OPEN CONTACTS PAGE TO ADD FRIENDS
}
}
This is my onACtivityResult and the "startPickerActivity" from this class:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Session.getActiveSession().onActivityResult(this, requestCode, resultCode, data);
Log.i("","--------------data is : " + data);
Log.i("","--------------resultCode is : " + resultCode);
Log.i("","--------------requestCode is : " + requestCode);
}
public void startPickerActivity(Uri data, int requestCode) {
Intent intent = new Intent();
intent.setData(data);
intent.setClass(PSAddFriendsActivity.this, PickerActivity.class);
startActivityForResult(intent, requestCode);
}
This is the PickerActivity, how I took it from FB:
public class PickerActivity extends FragmentActivity{
private FriendPickerFragment friendPickerFragment;
public static final Uri FRIEND_PICKER = Uri.parse("picker://friend");
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pickers);
Bundle args = getIntent().getExtras();
FragmentManager manager = getSupportFragmentManager();
Fragment fragmentToShow = null;
Uri intentUri = getIntent().getData();
if (FRIEND_PICKER.equals(intentUri)) {
if (savedInstanceState == null) {
friendPickerFragment = new FriendPickerFragment(args);
} else {
friendPickerFragment =
(FriendPickerFragment) manager.findFragmentById(R.id.picker_fragment);
}
// Set the listener to handle errors
friendPickerFragment.setOnErrorListener(new PickerFragment.OnErrorListener() {
#Override
public void onError(PickerFragment<?> fragment,
FacebookException error) {
PSPickerActivity.this.onError(error);
}
});
// Set the listener to handle button clicks
friendPickerFragment.setOnDoneButtonClickedListener(
new PickerFragment.OnDoneButtonClickedListener() {
#Override
public void onDoneButtonClicked(PickerFragment<?> fragment) {
finishActivity();
}
});
fragmentToShow = friendPickerFragment;
} else {
// Nothing to do, finish
setResult(RESULT_CANCELED);
finish();
return;
}
manager.beginTransaction()
.replace(R.id.picker_fragment, fragmentToShow)
.commit();
}
private void onError(Exception error) {
onError(error.getLocalizedMessage(), false);
}
private void onError(String error, final boolean finishActivity) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.error_dialog_title).
setMessage(error).
setPositiveButton(R.string.error_dialog_button_text,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
if (finishActivity) {
finishActivity();
}
}
});
builder.show();
}
private void finishActivity() {
setResult(RESULT_OK, null);
finish();
}
#Override
protected void onStart() {
super.onStart();
if (FRIEND_PICKER.equals(getIntent().getData())) {
try {
friendPickerFragment.loadData(false);
} catch (Exception ex) {
onError(ex);
}
}
}
#Override
protected void onResume() {
Log.i("", "location test onResume");
super.onResume();
MyApp.getInstance().pref.setIsBackground(this, false);
MyApp.getInstance().startLocationClient();
}
#Override
protected void onPause() {
Log.i("", "location test onPause");
super.onPause();
MyApp.getInstance().pref.setIsBackground(this, true);
}
}
Now I looked over this fragment, do not know if I have to add something or save something from the fragment on "onDoneButtonClicked"? or what exactly, because my main activity does return null as data..
forgot to call this in the finishActivty:
if (FRIEND_PICKER.equals(getIntent().getData())) {
if (friendPickerFragment != null) {
MyApp.getInstance().setSelectedUsers(friendPickerFragment.getSelection());
}
}
Now I can get from my Application the list of selected users.
About my edit, after this i found out that with Graph2.0 you cannot get a list of your whole friendlist. You can only get back the info of friends that also liked the app. It is possible to invite friends to like an app but only if you set it as a Game from the FB developers page
i m using following code to access youtube but on run time it is giving "class not found exception" i already added all Jar's reqiured
String developer_key="my Key";
#Override
protected void onCreate(Bundle savedInstanceState)
{ super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
YouTubeService service = new YouTubeService( developer_key);
}
It's no longer that simple.
You must first create your UX element (YouTubePlayerView, YouTubePlayerFragment, YouTubeStandalonePlayer, etc), then you send the initialize message to it.
From the YouTube Android API Demo App PlayerViewDemoActivity.java:
/**
* A simple YouTube Android API demo application which shows how to create a simple application that
* displays a YouTube Video in a {#link YouTubePlayerView}.
* <p>
* Note, to use a {#link YouTubePlayerView}, your activity must extend {#link YouTubeBaseActivity}.
*/
public class PlayerViewDemoActivity extends YouTubeFailureRecoveryActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.playerview_demo);
YouTubePlayerView youTubeView = (YouTubePlayerView) findViewById(R.id.youtube_view);
youTubeView.initialize(DeveloperKey.DEVELOPER_KEY, this);
}
#Override
public void onInitializationSuccess(YouTubePlayer.Provider provider, YouTubePlayer player,
boolean wasRestored) {
if (!wasRestored) {
player.loadVideo("wKJ9KzGQq0w");
}
}
#Override
protected YouTubePlayer.Provider getYouTubePlayerProvider() {
return (YouTubePlayerView) findViewById(R.id.youtube_view);
}
}
From YouTubeFailureRecoveryActivity.java:
/**
* An abstract activity which deals with recovering from errors which may occur during API
* initialization, but can be corrected through user action.
*/
public abstract class YouTubeFailureRecoveryActivity extends YouTubeBaseActivity implements
YouTubePlayer.OnInitializedListener {
private static final int RECOVERY_DIALOG_REQUEST = 1;
#Override
public void onInitializationFailure(YouTubePlayer.Provider provider,
YouTubeInitializationResult errorReason) {
if (errorReason.isUserRecoverableError()) {
errorReason.getErrorDialog(this, RECOVERY_DIALOG_REQUEST).show();
} else {
String errorMessage = String.format(getString(R.string.error_player), errorReason.toString());
Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show();
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == RECOVERY_DIALOG_REQUEST) {
// Retry initialization if user performed a recovery action
getYouTubePlayerProvider().initialize(DeveloperKey.DEVELOPER_KEY, this);
}
}
protected abstract YouTubePlayer.Provider getYouTubePlayerProvider();
}