package de.blinkt.openvpn.fragments; import android.app.Fragment; import android.app.PendingIntent; import android.content.*; import android.content.pm.PackageInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.text.Html; import android.text.SpannableString; import android.text.Spanned; import android.text.TextUtils; import android.text.method.LinkMovementMethod; import android.text.style.ClickableSpan; import android.util.Log; import android.util.Pair; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.webkit.WebView; import android.widget.TextView; import com.android.vending.billing.IInAppBillingService; import de.blinkt.openvpn.R; import de.blinkt.openvpn.core.VpnStatus; import org.json.JSONException; import org.json.JSONObject; import java.util.*; public class AboutFragment extends Fragment implements View.OnClickListener { public static final String INAPPITEM_TYPE_INAPP = "inapp"; public static final String RESPONSE_CODE = "RESPONSE_CODE"; private static final int DONATION_CODE = 12; private static final int BILLING_RESPONSE_RESULT_OK = 0; private static final String RESPONSE_BUY_INTENT = "BUY_INTENT"; private static final String[] donationSkus = { "donation1eur", "donation2eur", "donation5eur", "donation10eur", "donation1337eur","donation23eur","donation25eur",}; IInAppBillingService mService; Hashtable viewToProduct = new Hashtable(); ServiceConnection mServiceConn = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { mService = null; } @Override public void onServiceConnected(ComponentName name, IBinder service) { mService = IInAppBillingService.Stub.asInterface(service); initGooglePlayDonation(); } }; private void initGooglePlayDonation() { new Thread("queryGMSInApp") { @Override public void run() { initGMSDonateOptions(); } }.start(); } private TextView gmsTextView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getActivity().bindService(new Intent("com.android.vending.billing.InAppBillingService.BIND"), mServiceConn, Context.BIND_AUTO_CREATE); } @Override public void onDestroy() { super.onDestroy(); if (mServiceConn != null) { getActivity().unbindService(mServiceConn); } } private void initGMSDonateOptions() { try { int billingSupported = mService.isBillingSupported(3, getActivity().getPackageName(), INAPPITEM_TYPE_INAPP); if (billingSupported != BILLING_RESPONSE_RESULT_OK) { Log.i("OpenVPN", "Play store billing not supported"); return; } ArrayList skuList = new ArrayList(); Collections.addAll(skuList, donationSkus); Bundle querySkus = new Bundle(); querySkus.putStringArrayList("ITEM_ID_LIST", skuList); Bundle ownedItems = mService.getPurchases(3, getActivity().getPackageName(), INAPPITEM_TYPE_INAPP, null); if (ownedItems.getInt(RESPONSE_CODE) != BILLING_RESPONSE_RESULT_OK) return; final ArrayList ownedSkus = ownedItems.getStringArrayList("INAPP_PURCHASE_ITEM_LIST"); Bundle skuDetails = mService.getSkuDetails(3, getActivity().getPackageName(), INAPPITEM_TYPE_INAPP, querySkus); if (skuDetails.getInt(RESPONSE_CODE) != BILLING_RESPONSE_RESULT_OK) return; final ArrayList responseList = skuDetails.getStringArrayList("DETAILS_LIST"); if (getActivity() != null) { getActivity().runOnUiThread(new Runnable() { @Override public void run() { createPlayBuyOptions(ownedSkus, responseList); } }); } } catch (RemoteException e) { VpnStatus.logException(e); } } private static class SkuResponse { String title; String price; SkuResponse(String p, String t) { title=t; price=p; } } private void createPlayBuyOptions(ArrayList ownedSkus, ArrayList responseList) { try { Vector> gdonation = new Vector>(); gdonation.add(new Pair(getString(R.string.donatePlayStore),null)); HashMap responseMap = new HashMap(); for (String thisResponse : responseList) { JSONObject object = new JSONObject(thisResponse); responseMap.put( object.getString("productId"), new SkuResponse( object.getString("price"), object.getString("title"))); } for (String sku: donationSkus) if (responseMap.containsKey(sku)) gdonation.add(getSkuTitle(sku, responseMap.get(sku).title, responseMap.get(sku).price, ownedSkus)); String gmsTextString=""; for(int i=0;i1) gmsTextString+= ", "; gmsTextString+=gdonation.elementAt(i).first; } SpannableString gmsText = new SpannableString(gmsTextString); int lStart = 0; int lEnd=0; for(Pair item:gdonation){ lEnd = lStart + item.first.length(); if (item.second!=null) { final String mSku = item.second; ClickableSpan cspan = new ClickableSpan() { @Override public void onClick(View widget) { triggerBuy(mSku); } }; gmsText.setSpan(cspan,lStart,lEnd,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } lStart = lEnd+2; // Account for ", " between items } if(gmsTextView !=null) { gmsTextView.setText(gmsText); gmsTextView.setMovementMethod(LinkMovementMethod.getInstance()); gmsTextView.setVisibility(View.VISIBLE); } } catch (JSONException e) { VpnStatus.logException("Parsing Play Store IAP",e); } } private Pair getSkuTitle(final String sku, String title, String price, ArrayList ownedSkus) { String text; if (ownedSkus.contains(sku)) return new Pair(getString(R.string.thanks_for_donation, price),null); if (price.contains("€")|| price.contains("\u20ac")) { text= title; } else { text = String.format(Locale.getDefault(), "%s (%s)", title, price); } //return text; return new Pair(price, sku); } private void triggerBuy(String sku) { try { Bundle buyBundle = mService.getBuyIntent(3, getActivity().getPackageName(), sku, INAPPITEM_TYPE_INAPP, "Thanks for the donation! :)"); if (buyBundle.getInt(RESPONSE_CODE) == BILLING_RESPONSE_RESULT_OK) { PendingIntent buyIntent = buyBundle.getParcelable(RESPONSE_BUY_INTENT); getActivity().startIntentSenderForResult(buyIntent.getIntentSender(), DONATION_CODE, new Intent(), 0, 0, 0); } } catch (RemoteException e) { VpnStatus.logException(e); } catch (IntentSender.SendIntentException e) { VpnStatus.logException(e); } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.about, container, false); TextView ver = (TextView) v.findViewById(R.id.version); String version; String name = "Openvpn"; try { PackageInfo packageinfo = getActivity().getPackageManager().getPackageInfo(getActivity().getPackageName(), 0); version = packageinfo.versionName; name = getString(R.string.app); } catch (NameNotFoundException e) { version = "error fetching version"; } ver.setText(getString(R.string.version_info, name, version)); TextView paypal = (TextView) v.findViewById(R.id.donatestring); String donatetext = getActivity().getString(R.string.donatewithpaypal); Spanned htmltext = Html.fromHtml(donatetext); paypal.setText(htmltext); paypal.setMovementMethod(LinkMovementMethod.getInstance()); gmsTextView = (TextView) v.findViewById(R.id.donategms); /* recreating view without onCreate/onDestroy cycle */ if (mService!=null) initGooglePlayDonation(); TextView translation = (TextView) v.findViewById(R.id.translation); // Don't print a text for myself if (getString(R.string.translationby).contains("Arne Schwabe")) translation.setText(""); else translation.setText(R.string.translationby); WebView wv = (WebView)v.findViewById(R.id.webView); wv.loadUrl("file:///android_asset/full_licenses.html"); return v; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); if (mService!=null) initGooglePlayDonation(); } @Override public void onClick(View v) { } }