আপনার অ্যাপে ক্লায়েন্ট-সাইড লাইসেন্স যাচাইকরণ যোগ করা

সতর্কতা: আপনার অ্যাপ ক্লায়েন্ট সাইডে লাইসেন্স যাচাইকরণ প্রসেস সম্পূর্ণ করলে, সম্ভাব্য আক্রমণকারীদের পক্ষে এই যাচাইকরণ প্রসেসের সাথে যুক্ত লজিক পরিবর্তন করা বা সরিয়ে দেওয়া সহজ হয়।

এই কারণে, আমরা আপনাকে দৃঢ়ভাবে উৎসাহিত করি পরিবর্তে সার্ভার-সাইড লাইসেন্স যাচাইকরণ করতে।

আপনি প্রকাশক অ্যাকাউন্ট ও ডেভেলপমেন্ট এনভায়রনমেন্ট সেট-আপ করার পরে (লাইসেন্সিংয়ের জন্য সেট-আপ করা দেখুন), লাইসেন্স যাচাইকরণ লাইব্রেরির (LVL) মাধ্যমে আপনার অ্যাপে লাইসেন্স যাচাইকরণ যোগ করার জন্য প্রস্তুত।

LVL-এর মাধ্যমে লাইসেন্স যাচাইকরণ যোগ করার জন্য এইসব টাস্ক করতে হয়:

  1. আপনার অ্যাপ্লিকেশনের ম্যানিফেস্টে লাইসেন্সিং অনুমতি যোগ করা।
  2. নীতি প্রয়োগ করা — LVL-এ দেওয়া সম্পূর্ণ প্রয়োগের মধ্যে থেকে আপনি একটি বেছে নিতে পারেন অথবা আপনার নিজের তৈরি করতে পারেন।
  3. Obfuscator প্রয়োগ করা, যদি আপনার Policy কোনও লাইসেন্স রেসপন্স ডেটা ক্যাশে করে।
  4. আপনার অ্যাপ্লিকেশনের মূল অ্যাক্টিভিটিতে লাইসেন্স চেক করার জন্য কোড যোগ করা।
  5. DeviceLimiter প্রয়োগ করা (ঐচ্ছিক এবং বেশিরভাগ অ্যাপ্লিকেশনের জন্য সাজেস্ট করা হয় না)।

নিচের বিভাগগুলিতে এইসব টাস্কের ব্যাপারে বর্ণনা করা হয়েছে। ইন্টিগ্রেশন সম্পূর্ণ হয়ে গেলে, আপনি নিজের অ্যাপ্লিকেশন কম্পাইল করতে পারবেন এবং টেস্ট এনভায়রনমেন্ট সেট-আপ করা লিঙ্কে যেভাবে বর্ণনা করা হয়েছে সেই অনুযায়ী টেস্ট করা শুরু করতে পারবেন।

LVL-এ অন্তর্ভুক্ত সোর্স ফাইলের সম্পূর্ণ সেটের ওভারভিউয়ের জন্য, LVL ক্লাস ও ইন্টারফেসের সংক্ষিপ্ত বিবরণ দেখুন।

লাইসেন্স দেওয়ার অনুমতি যোগ করা

সার্ভারে লাইসেন্স চেক পাঠানোর জন্য Google Play অ্যাপ্লিকেশন ব্যবহার করতে, আপনার অ্যাপ্লিকেশনকে অবশ্যই সঠিক অনুমতির জন্য অনুরোধ করতে হবে, com.android.vending.CHECK_LICENSE। আপনার অ্যাপ্লিকেশন যদি লাইসেন্সিং অনুমতি ঘোষণা না করে কিন্তু লাইসেন্স চেক শুরু করার চেষ্টা করে, তাহলে LVL একটি নিরাপত্তা ব্যতিক্রম দেখায়।

আপনার অ্যাপ্লিকেশনে লাইসেন্সিং অনুমতির অনুরোধ করতে, <manifest>-এর চাইল্ড হিসেবে <uses-permission> এলিমেন্ট ঘোষণা করুন, যেমন:

<uses-permission android:name="com.android.vending.CHECK_LICENSE" />

যেমন, LVL স্যাম্পেল অ্যাপ্লিকেশন কীভাবে অনুমতি ঘোষণা করে তা এখানে দেওয়া হল:

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android" ...">
    <!-- Devices >= 3 have version of Google Play that supports licensing. -->
    <uses-sdk android:minSdkVersion="3" />
    <!-- Required permission to check licensing. -->
    <uses-permission android:name="com.android.vending.CHECK_LICENSE" />
    ...
</manifest>

মনে রাখবেন: বর্তমানে, আপনি LVL লাইব্রেরি প্রোজেক্টের ম্যানিফেস্টে CHECK_LICENSE অনুমতি ঘোষণা করতে পারবেন না, কারণ SDK টুল এটিকে নির্ভরশীল অ্যাপ্লিকেশনের ম্যানিফেস্টে মার্জ করবে না। পরিবর্তে, আপনাকে প্রতিটি নির্ভরশীল অ্যাপ্লিকেশনের ম্যানিফেস্টে অনুমতি ঘোষণা করতে হবে।

নীতি প্রয়োগ করা

Google Play লাইসেন্সিং পরিষেবা নিজে থেকে নির্ধারণ করে না যে কোনও নির্দিষ্ট লাইসেন্স সহ কোনও নির্দিষ্ট ব্যবহারকারীকে আপনার অ্যাপ্লিকেশনে অ্যাক্সেস দেওয়া উচিত কিনা। বরং, সেই দায়িত্ব আপনার অ্যাপ্লিকেশনে দেওয়া Policy ইমপ্লিমেন্টেশনের উপর ছেড়ে দেওয়া হয়।

নীতি হল LVL দ্বারা ঘোষিত একটি ইন্টারফেস যা লাইসেন্স চেক করার ফলাফলের উপর ভিত্তি করে ব্যবহারকারীর অ্যাক্সেস অনুমোদন বা প্রত্যাখ্যান করার জন্য আপনার অ্যাপ্লিকেশনের লজিক ধরে রাখার জন্য ডিজাইন করা হয়েছে। LVL ব্যবহার করতে, আপনার অ্যাপ্লিকেশনকে অবশ্যই Policy-এর ইমপ্লিমেন্টেশন প্রদান করতে হবে।

Policy ইন্টারফেস দুটি পদ্ধতি ঘোষণা করে, allowAccess() এবং processServerResponse(), যা লাইসেন্স সার্ভার থেকে কোনও উত্তর প্রসেস করার সময় LicenseChecker ইনস্ট্যান্স দ্বারা কল করা হয়। এটি LicenseResponse নামে একটি enum ঘোষণা করে, যা processServerResponse()-এ কলে পাস করা লাইসেন্স রেসপন্স ভ্যালু নির্দিষ্ট করে।

  • processServerResponse() আপনাকে লাইসেন্সিং সার্ভার থেকে পাওয়া কাঁচা রেসপন্স ডেটা প্রিপ্রসেস করতে দেয়, অ্যাক্সেস দেওয়া হবে কিনা তা নির্ধারণ করার আগে।

    সাধারণত, লাইসেন্স রেসপন্স থেকে কিছু বা সব ফিল্ড এক্সট্র্যাক্ট করে এবং ডেটা স্থানীয়ভাবে একটি স্থায়ী স্টোরেজে স্টোর করে, যেমন SharedPreferences স্টোরেজের মাধ্যমে, যাতে ডেটা অ্যাপ্লিকেশন ইনভোকেশন এবং ডিভাইস পাওয়ার সাইকেল জুড়ে অ্যাক্সেসযোগ্য হয়। যেমন, একটি Policy শেষবার সফলভাবে লাইসেন্স চেক করার টাইমস্ট্যাম্প, আবার চেষ্টা করার সংখ্যা, লাইসেন্সের বৈধতার মেয়াদ এবং একই ধরনের তথ্য একটি পারসিস্টেন্ট স্টোরে বজায় রাখবে, প্রতিবার অ্যাপ্লিকেশন চালু করার সময় ভ্যালু রিসেট করার পরিবর্তে।

    স্থানীয়ভাবে উত্তর সংক্রান্ত ডেটা স্টোর করার সময়, Policy-কে নিশ্চিত করতে হবে যে ডেটা অবফাসকেট করা হয়েছে (নিচে অবফাসকেটর প্রয়োগ করা দেখুন)।

  • allowAccess() নির্ধারণ করে যে ব্যবহারকারীকে আপনার অ্যাপ্লিকেশন অ্যাক্সেস করার অনুমতি দেওয়া হবে কিনা। এটি উপলভ্য লাইসেন্স রেসপন্স ডেটা (লাইসেন্সিং সার্ভার বা ক্যাশে থেকে) বা অন্যান্য অ্যাপ্লিকেশন-নির্দিষ্ট তথ্যের উপর ভিত্তি করে করা হয়। যেমন, allowAccess()-এর প্রয়োগে অতিরিক্ত মাপকাঠি বিবেচনা করা যেতে পারে, যেমন ব্যাকএন্ড সার্ভার থেকে পাওয়া ব্যবহার বা অন্যান্য ডেটা। সব ক্ষেত্রেই, allowAccess()-এর প্রয়োগের ফলে শুধুমাত্র true রিটার্ন করা উচিত, যদি ব্যবহারকারীর কাছে অ্যাপ্লিকেশন ব্যবহার করার লাইসেন্স থাকে, যেমনটি লাইসেন্সিং সার্ভার দ্বারা নির্ধারিত হয়, অথবা যদি কোনও ক্ষণস্থায়ী নেটওয়ার্ক বা সিস্টেম সমস্যা থাকে যা লাইসেন্স চেক সম্পূর্ণ হতে বাধা দেয়। এই ধরনের ক্ষেত্রে, আপনার ইমপ্লিমেন্টেশন আবার চেষ্টা করার উত্তরের সংখ্যা বজায় রাখতে পারে এবং পরবর্তী লাইসেন্স চেক সম্পূর্ণ না হওয়া পর্যন্ত সাময়িকভাবে অ্যাক্সেস দিতে পারে।

আপনার অ্যাপ্লিকেশনে লাইসেন্সিং যোগ করার প্রসেস সহজ করতে এবং কীভাবে Policy ডিজাইন করা উচিত তার একটি উদাহরণ প্রদান করতে, LVL-এ দুটি সম্পূর্ণ Policy ইমপ্লিমেন্টেশন অন্তর্ভুক্ত থাকে যা আপনি কোনও পরিবর্তন ছাড়াই ব্যবহার করতে পারেন বা আপনার প্রয়োজন অনুযায়ী মানিয়ে নিতে পারেন:

  • ServerManagedPolicy, একটি নমনীয় Policy যা বিভিন্ন নেটওয়ার্ক পরিস্থিতি জুড়ে অ্যাক্সেস ম্যানেজ করতে সার্ভার-প্রদত্ত সেটিংস এবং ক্যাশে করা উত্তর ব্যবহার করে এবং
  • StrictPolicy, যা কোনও রেসপন্স ডেটা ক্যাশে করে না এবং সার্ভার লাইসেন্সড রেসপন্স ফেরত দিলে শুধুমাত্র অ্যাক্সেস করার অনুমতি দেয়।

বেশিরভাগ অ্যাপ্লিকেশনের ক্ষেত্রে, ServerManagedPolicy ব্যবহার করার জন্য বিশেষভাবে সাজেস্ট করা হয়। ServerManagedPolicy হল LVL ডিফল্ট এবং এটি LVL স্যাম্পেল অ্যাপ্লিকেশনের সাথে ইন্টিগ্রেট করা থাকে।

কাস্টম নীতির জন্য নির্দেশিকা

আপনার লাইসেন্সিং প্রয়োগে, আপনি LVL-এ (ServerManagedPolicy বা StrictPolicy) প্রদান করা সম্পূর্ণ নীতিগুলির মধ্যে একটি ব্যবহার করতে পারেন অথবা আপনি একটি কাস্টম নীতি তৈরি করতে পারেন। যেকোনও ধরনের কাস্টম নীতির জন্য, আপনার প্রয়োগে বোঝার এবং বিবেচনা করার জন্য বেশ কয়েকটি গুরুত্বপূর্ণ ডিজাইন পয়েন্ট রয়েছে।

লাইসেন্সিং সার্ভার, রিসোর্সের অতিরিক্ত ব্যবহার আটকাতে অনুরোধের উপর সাধারণ সীমা প্রয়োগ করে, যাতে পরিষেবা বন্ধ না হয়ে যায়। কোনও অ্যাপ্লিকেশন অনুরোধের সীমা অতিক্রম করলে, লাইসেন্সিং সার্ভার একটি 503 প্রতিক্রিয়া প্রদান করে, যা আপনার অ্যাপ্লিকেশনে একটি সাধারণ সার্ভার সমস্যা হিসেবে পাস করা হয়। এর অর্থ হল, সীমা রিসেট না করা পর্যন্ত ব্যবহারকারীর জন্য কোনও লাইসেন্স সংক্রান্ত উত্তর উপলভ্য হবে না, যা ব্যবহারকারীকে অনির্দিষ্টকালের জন্য প্রভাবিত করতে পারে।

আপনি কাস্টম নীতি ডিজাইন করলে, আমরা সাজেস্ট করি যে Policy:

  1. লোকাল পারসিস্টেন্ট স্টোরেজে সবচেয়ে সাম্প্রতিক সফল লাইসেন্স রেসপন্স ক্যাশে (এবং সঠিকভাবে অস্পষ্ট) করে।
  2. লাইসেন্সিং সার্ভারে অনুরোধ করার পরিবর্তে, ক্যাশে করা উত্তর বৈধ না হওয়া পর্যন্ত, সমস্ত লাইসেন্স চেকের জন্য ক্যাশে করা উত্তর ফেরত দেয়। সার্ভার-প্রদত্ত VT এক্সট্রা অনুযায়ী উত্তরের বৈধতা সেট করার জন্য বিশেষভাবে সাজেস্ট করা হয়। আরও তথ্যের জন্য সার্ভার রেসপন্স এক্সট্রা দেখুন।
  3. কোনও অনুরোধের ফলে সমস্যা হলে, আবার চেষ্টা করার জন্য এক্সপোনেনশিয়াল ব্যাকঅফ পিরিয়ড ব্যবহার করে। মনে রাখবেন যে Google Play ক্লায়েন্ট অটোমেটিক ব্যর্থ অনুরোধ আবার করার চেষ্টা করে, তাই বেশিরভাগ ক্ষেত্রে আপনার Policy-এর সেগুলি আবার করার চেষ্টা করার প্রয়োজন নেই।
  4. "অতিরিক্ত সময়কাল" প্রদান করে যা ব্যবহারকারীকে সীমিত সময় বা ব্যবহারের সংখ্যার জন্য আপনার অ্যাপ্লিকেশন অ্যাক্সেস করার অনুমতি দেয়, যখন লাইসেন্স চেক আবার চেষ্টা করা হচ্ছে। অতিরিক্ত সময়কাল ব্যবহারকারীকে পরবর্তী লাইসেন্স চেক সম্পূর্ণ না হওয়া পর্যন্ত অ্যাক্সেস প্রদান করে এবং আপনার অ্যাপ্লিকেশন অ্যাক্সেসের উপর একটি কঠোর সীমা আরোপ করে আপনাকে সাহায্য করে, যখন কোনও বৈধ লাইসেন্স উত্তর উপলভ্য থাকে না।

উপরে তালিকাভুক্ত নির্দেশিকা অনুযায়ী আপনার Policy ডিজাইন করা অত্যন্ত গুরুত্বপূর্ণ, কারণ এটি ব্যবহারকারীদের জন্য সম্ভাব্য সেরা অভিজ্ঞতা নিশ্চিত করে এবং ত্রুটিপূর্ণ পরিস্থিতিতেও আপনার অ্যাপ্লিকেশনের উপর আপনাকে কার্যকর নিয়ন্ত্রণ প্রদান করে।

মনে রাখবেন, যেকোনও Policy বৈধতা ও ক্যাশিং, অতিরিক্ত সময়কালের জন্য আবার চেষ্টা করা এবং আরও অনেক কিছু ম্যানেজ করতে সাহায্য করার জন্য লাইসেন্সিং সার্ভারের দেওয়া সেটিংস ব্যবহার করতে পারে। সার্ভার-প্রদত্ত সেটিংস এক্সট্র্যাক্ট করা সহজ এবং সেগুলি ব্যবহার করার জন্য সুপারিশ করা হয়। কীভাবে অতিরিক্ত তথ্য এক্সট্র্যাক্ট ও ব্যবহার করতে হয় তার উদাহরণ দেখতে ServerManagedPolicy ইমপ্লিমেন্টেশন দেখুন। সার্ভার সেটিংসের তালিকা এবং সেগুলি কীভাবে ব্যবহার করতে হয় সেই সম্পর্কে তথ্যের জন্য, সার্ভার রেসপন্স এক্সট্রা দেখুন।

ServerManagedPolicy

LVL-এ ServerManagedPolicy নামক Policy ইন্টারফেসের সম্পূর্ণ ও সাজেস্ট করা ইমপ্লিমেন্টেশন অন্তর্ভুক্ত থাকে। প্রয়োগটি LVL ক্লাসের সাথে ইন্টিগ্রেট করা হয় এবং লাইব্রেরিতে ডিফল্ট Policy হিসেবে কাজ করে।

ServerManagedPolicy লাইসেন্স ও আবার চেষ্টা করার উত্তর সংক্রান্ত সব কিছু ম্যানেজ করে। এটি স্থানীয়ভাবে একটি SharedPreferences ফাইলে সমস্ত রেসপন্স ডেটা ক্যাশে করে, অ্যাপ্লিকেশনের Obfuscator ইমপ্লিমেন্টেশনের মাধ্যমে এটিকে অস্পষ্ট করে। এটি নিশ্চিত করে যে লাইসেন্স রেসপন্স ডেটা সুরক্ষিত আছে এবং ডিভাইস পাওয়ার সাইকেল জুড়ে থাকে। ServerManagedPolicy ইন্টারফেস পদ্ধতির কংক্রিট ইমপ্লিমেন্টেশন প্রদান করে processServerResponse() এবং allowAccess() এবং লাইসেন্স সংক্রান্ত উত্তর ম্যানেজ করার জন্য সহায়ক পদ্ধতি ও প্রকারের সেটও অন্তর্ভুক্ত করে।

গুরুত্বপূর্ণভাবে, ServerManagedPolicy-এর একটি মূল ফিচার হল, অ্যাপ্লিকেশনের রিফান্ড পিরিয়ড জুড়ে এবং বিভিন্ন নেটওয়ার্ক ও ত্রুটির পরিস্থিতিতে লাইসেন্সিং ম্যানেজ করার ভিত্তি হিসেবে সার্ভার-প্রদত্ত সেটিংসের ব্যবহার। কোনও অ্যাপ্লিকেশন লাইসেন্স চেক করার জন্য Google Play সার্ভারের সাথে যোগাযোগ করলে, সার্ভার নির্দিষ্ট কিছু লাইসেন্স রেসপন্স টাইপের অতিরিক্ত ফিল্ডে কী-ভ্যালু পেয়ার হিসেবে একাধিক সেটিংস যোগ করে। যেমন, সার্ভার অ্যাপ্লিকেশনের লাইসেন্সের বৈধতার মেয়াদ, আবার চেষ্টা করার গ্রেস পিরিয়ড এবং আবার চেষ্টা করার সর্বাধিক অনুমোদিত সংখ্যা সহ অন্যান্য বিষয়ের জন্য সাজেস্ট করা ভ্যালু প্রদান করে। ServerManagedPolicy তার processServerResponse() পদ্ধতিতে লাইসেন্স রেসপন্স থেকে ভ্যালু এক্সট্র্যাক্ট করে এবং তার allowAccess() পদ্ধতিতে সেগুলি চেক করে। ServerManagedPolicy-এর মাধ্যমে ব্যবহৃত সার্ভার-প্রদত্ত সেটিংসের তালিকার জন্য, সার্ভার রেসপন্স এক্সট্রা দেখুন।

সুবিধা, সেরা পারফর্ম্যান্স এবং Google Play সার্ভার থেকে লাইসেন্স সেটিংস ব্যবহার করার সুবিধার জন্য, আপনার লাইসেন্সিং Policy হিসেবে ServerManagedPolicy ব্যবহার করার সুপারিশ করা হয়।

SharedPreferences-এ স্থানীয়ভাবে স্টোর করা লাইসেন্স রেসপন্স ডেটার নিরাপত্তা নিয়ে আপনি চিন্তিত হলে, আরও শক্তিশালী অবফাসকেশন অ্যালগরিদম ব্যবহার করতে পারেন অথবা আরও কঠোর Policy ডিজাইন করতে পারেন যা লাইসেন্স ডেটা স্টোর করে না। LVL-এ এই ধরনের Policy-এর উদাহরণ অন্তর্ভুক্ত থাকে — আরও তথ্যের জন্য StrictPolicy দেখুন।

ServerManagedPolicy ব্যবহার করতে, আপনার অ্যাক্টিভিটিতে এটি ইমপোর্ট করুন, একটি ইনস্ট্যান্স তৈরি করুন এবং আপনার LicenseChecker তৈরি করার সময় ইনস্ট্যান্সের একটি রেফারেন্স পাস করুন। আরও তথ্যের জন্য LicenseChecker এবং LicenseCheckerCallback ইনস্ট্যান্টিয়েট করুন দেখুন।

StrictPolicy

LVL-এ Policy ইন্টারফেসের একটি বিকল্প সম্পূর্ণ প্রয়োগ অন্তর্ভুক্ত রয়েছে যাকে StrictPolicy বলা হয়। StrictPolicy প্রয়োগের মাধ্যমে ServerManagedPolicy-এর তুলনায় আরও বেশি বিধিনিষেধযুক্ত নীতি প্রদান করা হয়, কারণ এটি ব্যবহারকারীকে অ্যাপ্লিকেশন অ্যাক্সেস করার অনুমতি দেয় না, যতক্ষণ না অ্যাক্সেস করার সময় সার্ভার থেকে লাইসেন্স সংক্রান্ত উত্তর পাওয়া যায়, যা থেকে বোঝা যায় যে ব্যবহারকারীর কাছে লাইসেন্স আছে।

StrictPolicy-এর প্রধান বৈশিষ্ট্য হল এটি স্থায়ী স্টোরে স্থানীয়ভাবে কোনও লাইসেন্স রেসপন্স ডেটা স্টোর করে না। কোনও ডেটা স্টোর করা হয় না বলে, আবার চেষ্টা করার অনুরোধ ট্র্যাক করা হয় না এবং ক্যাশে করা উত্তর লাইসেন্স চেক করার জন্য ব্যবহার করা যায় না। Policy শুধুমাত্র তখনই অ্যাক্সেস করার অনুমতি দেয় যদি:

  • লাইসেন্সিং সার্ভার থেকে লাইসেন্স সংক্রান্ত উত্তর পাওয়া গেছে এবং
  • লাইসেন্স সংক্রান্ত উত্তর থেকে বোঝা যায় যে ব্যবহারকারীর কাছে অ্যাপ্লিকেশন অ্যাক্সেস করার লাইসেন্স আছে।

StrictPolicy ব্যবহার করা তখনই উপযুক্ত যখন আপনার প্রাথমিক লক্ষ্য হল, সম্ভাব্য সব ক্ষেত্রে, কোনও ব্যবহারকারীকে অ্যাপ্লিকেশন অ্যাক্সেস করার অনুমতি দেওয়া হবে না, যদি না ব্যবহারের সময় ব্যবহারকারীর লাইসেন্স আছে বলে কনফার্ম করা হয়। এছাড়াও, ServerManagedPolicy-এর থেকে Policy কিছুটা বেশি সুরক্ষা প্রদান করে — কারণ স্থানীয়ভাবে কোনও ডেটা ক্যাশে করা হয় না, তাই কোনও ক্ষতিকর ব্যবহারকারী ক্যাশে করা ডেটা নিয়ে কারচুপি করতে এবং অ্যাপ্লিকেশনে অ্যাক্সেস পেতে পারে না।

একই সাথে, এই Policy সাধারণ ব্যবহারকারীদের জন্য একটি চ্যালেঞ্জ তৈরি করে, কারণ এর অর্থ হল যে কোনও নেটওয়ার্ক (সেল বা ওয়াই-ফাই) কানেকশন উপলভ্য না থাকলে তারা অ্যাপ্লিকেশনটি অ্যাক্সেস করতে পারবেন না। অন্য একটি পার্শ্ব-প্রতিক্রিয়া হল, আপনার অ্যাপ্লিকেশন সার্ভারে আরও বেশি লাইসেন্স চেক করার অনুরোধ পাঠাবে, কারণ ক্যাশে করা উত্তর ব্যবহার করা সম্ভব নয়।

সামগ্রিকভাবে, এই নীতিটি অ্যাক্সেসের উপর সম্পূর্ণ নিরাপত্তা এবং নিয়ন্ত্রণের জন্য ব্যবহারকারীর সুবিধার কিছু মাত্রার একটি ট্রেডঅফকে উপস্থাপন করে। এই Policy ব্যবহার করার আগে ট্রেড-অফ সম্পর্কে ভালোভাবে বিবেচনা করুন।

StrictPolicy ব্যবহার করতে, আপনার অ্যাক্টিভিটিতে এটি ইমপোর্ট করুন, একটি ইনস্ট্যান্স তৈরি করুন, এবং আপনার LicenseChecker তৈরি করার সময় এটির একটি রেফারেন্স পাস করুন। আরও তথ্যের জন্য LicenseChecker এবং LicenseCheckerCallback ইনস্ট্যান্টিয়েট করুন দেখুন।

সাধারণত Policy প্রয়োগ করার জন্য কোনও অ্যাপ্লিকেশনের লাইসেন্স রেসপন্স ডেটা একটি পারসিস্টেন্ট স্টোরে সেভ করতে হয়, যাতে অ্যাপ্লিকেশন ইনভোকেশন এবং ডিভাইস পাওয়ার সাইকেল জুড়ে এটি অ্যাক্সেস করা যায়। যেমন, Policy শেষবার সফলভাবে লাইসেন্স চেক করার টাইমস্ট্যাম্প, কতবার চেষ্টা করা হয়েছে, লাইসেন্সের বৈধতার মেয়াদ এবং এই ধরনের তথ্য একটি স্থায়ী স্টোরে সেভ করে রাখবে, প্রতিবার অ্যাপ্লিকেশন চালু করার সময় ভ্যালু রিসেট করবে না। LVL-এ অন্তর্ভুক্ত ডিফল্ট Policy, ServerManagedPolicy, লাইসেন্স রেসপন্স ডেটা SharedPreferences ইনস্ট্যান্সে স্টোর করে, যাতে ডেটা স্থায়ী হয়।

অ্যাপ্লিকেশনে অ্যাক্সেস দেওয়া হবে কিনা তা নির্ধারণ করতে Policy সেভ করা লাইসেন্স রেসপন্স ডেটা ব্যবহার করবে, তাই এটি অবশ্যই নিশ্চিত করবে যে সেভ করা যেকোনও ডেটা সুরক্ষিত আছে এবং ডিভাইসে রুট ব্যবহারকারী সেটি আবার ব্যবহার বা ম্যানিপুলেট করতে পারবেন না। বিশেষ করে, Policy-কে অবশ্যই ডেটা স্টোর করার আগে তা অস্পষ্ট করতে হবে, অ্যাপ্লিকেশন এবং ডিভাইসের জন্য অনন্য একটি কী ব্যবহার করে। অ্যাপ্লিকেশন-নির্দিষ্ট এবং ডিভাইস-নির্দিষ্ট, উভয় ধরনের কী ব্যবহার করে অস্পষ্ট করা গুরুত্বপূর্ণ, কারণ এটি অ্যাপ্লিকেশন এবং ডিভাইসের মধ্যে অস্পষ্ট ডেটা শেয়ার করা প্রতিরোধ করে।

LVL, অ্যাপ্লিকেশনকে তার লাইসেন্স রেসপন্স ডেটা সুরক্ষিত, স্থায়ীভাবে স্টোর করতে সাহায্য করে। প্রথমত, এটি একটি Obfuscator ইন্টারফেস প্রদান করে যা আপনার অ্যাপ্লিকেশনকে সেভ করা ডেটার জন্য তার পছন্দের অস্পষ্টতা অ্যালগরিদম সরবরাহ করতে দেয়। তার উপর ভিত্তি করে, LVL হেল্পার ক্লাস PreferenceObfuscator প্রদান করে, যা অ্যাপ্লিকেশনের Obfuscator ক্লাস কল করা এবং SharedPreferences ইনস্ট্যান্সে অস্পষ্ট ডেটা পড়া ও লেখার বেশিরভাগ কাজ পরিচালনা করে।

LVL সম্পূর্ণ Obfuscator ইমপ্লিমেন্টেশন প্রদান করে, যাকে AESObfuscator বলা হয়। এটি ডেটা অস্পষ্ট করতে AES এনক্রিপশন ব্যবহার করে। আপনি কোনও পরিবর্তন না করেই আপনার অ্যাপ্লিকেশনে AESObfuscator ব্যবহার করতে পারেন অথবা আপনার প্রয়োজন অনুযায়ী এটি মানিয়ে নিতে পারেন। আপনি যদি এমন কোনও Policy (যেমন ServerManagedPolicy) ব্যবহার করেন যা লাইসেন্স রেসপন্স ডেটা ক্যাশে করে, তাহলে আপনার Obfuscator ইমপ্লিমেন্টেশনের ভিত্তি হিসেবে AESObfuscator ব্যবহার করার জন্য বিশেষভাবে সাজেস্ট করা হয়। আরও তথ্যের জন্য, পরবর্তী বিভাগ দেখুন।

AESObfuscator

LVL-এ AESObfuscator নামক Obfuscator ইন্টারফেসের সম্পূর্ণ ও সাজেস্ট করা ইমপ্লিমেন্টেশন অন্তর্ভুক্ত থাকে। এই ইমপ্লিমেন্টেশন LVL স্যাম্পেল অ্যাপ্লিকেশনের সাথে ইন্টিগ্রেট করা থাকে এবং লাইব্রেরিতে ডিফল্ট Obfuscator হিসেবে কাজ করে।

AESObfuscator, AES ব্যবহার করে ডেটার সুরক্ষিত অস্পষ্টতা প্রদান করে স্টোরেজে ডেটা লেখা বা পড়ার সময় ডেটা এনক্রিপ্ট এবং ডিক্রিপ্ট করতে। Obfuscator অ্যাপ্লিকেশন দ্বারা প্রদত্ত তিনটি ডেটা ফিল্ড ব্যবহার করে এনক্রিপশন সিড করে:

  1. সল্ট — প্রতিটি (আন)অবফাসকেশন করার জন্য ব্যবহার করা র‍্যান্ডম বাইটের অ্যারে।
  2. অ্যাপ্লিকেশন শনাক্তকারী স্ট্রিং, সাধারণত অ্যাপ্লিকেশনের প্যাকেজের নাম।
  3. ডিভাইস শনাক্তকারী স্ট্রিং, যা যতটা সম্ভব ডিভাইস-নির্দিষ্ট সোর্স থেকে নেওয়া হয়, যাতে এটি অনন্য হয়।

AESObfuscator ব্যবহার করতে, প্রথমে এটি আপনার অ্যাক্টিভিটিতে ইমপোর্ট করুন। সল্ট বাইট ধরে রাখার জন্য একটি ব্যক্তিগত স্ট্যাটিক ফাইনাল অ্যারে ঘোষণা করুন এবং এটিকে ২০টি র‍্যান্ডমলি জেনারেট করা বাইটে ইনিশিয়ালাইজ করুন।

Kotlin

// Generate 20 random bytes, and put them here.
private val SALT = byteArrayOf(
        -46, 65, 30, -128, -103, -57, 74, -64, 51, 88,
        -95, -45, 77, -117, -36, -113, -11, 32, -64, 89
)

জাভা

...
    // Generate 20 random bytes, and put them here.
    private static final byte[] SALT = new byte[] {
     -46, 65, 30, -128, -103, -57, 74, -64, 51, 88, -95,
     -45, 77, -117, -36, -113, -11, 32, -64, 89
     };
    ...

এরপর, ডিভাইস শনাক্তকারী ধরে রাখার জন্য একটি ভেরিয়েবল ঘোষণা করুন এবং প্রয়োজন অনুযায়ী যেকোনও উপায়ে এটির জন্য একটি ভ্যালু তৈরি করুন। যেমন, LVL-এ অন্তর্ভুক্ত স্যাম্পেল অ্যাপ্লিকেশন android.Settings.Secure.ANDROID_ID-এর জন্য সিস্টেম সেটিংস কোয়েরি করে, যা প্রতিটি ডিভাইসের জন্য অনন্য।

মনে রাখবেন, আপনি যে API ব্যবহার করেন তার উপর নির্ভর করে, ডিভাইস-নির্দিষ্ট তথ্য পেতে আপনার অ্যাপ্লিকেশনকে অতিরিক্ত অনুমতির অনুরোধ করতে হতে পারে। যেমন, ডিভাইসের IMEI বা সংশ্লিষ্ট ডেটা পেতে TelephonyManager-এ কোয়েরি করতে, অ্যাপ্লিকেশনকে তার ম্যানিফেস্টে android.permission.READ_PHONE_STATE অনুমতির জন্য অনুরোধ করতে হবে।

আপনার Obfuscator-এ ব্যবহার করার জন্য ডিভাইস-নির্দিষ্ট তথ্য পাওয়ার একমাত্র উদ্দেশ্যে নতুন অনুমতির অনুরোধ করার আগে, এটি আপনার অ্যাপ্লিকেশন বা Google Play-তে এর ফিল্টারিংয়ের উপর কীভাবে প্রভাব ফেলতে পারে তা বিবেচনা করুন (কারণ কিছু অনুমতি SDK বিল্ড টুলকে সংশ্লিষ্ট <uses-feature> যোগ করতে বাধ্য করতে পারে)।

শেষে, সল্ট, অ্যাপ্লিকেশন শনাক্তকারী এবং ডিভাইস শনাক্তকারী পাস করে AESObfuscator-এর একটি ইনস্ট্যান্স তৈরি করুন। আপনার Policy এবং LicenseChecker তৈরি করার সময়, আপনি সরাসরি ইনস্ট্যান্স তৈরি করতে পারবেন। যেমন:

Kotlin

    ...
    // Construct the LicenseChecker with a Policy.
    private val checker = LicenseChecker(
            this,
            ServerManagedPolicy(this, AESObfuscator(SALT, packageName, deviceId)),
            BASE64_PUBLIC_KEY
    )
    ...

জাভা

    ...
    // Construct the LicenseChecker with a Policy.
    checker = new LicenseChecker(
        this, new ServerManagedPolicy(this,
            new AESObfuscator(SALT, getPackageName(), deviceId)),
        BASE64_PUBLIC_KEY // Your public licensing key.
        );
    ...

সম্পূর্ণ উদাহরণের জন্য, LVL স্যাম্পেল অ্যাপ্লিকেশনে MainActivity দেখুন।

অ্যাক্টিভিটি থেকে লাইসেন্স চেক করা

আপনার অ্যাপ্লিকেশনে অ্যাক্সেস ম্যানেজ করার জন্য Policy প্রয়োগ করার পরে, পরবর্তী ধাপ হল আপনার অ্যাপ্লিকেশনে লাইসেন্স চেক যোগ করা, যা প্রয়োজন হলে লাইসেন্সিং সার্ভারে কোয়েরি শুরু করে এবং লাইসেন্স উত্তরের ভিত্তিতে অ্যাপ্লিকেশনে অ্যাক্সেস ম্যানেজ করে। লাইসেন্স চেক যোগ করা এবং উত্তর ম্যানেজ করার সব কাজ আপনার মূল Activity সোর্স ফাইলে করা হয়।

লাইসেন্স চেক যোগ করতে এবং উত্তর ম্যানেজ করতে, আপনাকে অবশ্যই:

  1. ইমপোর্ট যোগ করুন
  2. একটি ব্যক্তিগত ইনার ক্লাস হিসেবে LicenseCheckerCallback প্রয়োগ করুন
  3. LicenseCheckerCallback থেকে UI থ্রেডে পোস্ট করার জন্য একটি হ্যান্ডলার তৈরি করুন
  4. LicenseChecker এবং LicenseCheckerCallback ইনস্ট্যান্টিয়েট করুন
  5. লাইসেন্স চেক শুরু করতে checkAccess() কল করুন
  6. লাইসেন্সিংয়ের জন্য আপনার পাবলিক কী এম্বেড করুন
  7. IPC কানেকশন বন্ধ করতে আপনার LicenseChecker-এর onDestroy() পদ্ধতি কল করুন।

নিচের বিভাগগুলিতে এইসব টাস্কের ব্যাপারে বর্ণনা করা হয়েছে।

লাইসেন্স চেক ও উত্তর এক নজরে দেখে নেওয়া

বেশিরভাগ ক্ষেত্রে, আপনার অ্যাপ্লিকেশনের মূল Activity-এ, onCreate() পদ্ধতিতে লাইসেন্স চেক যোগ করা উচিত। এটি নিশ্চিত করে যে ব্যবহারকারী সরাসরি আপনার অ্যাপ্লিকেশন চালু করলে, লাইসেন্স চেক অবিলম্বে শুরু হবে। কিছু ক্ষেত্রে, আপনি অন্যান্য লোকেশনেও লাইসেন্স চেক যোগ করতে পারবেন। যেমন, আপনার অ্যাপ্লিকেশনে একাধিক অ্যাক্টিভিটি কম্পোনেন্ট থাকলে, যা অন্যান্য অ্যাপ্লিকেশন Intent-এর মাধ্যমে শুরু করতে পারে, আপনি সেইসব অ্যাক্টিভিটিতে লাইসেন্স চেক যোগ করতে পারেন।

লাইসেন্স চেক করার মধ্যে দুটি প্রধান অ্যাকশন রয়েছে:

  • লাইসেন্স চেক শুরু করার জন্য মেথড কল — LVL-এ, এটি হল আপনার তৈরি করা LicenseChecker অবজেক্টের checkAccess() মেথডের একটি কল।
  • একটি কলব্যাক যা লাইসেন্স চেক করার ফলাফল দেখায়। LVL-এ, এটি হল একটি LicenseCheckerCallback ইন্টারফেস যা আপনি প্রয়োগ করেন। allow() এবং dontAllow(), এই দুটি পদ্ধতি ইন্টারফেস ঘোষণা করে, যা লাইসেন্স চেক করার ফলাফলের উপর ভিত্তি করে লাইব্রেরি দ্বারা আহ্বান করা হয়। আপনার অ্যাপ্লিকেশনে ব্যবহারকারীর অ্যাক্সেস অনুমোদন বা বাতিল করার জন্য, আপনার প্রয়োজন অনুযায়ী যেকোনও লজিক সহ এই দুটি পদ্ধতি প্রয়োগ করুন। মনে রাখবেন যে এইসব পদ্ধতি অ্যাক্সেস করার অনুমতি দেওয়া হবে কিনা তা নির্ধারণ করে না — সেই নির্ধারণ করার দায়িত্ব আপনার Policy প্রয়োগের। বরং, এই পদ্ধতিগুলি সহজেই অ্যাপ্লিকেশনকে অ্যাক্সেস মঞ্জুর ও বাতিল করার (এবং অ্যাপ্লিকেশন সংক্রান্ত সমস্যা ম্যানেজ করার) উপায় প্রদান করে।

    allow() এবং dontAllow() পদ্ধতি তাদের উত্তরের জন্য একটি "কারণ" প্রদান করে, যা Policy ভ্যালু, LICENSED, NOT_LICENSED, বা RETRY-এর মধ্যে একটি হতে পারে। বিশেষ করে, আপনাকে এমন পরিস্থিতি সামলাতে হবে যেখানে পদ্ধতিটি dontAllow()-এর জন্য RETRY উত্তর পায় এবং ব্যবহারকারীকে একটি "আবার চেষ্টা করুন" বোতাম প্রদান করে, যা অনুরোধের সময় পরিষেবাটি উপলভ্য না থাকার কারণে ঘটতে পারে।

ছবি ১. সাধারণ লাইসেন্স চেক ইন্টার‍্যাকশনের এক নজরে।

সাধারণত লাইসেন্স চেক কীভাবে করা হয় তা উপরের ডায়াগ্রাম থেকে বোঝা যায়:

  1. অ্যাপ্লিকেশনের প্রধান অ্যাক্টিভিটিতে থাকা কোড LicenseCheckerCallback এবং LicenseChecker অবজেক্ট ইনস্ট্যান্টিয়েট করে। LicenseChecker তৈরি করার সময়, কোডটি Context, ব্যবহার করার জন্য একটি Policy ইমপ্লিমেন্টেশন এবং প্যারামিটার হিসেবে লাইসেন্সিংয়ের জন্য প্রকাশকের অ্যাকাউন্টের সর্বজনীন কী পাস করে।
  2. তারপর কোডটি LicenseChecker অবজেক্টে checkAccess() মেথড কল করে। মেথড ইমপ্লিমেন্টেশন Policy-কে কল করে, যাতে SharedPreferences-এ স্থানীয়ভাবে ক্যাশে করা কোনও সঠিক লাইসেন্স রেসপন্স আছে কিনা তা নির্ধারণ করা যায়।
    • যদি তাই হয়, তাহলে checkAccess()টি ইমপ্লিমেন্টেশন কল allow()।
    • অন্যথায়, LicenseChecker লাইসেন্স চেক করার অনুরোধ শুরু করে যা লাইসেন্সিং সার্ভারে পাঠানো হয়।

    মনে রাখবেন: আপনি কোনও ড্রাফ্ট অ্যাপ্লিকেশনের লাইসেন্স চেক করলে, লাইসেন্সিং সার্ভার সবসময় LICENSED রিটার্ন করে।

  3. উত্তর পাওয়া গেলে, LicenseChecker একটি LicenseValidator তৈরি করে যা স্বাক্ষরিত লাইসেন্স ডেটা যাচাই করে এবং উত্তরের ফিল্ডগুলি এক্সট্র্যাক্ট করে, তারপর আরও মূল্যায়নের জন্য সেগুলি আপনার Policy-এ পাস করে।
    • লাইসেন্সটি বৈধ হলে, Policy SharedPreferences-এ উত্তর ক্যাশে করে এবং যাচাইকারীকে বিজ্ঞপ্তি দেয়, যা পরে LicenseCheckerCallback অবজেক্টে allow() পদ্ধতিকে কল করে।
    • লাইসেন্স বৈধ না হলে, Policy ভ্যালিডেটরকে বিজ্ঞপ্তি পাঠায়, যা LicenseCheckerCallback-এ dontAllow() মেথডকে কল করে।
  4. সমাধান করা যায় এমন লোকাল বা সার্ভার সংক্রান্ত সমস্যার ক্ষেত্রে, যেমন অনুরোধ পাঠানোর জন্য নেটওয়ার্ক উপলভ্য না থাকলে, LicenseChecker আপনার Policy অবজেক্টের processServerResponse() পদ্ধতিতে RETRY রেসপন্স পাস করে।

    এছাড়াও, allow() এবং dontAllow() কলব্যাক পদ্ধতি দুটিই একটি reason আর্গুমেন্ট পায়। allow() পদ্ধতির কারণ সাধারণত Policy.LICENSED বা Policy.RETRY এবং dontAllow() পদ্ধতির কারণ সাধারণত Policy.NOT_LICENSED বা Policy.RETRY। এইসব রেসপন্স ভ্যালু খুবই উপযোগী, যাতে আপনি ব্যবহারকারীকে উপযুক্ত রেসপন্স দেখাতে পারেন, যেমন dontAllow()-এর রেসপন্স Policy.RETRY হলে "আবার চেষ্টা করুন" বোতাম দেখানো, যা পরিষেবা উপলভ্য না থাকার কারণে হতে পারে।

  5. অ্যাপ্লিকেশনে কোনও সমস্যা হলে, যেমন অ্যাপ্লিকেশনটি কোনও ভুল প্যাকেজের নামের লাইসেন্স চেক করার চেষ্টা করলে, LicenseChecker, LicenseCheckerCallback-এর applicationError() পদ্ধতিতে একটি সমস্যার উত্তর পাঠায়।

মনে রাখবেন, লাইসেন্স চেক শুরু করা এবং ফলাফল ম্যানেজ করার পাশাপাশি, যা নিচের বিভাগে বর্ণনা করা হয়েছে, আপনার অ্যাপ্লিকেশনকে নীতি প্রয়োগ করতে হবে এবং যদি Policy রেসপন্স ডেটা (যেমন ServerManagedPolicy) স্টোর করে, তাহলে Obfuscator প্রয়োগ করতে হবে।

ইম্পোর্ট যোগ করুন

প্রথমে, অ্যাপ্লিকেশনের প্রধান অ্যাক্টিভিটির ক্লাস ফাইল খুলুন এবং LVL প্যাকেজ থেকে LicenseChecker ও LicenseCheckerCallback ইমপোর্ট করুন।

Kotlin

import com.google.android.vending.licensing.LicenseChecker
import com.google.android.vending.licensing.LicenseCheckerCallback

জাভা

import com.google.android.vending.licensing.LicenseChecker;
import com.google.android.vending.licensing.LicenseCheckerCallback;

আপনি যদি LVL-এর সাথে প্রদান করা ডিফল্ট Policy ইমপ্লিমেন্টেশন ব্যবহার করেন, ServerManagedPolicy, AESObfuscator-এর সাথে এটিও ইমপোর্ট করুন। আপনি যদি কাস্টম Policy বা Obfuscator ব্যবহার করেন, তাহলে তার পরিবর্তে সেগুলি ইমপোর্ট করুন।

Kotlin

import com.google.android.vending.licensing.ServerManagedPolicy
import com.google.android.vending.licensing.AESObfuscator

জাভা

import com.google.android.vending.licensing.ServerManagedPolicy;
import com.google.android.vending.licensing.AESObfuscator;

LicenseCheckerCallback-কে একটি ব্যক্তিগত ইনার ক্লাস হিসেবে প্রয়োগ করুন

LicenseCheckerCallback হল LVL-এর প্রদান করা একটি ইন্টারফেস যা লাইসেন্স চেক করার ফলাফল ম্যানেজ করে। LVL ব্যবহার করে লাইসেন্সিং সমর্থন করতে, আপনাকে অবশ্যই LicenseCheckerCallback এবং অ্যাপ্লিকেশনে অ্যাক্সেসের অনুমতি দিতে বা না দিতে এর পদ্ধতিগুলি প্রয়োগ করতে হবে।

লাইসেন্স চেক করার ফলাফল সবসময় LicenseCheckerCallback মেথডের মধ্যে কোনও একটিতে কল করে, যা রেসপন্স পেলোডের যাচাইকরণ, সার্ভার রেসপন্স কোড এবং আপনার Policy-এর মাধ্যমে প্রদান করা যেকোনও অতিরিক্ত প্রসেসিংয়ের উপর ভিত্তি করে করা হয়। আপনার অ্যাপ্লিকেশন যেকোনও উপায়ে পদ্ধতিগুলি প্রয়োগ করতে পারে। সাধারণত, পদ্ধতিগুলি সহজ রাখাই সবচেয়ে ভালো, সেগুলিকে UI স্টেট এবং অ্যাপ্লিকেশন অ্যাক্সেস ম্যানেজ করার মধ্যে সীমাবদ্ধ রাখুন। আপনি যদি লাইসেন্স সংক্রান্ত উত্তরে আরও প্রসেসিং যোগ করতে চান, যেমন ব্যাকএন্ড সার্ভারের সাথে যোগাযোগ করা বা কাস্টম সীমাবদ্ধতা প্রয়োগ করা, তাহলে আপনার সেই কোডটি LicenseCheckerCallback পদ্ধতিতে না রেখে Policy-এ অন্তর্ভুক্ত করার কথা বিবেচনা করা উচিত।

বেশিরভাগ ক্ষেত্রে, আপনার অ্যাপ্লিকেশনের প্রধান অ্যাক্টিভিটি ক্লাসের মধ্যে LicenseCheckerCallback-এর ইমপ্লিমেন্টেশনকে প্রাইভেট ক্লাস হিসেবে ঘোষণা করা উচিত।

প্রয়োজন অনুযায়ী allow() এবং dontAllow() পদ্ধতি প্রয়োগ করুন। শুরু করার জন্য, আপনি মেথডে সহজ ফলাফল-হ্যান্ডলিং আচরণ ব্যবহার করতে পারেন, যেমন একটি ডায়ালগে লাইসেন্সের ফলাফল প্রদর্শন করা। এটি আপনাকে সাহায্য করে আপনার অ্যাপ্লিকেশন দ্রুত চালানো এবং ডিবাগিংয়ে সহায়তা করতে পারে। পরে, আপনি ঠিক কী ধরনের আচরণ চান তা নির্ধারণ করার পরে, আপনি আরও জটিল হ্যান্ডলিং যোগ করতে পারেন।

dontAllow()-এ লাইসেন্সবিহীন উত্তর ম্যানেজ করার জন্য কিছু সাজেশন নিচে দেওয়া হল:

  • ব্যবহারকারীকে "আবার চেষ্টা করুন" ডায়ালগ দেখান, যার মধ্যে নতুন লাইসেন্স চেক শুরু করার জন্য একটি বোতাম থাকবে, যদি reason-এর ভ্যালু Policy.RETRY হয়।
  • "এই অ্যাপ্লিকেশনটি কিনুন" ডায়ালগ দেখান, যার মধ্যে এমন একটি বোতাম থাকবে যা ব্যবহারকারীকে Google Play-তে অ্যাপ্লিকেশনের বিবরণ পৃষ্ঠায় ডিপ-লিঙ্ক করে, যেখান থেকে ব্যবহারকারী অ্যাপ্লিকেশনটি কিনতে পারবেন। এই ধরনের লিঙ্ক কীভাবে সেট-আপ করতে হয় সেই সম্পর্কে আরও জানতে, আপনার প্রোডাক্টের সাথে লিঙ্ক করা দেখুন।
  • একটি টোস্ট বিজ্ঞপ্তি দেখান যা ইঙ্গিত করে যে অ্যাপ্লিকেশনটির বৈশিষ্ট্যগুলি সীমিত কারণ এটি লাইসেন্সপ্রাপ্ত নয়।

নিচের উদাহরণে দেখানো হয়েছে যে কীভাবে LVL স্যাম্পেল অ্যাপ্লিকেশন LicenseCheckerCallback প্রয়োগ করে, যেখানে ডায়ালগে লাইসেন্স চেক করার ফলাফল দেখানোর পদ্ধতি ব্যবহার করা হয়।

Kotlin

private inner class MyLicenseCheckerCallback : LicenseCheckerCallback {

    override fun allow(reason: Int) {
        if (isFinishing) {
            // Don't update UI if Activity is finishing.
            return
        }
        // Should allow user access.
        displayResult(getString(R.string.allow))
    }

    override fun dontAllow(reason: Int) {
        if (isFinishing) {
            // Don't update UI if Activity is finishing.
            return
        }
        displayResult(getString(R.string.dont_allow))

        if (reason == Policy.RETRY) {
            // If the reason received from the policy is RETRY, it was probably
            // due to a loss of connection with the service, so we should give the
            // user a chance to retry. So show a dialog to retry.
            showDialog(DIALOG_RETRY)
        } else {
            // Otherwise, the user isn't licensed to use this app.
            // Your response should always inform the user that the application
            // isn't licensed, but your behavior at that point can vary. You might
            // provide the user a limited access version of your app or you can
            // take them to Google Play to purchase the app.
            showDialog(DIALOG_GOTOMARKET)
        }
    }
}

জাভা

private class MyLicenseCheckerCallback implements LicenseCheckerCallback {
    public void allow(int reason) {
        if (isFinishing()) {
            // Don't update UI if Activity is finishing.
            return;
        }
        // Should allow user access.
        displayResult(getString(R.string.allow));
    }

    public void dontAllow(int reason) {
        if (isFinishing()) {
            // Don't update UI if Activity is finishing.
            return;
        }
        displayResult(getString(R.string.dont_allow));

        if (reason == Policy.RETRY) {
            // If the reason received from the policy is RETRY, it was probably
            // due to a loss of connection with the service, so we should give the
            // user a chance to retry. So show a dialog to retry.
            showDialog(DIALOG_RETRY);
        } else {
            // Otherwise, the user isn't licensed to use this app.
            // Your response should always inform the user that the application
            // isn't licensed, but your behavior at that point can vary. You might
            // provide the user a limited access version of your app or you can
            // take them to Google Play to purchase the app.
            showDialog(DIALOG_GOTOMARKET);
        }
    }
}

এছাড়াও, আপনাকে applicationError() পদ্ধতি প্রয়োগ করতে হবে, যা LVL কল করে যাতে আপনার অ্যাপ্লিকেশন এমন সমস্যা ম্যানেজ করতে পারে যা আবার চেষ্টা করা যায় না। এই ধরনের সমস্যার তালিকা দেখতে, লাইসেন্সিং রেফারেন্স-এ সার্ভার রেসপন্স কোড দেখুন। আপনি যেকোনও উপায়ে পদ্ধতিটি প্রয়োগ করতে পারেন। বেশিরভাগ ক্ষেত্রে, পদ্ধতিটি ত্রুটি কোড লগ করবে এবং dontAllow() কল করবে।

LicenseCheckerCallback থেকে UI থ্রেডে পোস্ট করার জন্য একটি হ্যান্ডলার তৈরি করুন

লাইসেন্স চেক করার সময়, LVL, Google Play অ্যাপ্লিকেশনে অনুরোধ পাঠায়, যা লাইসেন্সিং সার্ভারের সাথে যোগাযোগ পরিচালনা করে। LVL অ্যাসিঙ্ক্রোনাস IPC (Binder ব্যবহার করে) মাধ্যমে অনুরোধ পাস করে, যাতে আসল প্রসেসিং এবং নেটওয়ার্ক কমিউনিকেশন আপনার অ্যাপ্লিকেশন দ্বারা ম্যানেজ করা থ্রেডে না হয়। একইভাবে, Google Play অ্যাপ্লিকেশন ফলাফল পেলে, এটি IPC-তে কলব্যাক পদ্ধতি চালু করে, যা আপনার অ্যাপ্লিকেশনের প্রসেসে IPC থ্রেড পুলে রান করে।

LicenseChecker ক্লাস Google Play অ্যাপ্লিকেশনের সাথে আপনার অ্যাপ্লিকেশনের IPC কমিউনিকেশন ম্যানেজ করে, যার মধ্যে অনুরোধ পাঠানো কল এবং উত্তর পাওয়া কলব্যাক অন্তর্ভুক্ত। এছাড়াও, LicenseChecker ওপেন লাইসেন্স অনুরোধ ট্র্যাক করে এবং সেগুলির টাইমআউট ম্যানেজ করে।

যাতে এটি টাইম-আউট সঠিকভাবে ম্যানেজ করতে পারে এবং আপনার অ্যাপ্লিকেশনের UI থ্রেডকে প্রভাবিত না করেই ইনকামিং উত্তর প্রসেস করতে পারে, তাই LicenseChecker ইনস্ট্যান্টিয়েশনের সময় একটি ব্যাকগ্রাউন্ড থ্রেড তৈরি করে। থ্রেডে এটি লাইসেন্স চেক করার ফলাফল প্রসেস করে, ফলাফল সার্ভার থেকে পাওয়া উত্তর বা টাইমআউট সংক্রান্ত সমস্যা যাই হোক না কেন। প্রসেসিং শেষ হলে, LVL ব্যাকগ্রাউন্ড থ্রেড থেকে আপনার LicenseCheckerCallback মেথড কল করে।

আপনার অ্যাপ্লিকেশনের ক্ষেত্রে এর অর্থ হল:

  1. আপনার LicenseCheckerCallback পদ্ধতি, অনেক ক্ষেত্রে, ব্যাকগ্রাউন্ড থ্রেড থেকে ইনভোক করা হবে।
  2. UI থ্রেডে হ্যান্ডলার তৈরি না করলে এবং হ্যান্ডলারে কলব্যাক পদ্ধতি পোস্ট না করলে, এইসব পদ্ধতি UI থ্রেডে স্ট্যাটাস আপডেট করতে বা কোনও প্রসেসিং চালু করতে পারবে না।

আপনি যদি চান যে আপনার LicenseCheckerCallback পদ্ধতি UI থ্রেড আপডেট করুক, তাহলে নিচে দেখানো হিসাবে মূল অ্যাক্টিভিটির onCreate() পদ্ধতিতে একটি Handler ইনস্ট্যান্টিয়েট করুন। এই উদাহরণে, LVL স্যাম্পেল অ্যাপ্লিকেশনের LicenseCheckerCallback পদ্ধতি (উপরে দেখুন) displayResult()-কে কল করে যাতে হ্যান্ডলারের post() পদ্ধতির মাধ্যমে UI থ্রেড আপডেট করা যায়।

Kotlin

    private lateinit var handler: Handler

    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        handler = Handler()
    }

জাভা

    private Handler handler;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        ...
        handler = new Handler();
    }

তারপর, আপনার LicenseCheckerCallback পদ্ধতিতে, আপনি হ্যান্ডলার পদ্ধতি ব্যবহার করে হ্যান্ডলারে Runnable বা Message অবজেক্ট পোস্ট করতে পারেন। লাইসেন্সের স্ট্যাটাস দেখানোর জন্য LVL-এ অন্তর্ভুক্ত স্যাম্পেল অ্যাপ্লিকেশন কীভাবে UI থ্রেডে হ্যান্ডলারের কাছে রানএবেল পোস্ট করে তা এখানে দেখানো হয়েছে।

Kotlin

private fun displayResult(result: String) {
    handler.post {
        statusText.text = result
        setProgressBarIndeterminateVisibility(false)
        checkLicenseButton.isEnabled = true
    }
}

জাভা

private void displayResult(final String result) {
        handler.post(new Runnable() {
            public void run() {
                statusText.setText(result);
                setProgressBarIndeterminateVisibility(false);
                checkLicenseButton.setEnabled(true);
            }
        });
    }

LicenseChecker এবং LicenseCheckerCallback ইনস্ট্যান্টিয়েট করুন

প্রধান অ্যাক্টিভিটির onCreate() পদ্ধতিতে, LicenseCheckerCallback এবং LicenseChecker-এর ব্যক্তিগত ইনস্ট্যান্স তৈরি করুন। আপনাকে প্রথমে LicenseCheckerCallback ইনস্ট্যান্টিয়েট করতে হবে, কারণ LicenseChecker-এর জন্য কনস্ট্রাক্টর কল করার সময় আপনাকে সেই ইনস্ট্যান্সের রেফারেন্স পাস করতে হবে।

আপনি যখন LicenseChecker ইনস্ট্যান্টিয়েট করেন, তখন আপনাকে এইসব প্যারামিটার পাস করতে হবে:

  • Context অ্যাপ্লিকেশন
  • লাইসেন্স চেক করার জন্য ব্যবহার করতে Policy প্রয়োগের রেফারেন্স। অধিকাংশ ক্ষেত্রে, আপনি LVL, ServerManagedPolicy-এর মাধ্যমে প্রদান করা ডিফল্ট Policy প্রয়োগ ব্যবহার করবেন।
  • লাইসেন্সিংয়ের জন্য আপনার প্রকাশক অ্যাকাউন্টের সর্বজনীন কী ধারণকারী স্ট্রিং ভেরিয়েবল।

আপনি ServerManagedPolicy ব্যবহার করলে, আপনাকে সরাসরি ক্লাস অ্যাক্সেস করতে হবে না, তাই আপনি LicenseChecker কনস্ট্রাক্টরে এটি ইনস্ট্যান্টিয়েট করতে পারবেন, যেমনটি নিচের উদাহরণে দেখানো হয়েছে। মনে রাখবেন, ServerManagedPolicy তৈরি করার সময় আপনাকে নতুন Obfuscator ইনস্ট্যান্সের রেফারেন্স পাস করতে হবে।

নিচের উদাহরণে দেখানো হয়েছে কীভাবে একটি অ্যাক্টিভিটি ক্লাসের onCreate() পদ্ধতি থেকে LicenseChecker এবং LicenseCheckerCallback ইনস্ট্যান্টিয়েট করা হয়।

Kotlin

class MainActivity : AppCompatActivity() {
    ...
    private lateinit var licenseCheckerCallback: LicenseCheckerCallback
    private lateinit var checker: LicenseChecker

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ...
        // Construct the LicenseCheckerCallback. The library calls this when done.
        licenseCheckerCallback = MyLicenseCheckerCallback()

        // Construct the LicenseChecker with a Policy.
        checker = LicenseChecker(
                this,
                ServerManagedPolicy(this, AESObfuscator(SALT, packageName, deviceId)),
                BASE64_PUBLIC_KEY // Your public licensing key.
        )
        ...
    }
}

জাভা

public class MainActivity extends Activity {
    ...
    private LicenseCheckerCallback licenseCheckerCallback;
    private LicenseChecker checker;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ...
        // Construct the LicenseCheckerCallback. The library calls this when done.
        licenseCheckerCallback = new MyLicenseCheckerCallback();

        // Construct the LicenseChecker with a Policy.
        checker = new LicenseChecker(
            this, new ServerManagedPolicy(this,
                new AESObfuscator(SALT, getPackageName(), deviceId)),
            BASE64_PUBLIC_KEY // Your public licensing key.
            );
        ...
    }
}

মনে রাখবেন যে, LicenseChecker, UI থ্রেড থেকে LicenseCheckerCallback মেথডকে কল করে, শুধুমাত্র যদি স্থানীয়ভাবে ক্যাশে করা বৈধ লাইসেন্স রেসপন্স থাকে। লাইসেন্স চেক সার্ভারে পাঠানো হলে, কলব্যাক সবসময় ব্যাকগ্রাউন্ড থ্রেড থেকে শুরু হয়, এমনকি নেটওয়ার্কের সমস্যা হলেও।

লাইসেন্স চেক শুরু করতে checkAccess() কল করুন

আপনার প্রধান অ্যাক্টিভিটিতে, LicenseChecker ইনস্ট্যান্সের checkAccess() পদ্ধতিতে একটি কল যোগ করুন। কলে, আপনার LicenseCheckerCallback ইনস্ট্যান্সের রেফারেন্স প্যারামিটার হিসেবে পাস করুন। কল করার আগে আপনাকে যদি কোনও বিশেষ UI এফেক্ট বা স্টেট ম্যানেজমেন্ট সামলাতে হয়, তাহলে র‍্যাপার পদ্ধতি থেকে checkAccess() কল করা আপনার পক্ষে উপযোগী হতে পারে। যেমন, LVL স্যাম্পেল অ্যাপ্লিকেশন doCheck() র‍্যাপার পদ্ধতি থেকে checkAccess() কল করে:

Kotlin

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ...
        // Call a wrapper method that initiates the license check
        doCheck()
        ...
    }
    ...
    private fun doCheck() {
        checkLicenseButton.isEnabled = false
        setProgressBarIndeterminateVisibility(true)
        statusText.setText(R.string.checking_license)
        checker.checkAccess(licenseCheckerCallback)
    }

জাভা

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ...
        // Call a wrapper method that initiates the license check
        doCheck();
        ...
    }
    ...
    private void doCheck() {
        checkLicenseButton.setEnabled(false);
        setProgressBarIndeterminateVisibility(true);
        statusText.setText(R.string.checking_license);
        checker.checkAccess(licenseCheckerCallback);
    }

লাইসেন্সিংয়ের জন্য আপনার পাবলিক কী এম্বেড করুন

প্রতিটি অ্যাপ্লিকেশনের জন্য, Google Play পরিষেবা অটোমেটিক একটি ২০৪৮-বিট RSA পাবলিক/প্রাইভেট কী পেয়ার জেনারেট করে যা লাইসেন্সিং এবং অ্যাপ-মধ্যস্থ বিলিংয়ের জন্য ব্যবহার করা হয়। কী পেয়ারটি অনন্যভাবে অ্যাপ্লিকেশনের সাথে যুক্ত। অ্যাপ্লিকেশনের সাথে যুক্ত হলেও, কী পেয়ারটি একই নয়, যেমনটি আপনি আপনার অ্যাপ্লিকেশন সাইন করার জন্য ব্যবহার করেন (বা এটি থেকে প্রাপ্ত)।

Google Play Console-এ সাইন-ইন করা যেকোনও ডেভেলপারকে লাইসেন্স দেওয়ার জন্য Google Play Console সর্বজনীন কী প্রকাশ করে, তবে এটি একটি সুরক্ষিত লোকেশনে সব ব্যবহারকারীর থেকে ব্যক্তিগত কী লুকিয়ে রাখে। আপনার অ্যাকাউন্টে প্রকাশিত কোনও অ্যাপ্লিকেশনের জন্য কোনও অ্যাপ্লিকেশন লাইসেন্স চেক করার অনুরোধ করলে, লাইসেন্সিং সার্ভার আপনার অ্যাপ্লিকেশনের কী পেয়ারের ব্যক্তিগত কী ব্যবহার করে লাইসেন্স সংক্রান্ত উত্তরে স্বাক্ষর করে। LVL উত্তর পেলে, লাইসেন্স উত্তরের স্বাক্ষর যাচাই করার জন্য এটি অ্যাপ্লিকেশনের মাধ্যমে প্রদান করা পাবলিক কী ব্যবহার করে।

কোনও অ্যাপ্লিকেশনে লাইসেন্সিং যোগ করতে, আপনাকে লাইসেন্সিংয়ের জন্য আপনার অ্যাপ্লিকেশনের সর্বজনীন কী পেতে হবে এবং এটি আপনার অ্যাপ্লিকেশনে কপি করতে হবে। লাইসেন্সিংয়ের জন্য আপনার অ্যাপ্লিকেশনের সর্বজনীন কী কীভাবে খুঁজে পাবেন তা এখানে দেওয়া হল:

  1. Google Play Console-এ গিয়ে সাইন-ইন করুন। আপনি যে অ্যাকাউন্ট থেকে লাইসেন্সিং অ্যাপ্লিকেশন প্রকাশ করেছেন (বা করবেন) সেই অ্যাকাউন্টে সাইন-ইন করেছেন কিনা তা নিশ্চিত করুন।
  2. অ্যাপ্লিকেশনের বিবরণ পৃষ্ঠায়, পরিষেবা ও API লিঙ্কটি খুঁজে বের করে সেটিতে ক্লিক করুন।
  3. পরিষেবা ও API পৃষ্ঠায়, লাইসেন্সিং ও ইন-অ্যাপ বিলিং বিভাগটি খুঁজে নিন। লাইসেন্সিংয়ের জন্য আপনার পাবলিক কী এই অ্যাপ্লিকেশনের জন্য আপনার লাইসেন্স কী ফিল্ডে দেওয়া আছে।

আপনার অ্যাপ্লিকেশনে সর্বজনীন কী যোগ করতে, ফিল্ড থেকে কী স্ট্রিং কপি করে আপনার অ্যাপ্লিকেশনে স্ট্রিং ভেরিয়েবল BASE64_PUBLIC_KEY-এর ভ্যালু হিসেবে পেস্ট করুন। কপি করার সময়, কোনও অক্ষর বাদ না দিয়ে সম্পূর্ণ কী স্ট্রিং বেছে নিয়েছেন কিনা তা ভাল করে দেখে নিন।

LVL স্যাম্পেল অ্যাপ্লিকেশন থেকে একটি উদাহরণ এখানে দেওয়া হল:

Kotlin

private const val BASE64_PUBLIC_KEY = "MIIBIjANBgkqhkiG ... " //truncated for this example
class LicensingActivity : AppCompatActivity() {
    ...
}

জাভা

public class MainActivity extends Activity {
    private static final String BASE64_PUBLIC_KEY = "MIIBIjANBgkqhkiG ... "; //truncated for this example
    ...
}

IPC কানেকশন বন্ধ করতে আপনার LicenseChecker-এর onDestroy() মেথড কল করুন

শেষে, আপনার অ্যাপ্লিকেশন Context পরিবর্তন করার আগে LVL-কে ক্লিন-আপ করার অনুমতি দিতে, আপনার অ্যাক্টিভিটির onDestroy() ইমপ্লিমেন্টেশন থেকে LicenseChecker-এর onDestroy() পদ্ধতিতে একটি কল যোগ করুন। কলের ফলে LicenseChecker Google Play অ্যাপ্লিকেশনের ILicensingService-এ খোলা যেকোনও IPC কানেকশন সঠিকভাবে বন্ধ করে দেয় এবং পরিষেবা ও হ্যান্ডলারের যেকোনও লোকাল রেফারেন্স সরিয়ে দেয়।

LicenseChecker-এর onDestroy() পদ্ধতি কল করতে না পারলে আপনার অ্যাপ্লিকেশনের লাইফসাইকেলে সমস্যা হতে পারে। যেমন, লাইসেন্স চেক করার সময় ব্যবহারকারী স্ক্রিন ওরিয়েন্টেশন পরিবর্তন করলে, অ্যাপ্লিকেশন Context নষ্ট হয়ে যায়। আপনার অ্যাপ্লিকেশন যদি LicenseChecker-এর IPC কানেকশন সঠিকভাবে বন্ধ না করে, তাহলে উত্তর পাওয়ার সময় আপনার অ্যাপ্লিকেশন ক্র্যাশ করবে। একইভাবে, লাইসেন্স চেক করার সময় ব্যবহারকারী আপনার অ্যাপ্লিকেশন থেকে বেরিয়ে গেলে, পরিষেবা থেকে ডিসকানেক্ট করার জন্য LicenseChecker-এর onDestroy() পদ্ধতি সঠিকভাবে কল না করা হলে, উত্তর পাওয়ার সময় আপনার অ্যাপ্লিকেশন ক্র্যাশ করবে।

LVL-এ অন্তর্ভুক্ত স্যাম্পেল অ্যাপ্লিকেশন থেকে একটি উদাহরণ এখানে দেওয়া হল, যেখানে mChecker হল LicenseChecker ইনস্ট্যান্স:

Kotlin

    override fun onDestroy() {
        super.onDestroy()
        checker.onDestroy()
        ...
    }

জাভা

    @Override
    protected void onDestroy() {
        super.onDestroy();
        checker.onDestroy();
        ...
    }

আপনি LicenseChecker এক্সটেন্ড বা পরিবর্তন করলে, আপনাকে হয়ত LicenseChecker-এর finishCheck() পদ্ধতি কল করতে হবে, যাতে খোলা থাকা যেকোনও IPC কানেকশন ক্লিন-আপ করা যায়।

DeviceLimiter প্রয়োগ করা

কিছু ক্ষেত্রে, আপনি হয়ত চাইবেন যে আপনার Policy যেন একটি লাইসেন্স ব্যবহার করার অনুমতিপ্রাপ্ত আসল ডিভাইসের সংখ্যা সীমিত করে। এটি কোনও ব্যবহারকারীকে একাধিক ডিভাইসে লাইসেন্সপ্রাপ্ত অ্যাপ্লিকেশন সরানো এবং একই অ্যাকাউন্ট আইডির অধীনে সেইসব ডিভাইসে অ্যাপ্লিকেশন ব্যবহার করা থেকে আটকাবে। এছাড়াও, এটি কোনও ব্যবহারকারীকে লাইসেন্সের সাথে যুক্ত অ্যাকাউন্টের তথ্য অন্য ব্যক্তিদের প্রদান করে অ্যাপ্লিকেশন "শেয়ার" করতে বাধা দেবে, যারা তখন তাদের ডিভাইসে সেই অ্যাকাউন্টে সাইন-ইন করতে এবং অ্যাপ্লিকেশনের লাইসেন্স অ্যাক্সেস করতে পারে।

LVL, DeviceLimiter ইন্টারফেস প্রদান করার মাধ্যমে প্রতিটি ডিভাইসের জন্য লাইসেন্সিংয়ের সুবিধা দেয়, যা একটি পদ্ধতি ঘোষণা করে, allowDeviceAccess()। যখন কোনও LicenseValidator লাইসেন্সিং সার্ভার থেকে কোনও উত্তর হ্যান্ডেল করে, তখন এটি allowDeviceAccess() কল করে, উত্তর থেকে এক্সট্র্যাক্ট করা ব্যবহারকারীর আইডি স্ট্রিং পাস করে।

আপনি ডিভাইসের সীমাবদ্ধতা সমর্থন করতে না চাইলে, কোনও কাজ করার প্রয়োজন নেই — LicenseChecker ক্লাস অটোমেটিক NullDeviceLimiter নামক ডিফল্ট ইমপ্লিমেন্টেশন ব্যবহার করে। নাম থেকে বোঝা যায়, NullDeviceLimiter হল "no-op" ক্লাস যার allowDeviceAccess() পদ্ধতি সব ব্যবহারকারী ও ডিভাইসের জন্য LICENSED উত্তর দেয়।

সতর্কতা: ডিভাইস প্রতি লাইসেন্সিং বেশিরভাগ অ্যাপ্লিকেশনের জন্য সাজেস্ট করা হয় না কারণ:

  • ব্যবহারকারী ও ডিভাইস ম্যাপিং ম্যানেজ করার জন্য আপনাকে ব্যাকএন্ড সার্ভার প্রদান করতে হবে এবং
  • এর ফলে, কোনও ব্যবহারকারী অন্য ডিভাইসে বৈধভাবে কেনা কোনও অ্যাপ্লিকেশন অ্যাক্সেস করতে অনিচ্ছাকৃতভাবে বাধা পেতে পারেন।

আপনার কোড অস্পষ্ট করা হচ্ছে

আপনার অ্যাপ্লিকেশনের নিরাপত্তা নিশ্চিত করতে, বিশেষ করে লাইসেন্সিং এবং/অথবা কাস্টম সীমাবদ্ধতা এবং সুরক্ষা ব্যবহার করে এমন একটি পেড অ্যাপ্লিকেশনের জন্য, আপনার অ্যাপ্লিকেশন কোড অস্পষ্ট করা খুবই গুরুত্বপূর্ণ। আপনার কোড সঠিকভাবে অস্পষ্ট করলে, কোনও ক্ষতিকর ব্যবহারকারীর পক্ষে অ্যাপ্লিকেশনের বাইটকোড ডিকম্পাইল করা, এটি পরিবর্তন করা — যেমন লাইসেন্স চেক সরিয়ে দেওয়া — এবং তারপরে এটি রিকম্পাইল করা আরও কঠিন হয়ে যায়।

Android অ্যাপ্লিকেশনের জন্য বেশ কিছু অবফাসকেটর প্রোগ্রাম উপলভ্য, যার মধ্যে ProGuard-ও রয়েছে, যা কোড-অপ্টিমাইজেশন ফিচারও অফার করে। Google Play লাইসেন্সিং ব্যবহার করে এমন সব অ্যাপ্লিকেশনের জন্য আপনার কোড অস্পষ্ট করতে ProGuard বা একই ধরনের প্রোগ্রাম ব্যবহার করার জন্য জোরালোভাবে সাজেস্ট করা হয়।

লাইসেন্সপ্রাপ্ত অ্যাপ্লিকেশন প্রকাশ করা

আপনার লাইসেন্স প্রয়োগ করার পরীক্ষা শেষ হলে, আপনি Google Play-তে অ্যাপ্লিকেশন প্রকাশ করার জন্য প্রস্তুত। প্রস্তুত করা, স্বাক্ষর করা এবং তারপর অ্যাপ্লিকেশন প্রকাশ করার জন্য সাধারণ ধাপগুলি অনুসরণ করুন।

কোথায় সহায়তা পাওয়া যাবে

আপনার অ্যাপ্লিকেশনে প্রকাশনা প্রয়োগ বা স্থাপন করার সময় আপনার যদি প্রশ্ন থাকে বা সমস্যার সম্মুখীন হন, তাহলে নিচের সারণীতে তালিকাভুক্ত সহায়তা সংস্থানগুলি ব্যবহার করুন। সঠিক ফোরামে আপনার কোয়েরি পাঠিয়ে, আপনি আরও দ্রুত প্রয়োজনীয় সহায়তা পেতে পারেন।

টেবিল ২. Google Play লাইসেন্সিং পরিষেবার জন্য ডেভেলপার সহায়তা রিসোর্স।

সহায়তার ধরন রিসোর্স বিভিন্ন ধরনের বিষয়
ডেভেলপমেন্ট ও টেস্টিং সংক্রান্ত সমস্যা Google Groups: android-developers LVL ডাউনলোড ও ইন্টিগ্রেশন, লাইব্রেরি প্রোজেক্ট, Policy প্রশ্ন, ব্যবহারকারীর অভিজ্ঞতা সংক্রান্ত আইডিয়া, উত্তর ম্যানেজ করা, Obfuscator, IPC, টেস্ট এনভায়রনমেন্ট সেট-আপ
Stack Overflow: http://stackoverflow.com/questions/tagged/android
অ্যাকাউন্ট, প্রকাশনা এবং ডিপ্লয়মেন্ট সংক্রান্ত সমস্যা Google Play সহায়তা ফোরাম প্রকাশক অ্যাকাউন্ট, লাইসেন্সিং কী পেয়ার, টেস্ট অ্যাকাউন্ট, সার্ভার উত্তর, টেস্ট উত্তর, অ্যাপ্লিকেশন ডিপ্লয়মেন্ট ও ফলাফল
Market লাইসেন্সিং সহায়তা সংক্রান্ত প্রায়শই জিজ্ঞাসিত প্রশ্ন
LVL ইস্যু ট্র্যাকার Marketlicensing প্রজেক্টের সমস্যা ট্র্যাকার LVL সোর্স কোড ক্লাস এবং ইন্টারফেস ইমপ্লিমেন্টেশন সম্পর্কিত বাগ ও সমস্যার রিপোর্ট

উপরে তালিকাভুক্ত গ্রুপে কীভাবে পোস্ট করতে হয় সেই সম্পর্কে সাধারণ তথ্যের জন্য, ডেভেলপার সহায়তা রিসোর্স পৃষ্ঠায় কমিউনিটি রিসোর্স বিভাগ দেখুন।

অতিরিক্ত রিসোর্স

LVL-এর সাথে অন্তর্ভুক্ত স্যাম্পেল অ্যাপ্লিকেশনটি কীভাবে লাইসেন্স চেক শুরু করতে হয় এবং ফলাফল ম্যানেজ করতে হয় তার একটি সম্পূর্ণ উদাহরণ প্রদান করে, MainActivity ক্লাসে।