SDK রানটাইম বিকাশকারীর নির্দেশিকা, SDK রানটাইম বিকাশকারীর নির্দেশিকা

আপনি Android ডকুমেন্টেশনের গোপনীয়তা স্যান্ডবক্সের মাধ্যমে পড়ার সময়, আপনি যে প্রোগ্রামটির সাথে কাজ করছেন সেটি নির্বাচন করতে বিকাশকারী পূর্বরূপ বা বিটা বোতামটি ব্যবহার করুন, কারণ নির্দেশাবলী পরিবর্তিত হতে পারে।


মতামত প্রদান

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

এই পৃষ্ঠার পদক্ষেপগুলি আপনাকে একটি রানটাইম-সক্ষম SDK তৈরির প্রক্রিয়ার মাধ্যমে গাইড করে যা একটি ওয়েব-ভিত্তিক দৃশ্যকে সংজ্ঞায়িত করে যা দূরবর্তীভাবে একটি কলিং অ্যাপে রেন্ডার করা যেতে পারে।

পরিচিত সীমাবদ্ধতা

SDK রানটাইমের জন্য চলমান ক্ষমতার তালিকার জন্য, রিলিজ নোটগুলি দেখুন।

পরবর্তী প্রধান অ্যান্ড্রয়েড প্ল্যাটফর্ম রিলিজে নিম্নলিখিত সীমাবদ্ধতাগুলি সংশোধন করা হবে বলে আশা করা হচ্ছে।

  • একটি স্ক্রোলযোগ্য দৃশ্যের মধ্যে বিজ্ঞাপন রেন্ডারিং। উদাহরণস্বরূপ, RecyclerView সঠিকভাবে কাজ করে না।
    • আপনি আকার পরিবর্তন করার সময় জ্যাঙ্ক অনুভব করতে পারেন।
    • ব্যবহারকারীর স্পর্শ স্ক্রোল ইভেন্ট সঠিকভাবে রানটাইম পাস করা হয় না.
  • স্টোরেজ API

নিম্নলিখিত সমস্যাটি 2023 সালে ঠিক করা হবে:

  • getAdId এবং getAppSetId APIগুলি এখনও সঠিকভাবে কাজ করে না কারণ এইগুলির জন্য সমর্থন এখনও সক্রিয় করা হয়নি৷

আপনি শুরু করার আগে

শুরু করার আগে, নিম্নলিখিত পদক্ষেপগুলি সম্পূর্ণ করুন:

  1. অ্যান্ড্রয়েডে গোপনীয়তা স্যান্ডবক্সের জন্য আপনার বিকাশের পরিবেশ সেট আপ করুন ৷ SDK রানটাইম সমর্থন করার জন্য টুলিং সক্রিয় বিকাশের অধীনে রয়েছে, তাই এই নির্দেশিকাটির জন্য আপনাকে Android স্টুডিওর সর্বশেষ ক্যানারি সংস্করণ ব্যবহার করতে হবে। আপনি অ্যান্ড্রয়েড স্টুডিওর এই সংস্করণটি আপনার ব্যবহার করা অন্যান্য সংস্করণের সমান্তরালে চালাতে পারেন, তাই এই প্রয়োজনীয়তা আপনার জন্য কাজ না করলে অনুগ্রহ করে আমাদের জানান

  2. হয় একটি সমর্থিত ডিভাইসে একটি সিস্টেম ইমেজ ইনস্টল করুন বা Android-এ গোপনীয়তা স্যান্ডবক্সের জন্য সমর্থন অন্তর্ভুক্ত করে এমন একটি এমুলেটর সেট আপ করুন

অ্যান্ড্রয়েড স্টুডিওতে আপনার প্রকল্প সেট আপ করুন

SDK রানটাইম ব্যবহার করে দেখতে, একটি মডেল ব্যবহার করুন যা ক্লায়েন্ট-সার্ভার মডেলের অনুরূপ। প্রধান পার্থক্য হল অ্যাপ (ক্লায়েন্ট) এবং SDKs ("সার্ভার") একই ডিভাইসে চলে।

  1. আপনার প্রকল্পে একটি অ্যাপ মডিউল যোগ করুন। এই মডিউলটি ক্লায়েন্ট হিসাবে কাজ করে যা SDK চালায়।
  2. আপনার অ্যাপ মডিউলে, SDK রানটাইম সক্ষম করুন , প্রয়োজনীয় অনুমতিগুলি ঘোষণা করুন এবং API-নির্দিষ্ট বিজ্ঞাপন পরিষেবাগুলি কনফিগার করুন
  3. আপনার প্রকল্পে একটি লাইব্রেরি মডিউল যোগ করুন। এই মডিউলটিতে আপনার SDK কোড রয়েছে।
  4. আপনার SDK মডিউলে, প্রয়োজনীয় অনুমতিগুলি ঘোষণা করুন৷ এই মডিউলে আপনাকে API-নির্দিষ্ট বিজ্ঞাপন পরিষেবাগুলি কনফিগার করার দরকার নেই৷
  5. আপনার লাইব্রেরি মডিউলের build.gradle ফাইলের dependencies সরান যা আপনার SDK ব্যবহার করে না৷ বেশিরভাগ ক্ষেত্রে, আপনি সমস্ত নির্ভরতা মুছে ফেলতে পারেন। আপনি একটি নতুন ডিরেক্টরি তৈরি করে এটি করতে পারেন যার নাম আপনার SDK-এর সাথে মিলে যায়৷
  6. com.android.privacy-sandbox-sdk টাইপ ব্যবহার করে ম্যানুয়ালি একটি নতুন মডিউল তৈরি করুন। আপনার ডিভাইসে স্থাপন করা যেতে পারে এমন একটি APK তৈরি করতে এটি SDK কোডের সাথে একত্রিত করা হয়েছে। আপনি একটি নতুন ডিরেক্টরি তৈরি করে এটি করতে পারেন যার নাম আপনার SDK-এর সাথে মিলে যায়৷ একটি খালি build.gradle ফাইল যোগ করুন। এই ফাইলের বিষয়বস্তু এই গাইডে পরে পপুলেট করা হবে।

  7. আপনার gradle.properties ফাইলে নিম্নলিখিত স্নিপেট যোগ করুন:

    android.experimental.privacysandboxsdk.enable=true
    
  8. Tiramisu (এক্সটেনশন লেভেল 4) এমুলেটর ইমেজটি ডাউনলোড করুন এবং এই ইমেজটি দিয়ে একটি এমুলেটর তৈরি করুন যাতে প্লে স্টোর অন্তর্ভুক্ত থাকে।

আপনি একজন SDK ডেভেলপার বা অ্যাপ ডেভেলপার কিনা তার উপর নির্ভর করে, আপনার কাছে পূর্ববর্তী অনুচ্ছেদে বর্ণিত একটির থেকে আলাদা চূড়ান্ত সেটআপ থাকতে পারে।

Android স্টুডিও বা অ্যান্ড্রয়েড ডিবাগ ব্রিজ (ADB) ব্যবহার করে আপনি যেভাবে একটি অ্যাপ ইনস্টল করবেন একইভাবে একটি টেস্ট ডিভাইসে SDK ইনস্টল করুন।আপনাকে শুরু করতে সাহায্য করার জন্য, আমরা কোটলিন এবং জাভা প্রোগ্রামিং ভাষায় নমুনা অ্যাপ তৈরি করেছি, যা এই GitHub সংগ্রহস্থলে পাওয়া যাবে। README এবং ম্যানিফেস্ট ফাইলগুলিতে মন্তব্য রয়েছে যা বর্ণনা করে যে Android স্টুডিওর স্থিতিশীল সংস্করণে নমুনা চালানোর জন্য কী পরিবর্তন করতে হবে৷

আপনার SDK প্রস্তুত করুন

  1. ম্যানুয়ালি একটি মডিউল-স্তরের ডিরেক্টরি তৈরি করুন। এটি SDK APK তৈরি করতে আপনার বাস্তবায়ন কোডের চারপাশে মোড়ক হিসাবে কাজ করে। নতুন ডিরেক্টরিতে, একটি build.gradle ফাইল যোগ করুন এবং নিম্নলিখিত স্নিপেট দিয়ে এটি পূরণ করুন। আপনার রানটাইম-সক্ষম SDK (RE-SDK) এর জন্য একটি অনন্য নাম ব্যবহার করুন এবং একটি সংস্করণ প্রদান করুন৷ dependencies বিভাগে আপনার লাইব্রেরি মডিউল অন্তর্ভুক্ত করুন।

    plugins {
        id 'com.android.privacy-sandbox-sdk'
    }
    
    android {
        compileSdk 33
        compileSdkExtension 4
        minSdk 33
        targetSdk 33
        namespace = "com.example.example-sdk"
    
        bundle {
            packageName = "com.example.privacysandbox.provider"
            sdkProviderClassName = "com.example.sdk_implementation.SdkProviderImpl"
            setVersion(1, 0, 0)
        }
    }
    
    dependencies {
        include project(':<your-library-here>')
    }
    
  2. আপনার SDK-এর জন্য একটি এন্ট্রি পয়েন্ট হিসাবে পরিবেশন করতে আপনার বাস্তবায়ন লাইব্রেরিতে একটি ক্লাস তৈরি করুন। ক্লাসের নাম sdkProviderClassName এর মানের সাথে মানচিত্র করা উচিত এবং SandboxedSdkProvider প্রসারিত করা উচিত।

আপনার SDK-এর প্রবেশ বিন্দু SandboxedSdkProvider প্রসারিত করে। SandboxedSdkProvider আপনার SDK-এর জন্য একটি Context বস্তু রয়েছে, যা আপনি getContext() কল করে অ্যাক্সেস করতে পারেন। onLoadSdk() চালু করা হলেই এই প্রসঙ্গটি অ্যাক্সেস করতে হবে।

আপনার SDK অ্যাপটি কম্পাইল করার জন্য, আপনাকে SDK লাইফসাইকেল পরিচালনা করার পদ্ধতিগুলি ওভাররাইড করতে হবে:

onLoadSdk()

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

একটি উদাহরণ হিসাবে AIDL ব্যবহার করে, আপনার IBinder উপস্থাপন করার জন্য একটি AIDL ফাইল সংজ্ঞায়িত করা উচিত যা অ্যাপ দ্বারা ভাগ করা এবং ব্যবহার করা হবে:

// ISdkInterface.aidl
interface ISdkInterface {
    // the public functions to share with the App.
    int doSomething();
}
getView()

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

নিম্নলিখিত কোড স্নিপেট এই পদ্ধতিগুলিকে কীভাবে ওভাররাইড করতে হয় তা প্রদর্শন করে:

কোটলিন

class SdkProviderImpl : SandboxedSdkProvider() {
    override fun onLoadSdk(params: Bundle?): SandboxedSdk {
        // Returns a SandboxedSdk, passed back to the client. The IBinder used
        // to create the SandboxedSdk object is used by the app to call into the
        // SDK.
        return SandboxedSdk(SdkInterfaceProxy())
    }

    override fun getView(windowContext: Context, bundle: Bundle, width: Int,
            height: Int): View {
        val webView = WebView(windowContext)
        val layoutParams = LinearLayout.LayoutParams(width, height)
        webView.setLayoutParams(layoutParams)
        webView.loadUrl("https://developer.android.com/privacy-sandbox")
        return webView
    }

    private class SdkInterfaceProxy : ISdkInterface.Stub() {
        fun doSomething() {
            // Implementation of the API.
        }
    }
}

জাভা

public class SdkProviderImpl extends SandboxedSdkProvider {
    @Override
    public SandboxedSdk onLoadSdk(Bundle params) {
        // Returns a SandboxedSdk, passed back to the client. The IBinder used
        // to create the SandboxedSdk object is used by the app to call into the
        // SDK.
        return new SandboxedSdk(new SdkInterfaceProxy());
    }

    @Override
    public View getView(Context windowContext, Bundle bundle, int width,
            int height) {
        WebView webView = new WebView(windowContext);
        LinearLayout.LayoutParams layoutParams =
                new LinearLayout.LayoutParams(width, height);
        webView.setLayoutParams(layoutParams);
        webView.loadUrl("https://developer.android.com/privacy-sandbox");
        return webView;
    }

    private static class SdkInterfaceProxy extends ISdkInterface.Stub {
        @Override
        public void doSomething() {
            // Implementation of the API.
        }
    }
}

SDK রানটাইমে ভিডিও প্লেয়ার পরীক্ষা করুন

ব্যানার বিজ্ঞাপনগুলিকে সমর্থন করার পাশাপাশি, গোপনীয়তা স্যান্ডবক্স SDK রানটাইমের ভিতরে চলমান ভিডিও প্লেয়ারকে সমর্থন করতে প্রতিশ্রুতিবদ্ধ৷

ভিডিও প্লেয়ার পরীক্ষা করার জন্য প্রবাহ ব্যানার বিজ্ঞাপন পরীক্ষার অনুরূপ। প্রত্যাবর্তিত View অবজেক্টে একটি ভিডিও প্লেয়ার অন্তর্ভুক্ত করতে আপনার SDK-এর এন্ট্রি পয়েন্টের getView() পদ্ধতিটি পরিবর্তন করুন৷ আপনি গোপনীয়তা স্যান্ডবক্স দ্বারা সমর্থিত হবে এমন সমস্ত ভিডিও প্লেয়ার ফ্লো পরীক্ষা করুন৷ মনে রাখবেন যে ভিডিওর জীবনচক্র সম্পর্কে SDK এবং ক্লায়েন্ট অ্যাপের মধ্যে যোগাযোগ সুযোগের বাইরে, তাই এই কার্যকারিতার জন্য প্রতিক্রিয়ার এখনও প্রয়োজন নেই৷

আপনার পরীক্ষা এবং প্রতিক্রিয়া নিশ্চিত করবে যে SDK রানটাইম আপনার পছন্দের ভিডিও প্লেয়ারের সমস্ত ব্যবহারের ক্ষেত্রে সমর্থন করে৷

নিচের কোড স্নিপেটটি দেখায় কিভাবে একটি ইউআরএল থেকে লোড হওয়া একটি সাধারণ ভিডিও ভিউ ফেরত দেওয়া যায়।

কোটলিন

    class SdkProviderImpl : SandboxedSdkProvider() {

        override fun getView(windowContext: Context, bundle: Bundle, width: Int,
                height: Int): View {
            val videoView = VideoView(windowContext)
            val layoutParams = LinearLayout.LayoutParams(width, height)
            videoView.setLayoutParams(layoutParams)
            videoView.setVideoURI(Uri.parse("https://test.website/video.mp4"))
            videoView.setOnPreparedListener { mp -> mp.start() }
            return videoView
        }
    }

জাভা

    public class SdkProviderImpl extends SandboxedSdkProvider {

        @Override
        public View getView(Context windowContext, Bundle bundle, int width,
                int height) {
            VideoView videoView = new VideoView(windowContext);
            LinearLayout.LayoutParams layoutParams =
                    new LinearLayout.LayoutParams(width, height);
            videoView.setLayoutParams(layoutParams);
            videoView.setVideoURI(Uri.parse("https://test.website/video.mp4"));
            videoView.setOnPreparedListener(mp -> {
                mp.start();
            });
            return videoView;
        }
    }

আপনার SDK-এ স্টোরেজ API ব্যবহার করা

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

SDKs SandboxedSdkProvider#getContext() দ্বারা প্রত্যাবর্তিত Context অবজেক্টে ফাইল স্টোরেজ API ব্যবহার করে এই পৃথক অভ্যন্তরীণ স্টোরেজ অ্যাক্সেস করতে সক্ষম হবে। SDK শুধুমাত্র অভ্যন্তরীণ স্টোরেজ ব্যবহার করতে পারে, তাই শুধুমাত্র অভ্যন্তরীণ স্টোরেজ API, যেমন Context.getFilesDir() বা Context.getCacheDir() কাজ করবে। অভ্যন্তরীণ স্টোরেজ থেকে অ্যাক্সেসে আরও উদাহরণ দেখুন।

SDK রানটাইম থেকে বাহ্যিক সঞ্চয়স্থানে অ্যাক্সেস সমর্থিত নয়। বাহ্যিক সঞ্চয়স্থান অ্যাক্সেস করার জন্য API-কে কল করা হয় একটি ব্যতিক্রম ছুঁড়ে দেবে বা null দেবে। বেশ কয়েকটি উদাহরণ:

Android 13-এ, SDK রানটাইমের সমস্ত SDKগুলি SDK রানটাইমের জন্য বরাদ্দ করা অভ্যন্তরীণ স্টোরেজ ভাগ করবে৷ ক্লায়েন্ট অ্যাপ আনইনস্টল না হওয়া পর্যন্ত বা ক্লায়েন্ট অ্যাপের ডেটা পরিষ্কার না হওয়া পর্যন্ত স্টোরেজ বজায় থাকবে।

স্টোরেজের জন্য আপনাকে অবশ্যই SandboxedSdkProvider.getContext() দ্বারা প্রত্যাবর্তিত Context ব্যবহার করতে হবে। অন্য কোনো Context অবজেক্ট ইনস্ট্যান্সে ফাইল স্টোরেজ API ব্যবহার করা, যেমন অ্যাপ্লিকেশন প্রসঙ্গ, সমস্ত পরিস্থিতিতে বা ভবিষ্যতে প্রত্যাশিতভাবে কাজ করার গ্যারান্টি দেওয়া হয় না।

নিম্নলিখিত কোড স্নিপেট দেখায় কিভাবে SDK রানটাইমে স্টোরেজ ব্যবহার করতে হয়:

কোটলিন

    private static class SdkInterfaceStorage extends ISdkInterface.Stub {
    override fun doSomething() {
        val filename = "myfile"
        val fileContents = "content"
        try {
            getContext().openFileOutput(filename, Context.MODE_PRIVATE).use {
                it.write(fileContents.toByteArray())
            } catch (e: Exception) {
                throw RuntimeException(e)
            }
        }
    }
}

    

জাভা

    private static class SdkInterfaceStorage extends ISdkInterface.Stub {
    @Override
    public void doSomething() {
        final filename = "myFile";
        final String fileContents = "content";
        try (FileOutputStream fos = getContext().openFileOutput(filename, Context.MODE_PRIVATE)) {
            fos.write(fileContents.toByteArray());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}

    

প্রতি-SDK সঞ্চয়স্থান

প্রতিটি SDK রানটাইমের জন্য পৃথক অভ্যন্তরীণ স্টোরেজের মধ্যে, প্রতিটি SDK-এর নিজস্ব স্টোরেজ ডিরেক্টরি রয়েছে৷ প্রতি-SDK স্টোরেজ হল SDK রানটাইমের অভ্যন্তরীণ সঞ্চয়স্থানের একটি যৌক্তিক বিভাজন যা প্রতিটি SDK কতটা স্টোরেজ ব্যবহার করে তা হিসাব করতে সাহায্য করে।

অ্যান্ড্রয়েড 13-এ, শুধুমাত্র একটি এপিআই প্রতি-SDK সঞ্চয়স্থানে একটি পথ ফেরত দেয়: Context#getDataDir()

Android 14-এ, Context অবজেক্টের সমস্ত অভ্যন্তরীণ স্টোরেজ API প্রতিটি SDK-এর জন্য একটি স্টোরেজ পাথ ফেরত দেয়। আপনাকে নিম্নলিখিত adb কমান্ডটি চালিয়ে এই বৈশিষ্ট্যটি সক্ষম করতে হতে পারে:

adb shell device_config put adservices sdksandbox_customized_sdk_context_enabled true

Google Play পরিষেবাগুলির দ্বারা প্রদত্ত বিজ্ঞাপন আইডি অ্যাক্সেস করুন৷

যদি আপনার SDK-এর Google Play পরিষেবার দ্বারা প্রদত্ত বিজ্ঞাপন আইডিতে অ্যাক্সেসের প্রয়োজন হয়:

  • SDK-এর ম্যানিফেস্টে android.permission.ACCESS_ADSERVICES_AD_ID অনুমতি ঘোষণা করুন।
  • অ্যাসিঙ্ক্রোনাস মান পুনরুদ্ধার করতে AdIdManager#getAdId() ব্যবহার করুন।

Google Play পরিষেবাগুলির দ্বারা প্রদত্ত অ্যাপ সেট আইডি অ্যাক্সেস করুন৷

যদি আপনার SDK-এর Google Play পরিষেবা দ্বারা প্রদত্ত অ্যাপ সেট আইডিতে অ্যাক্সেসের প্রয়োজন হয়:

  • অ্যাসিঙ্ক্রোনাসভাবে মান পুনরুদ্ধার করতে AppSetIdManager#getAppSetId() ব্যবহার করুন।

ক্লায়েন্ট অ্যাপ আপডেট করুন

SDK রানটাইমে চলমান একটি SDK-এ কল করতে, কলিং ক্লায়েন্ট অ্যাপে নিম্নলিখিত পরিবর্তনগুলি করুন:

  1. আপনার অ্যাপের ম্যানিফেস্টে INTERNET এবং ACCESS_NETWORK_STATE অনুমতি যোগ করুন:

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    
  2. আপনার অ্যাপের কার্যকলাপে যেটিতে একটি বিজ্ঞাপন রয়েছে, SdkSandboxManager এর একটি রেফারেন্স ঘোষণা করুন, SDK লোড হয়েছে কিনা তা জানার জন্য একটি বুলিয়ান এবং দূরবর্তী রেন্ডারিংয়ের জন্য একটি SurfaceView অবজেক্ট:

    কোটলিন

        private lateinit var mSdkSandboxManager: SdkSandboxManager
        private lateinit var mClientView: SurfaceView
        private var mSdkLoaded = false
    
        companion object {
            private const val SDK_NAME = "com.example.privacysandbox.provider"
        }
    

    জাভা

        private static final String SDK_NAME = "com.example.privacysandbox.provider";
    
        private SdkSandboxManager mSdkSandboxManager;
        private SurfaceView mClientView;
        private boolean mSdkLoaded = false;
    
  3. ডিভাইসে SDK রানটাইম প্রক্রিয়া উপলব্ধ কিনা তা পরীক্ষা করুন।

    1. SdkSandboxState ধ্রুবক পরীক্ষা করুন ( getSdkSandboxState() )। SDK_SANDBOX_STATE_ENABLED_PROCESS_ISOLATION মানে SDK রানটাইম উপলব্ধ৷

    2. loadSdk() কলিং সফল হয়েছে কিনা পরীক্ষা করুন। এটি সফল যদি কোন ব্যতিক্রম নিক্ষেপ করা না হয়, এবং রিসিভারটি SandboxedSdk এর উদাহরণ।

      • অগ্রভাগ থেকে loadSdk() কল করুন। যদি এটি ব্যাকগ্রাউন্ড থেকে কল করা হয় তবে একটি SecurityException নিক্ষেপ করা হবে।

      • একটি LoadSdkException নিক্ষেপ করা হয়েছে কিনা তা যাচাই করতে SandboxedSdk এর একটি উদাহরণের জন্য OutcomeReceiver চেক করুন। একটি ব্যতিক্রম নির্দেশ করে যে SDK রানটাইম উপলব্ধ নাও হতে পারে।

    যদি SdkSandboxState বা loadSdk কল ব্যর্থ হয়, তাহলে SDK রানটাইম উপলভ্য নয় এবং কলটি বিদ্যমান SDK-এ ফলব্যাক করা উচিত।

  4. লোড হওয়ার পর রানটাইমে SDK-এর সাথে ইন্টারঅ্যাক্ট করার জন্য OutcomeReceiver প্রয়োগ করে একটি কলব্যাক ক্লাস সংজ্ঞায়িত করুন। নিম্নলিখিত উদাহরণে, ক্লায়েন্ট SDK সফলভাবে লোড না হওয়া পর্যন্ত অপেক্ষা করার জন্য একটি কলব্যাক ব্যবহার করে, তারপর SDK থেকে একটি ওয়েব ভিউ রেন্ডার করার চেষ্টা করে৷ এই ধাপে কলব্যাকগুলি পরে সংজ্ঞায়িত করা হয়েছে।

    কোটলিন

        private inner class LoadSdkOutcomeReceiverImpl private constructor() :
                OutcomeReceiver {
    
          override fun onResult(sandboxedSdk: SandboxedSdk) {
              mSdkLoaded = true
    
              val binder: IBinder = sandboxedSdk.getInterface()
              if (!binderInterface.isPresent()) {
                  // SDK is not loaded anymore.
                  return
              }
              val sdkInterface: ISdkInterface = ISdkInterface.Stub.asInterface(binder)
              sdkInterface.doSomething()
    
              Handler(Looper.getMainLooper()).post {
                  val bundle = Bundle()
                  bundle.putInt(SdkSandboxManager.EXTRA_WIDTH_IN_PIXELS, mClientView.getWidth())
                  bundle.putInt(SdkSandboxManager.EXTRA_HEIGHT_IN_PIXELS, mClientView.getHeight())
                  bundle.putInt(SdkSandboxManager.EXTRA_DISPLAY_ID, display!!.displayId)
                  bundle.putInt(SdkSandboxManager.EXTRA_HOST_TOKEN, mClientView.getHostToken())
                  mSdkSandboxManager!!.requestSurfacePackage(
                          SDK_NAME, bundle, { obj: Runnable -> obj.run() },
                          RequestSurfacePackageOutcomeReceiverImpl())
              }
          }
    
          override fun onError(error: LoadSdkException) {
                  // Log or show error.
          }
        }
    

    জাভা

        import static android.app.sdksandbox.SdkSandboxManager.EXTRA_DISPLAY_ID;
        import static android.app.sdksandbox.SdkSandboxManager.EXTRA_HEIGHT_IN_PIXELS;
        import static android.app.sdksandbox.SdkSandboxManager.EXTRA_HOST_TOKEN;
        import static android.app.sdksandbox.SdkSandboxManager.EXTRA_WIDTH_IN_PIXELS;
    
        private class LoadSdkOutcomeReceiverImpl
                implements OutcomeReceiver {
            private LoadSdkOutcomeReceiverImpl() {}
    
            @Override
            public void onResult(@NonNull SandboxedSdk sandboxedSdk) {
                mSdkLoaded = true;
    
                IBinder binder = sandboxedSdk.getInterface();
                if (!binderInterface.isPresent()) {
                    // SDK is not loaded anymore.
                    return;
                }
                ISdkInterface sdkInterface = ISdkInterface.Stub.asInterface(binder);
                sdkInterface.doSomething();
    
                new Handler(Looper.getMainLooper()).post(() -> {
                    Bundle bundle = new Bundle();
                    bundle.putInt(EXTRA_WIDTH_IN_PIXELS, mClientView.getWidth());
                    bundle.putInt(EXTRA_HEIGHT_IN_PIXELS, mClientView.getHeight());
                    bundle.putInt(EXTRA_DISPLAY_ID, getDisplay().getDisplayId());
                    bundle.putInt(EXTRA_HOST_TOKEN, mClientView.getHostToken());
    
                    mSdkSandboxManager.requestSurfacePackage(
                            SDK_NAME, bundle, Runnable::run,
                            new RequestSurfacePackageOutcomeReceiverImpl());
                });
            }
    
            @Override
            public void onError(@NonNull LoadSdkException error) {
                // Log or show error.
            }
        }
    

    requestSurfacePackage() কল করার সময় রানটাইমে SDK থেকে রিমোট ভিউ ফিরে পেতে, OutcomeReceiver<Bundle, RequestSurfacePackageException> ইন্টারফেস প্রয়োগ করুন:

    কোটলিন

        private inner class RequestSurfacePackageOutcomeReceiverImpl :
                OutcomeReceiver {
            fun onResult(@NonNull result: Bundle) {
                Handler(Looper.getMainLooper())
                        .post {
                            val surfacePackage: SurfacePackage = result.getParcelable(
                                    EXTRA_SURFACE_PACKAGE,
                                    SurfacePackage::class.java)
                            mRenderedView.setChildSurfacePackage(surfacePackage)
                            mRenderedView.setVisibility(View.VISIBLE)
                        }
            }
    
            fun onError(@NonNull error: RequestSurfacePackageException?) {
                // Error handling
            }
        }
    

    জাভা

        import static android.app.sdksandbox.SdkSandboxManager.EXTRA_SURFACE_PACKAGE;
    
        private class RequestSurfacePackageOutcomeReceiverImpl
                implements OutcomeReceiver {
            @Override
            public void onResult(@NonNull Bundle result) {
                new Handler(Looper.getMainLooper())
                        .post(
                                () -> {
                                    SurfacePackage surfacePackage =
                                            result.getParcelable(
                                                    EXTRA_SURFACE_PACKAGE,
                                                    SurfacePackage.class);
                                    mRenderedView.setChildSurfacePackage(surfacePackage);
                                    mRenderedView.setVisibility(View.VISIBLE);
                                });
            }
            @Override
            public void onError(@NonNull RequestSurfacePackageException error) {
                // Error handling
            }
        }
    

    দৃশ্য দেখানো হয়ে গেলে, কল করে SurfacePackage প্রকাশ করতে মনে রাখবেন:

    surfacePackage.notifyDetachedFromWindow()
    
  5. onCreate() এ, SdkSandboxManager , প্রয়োজনীয় কলব্যাক শুরু করুন এবং তারপর SDK লোড করার জন্য একটি অনুরোধ করুন:

    কোটলিন

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        mSdkSandboxManager = applicationContext.getSystemService(
                SdkSandboxManager::class.java
        )
    
        mClientView = findViewById(R.id.rendered_view)
        mClientView.setZOrderOnTop(true)
    
        val loadSdkCallback = LoadSdkCallbackImpl()
        mSdkSandboxManager.loadSdk(
                SDK_NAME, Bundle(), { obj: Runnable -> obj.run() }, loadSdkCallback
        )
    }
    

    জাভা

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        mSdkSandboxManager = getApplicationContext().getSystemService(
                SdkSandboxManager.class);
    
        mClientView = findViewById(R.id.rendered_view);
        mClientView.setZOrderOnTop(true);
    
        LoadSdkCallbackImpl loadSdkCallback = new LoadSdkCallbackImpl();
        mSdkSandboxManager.loadSdk(
                SDK_NAME, new Bundle(), Runnable::run, loadSdkCallback);
    }
    
  6. SDK স্যান্ডবক্স প্রক্রিয়া অপ্রত্যাশিতভাবে বন্ধ হয়ে গেলে কেসটি পরিচালনা করতে, SdkSandboxProcessDeathCallback ইন্টারফেসের জন্য একটি বাস্তবায়ন সংজ্ঞায়িত করুন:

    কোটলিন

        private inner class SdkSandboxLifecycleCallbackImpl() : SdkSandboxProcessDeathCallback {
            override fun onSdkSandboxDied() {
                // The SDK runtime process has terminated. To bring back up the
                // sandbox and continue using SDKs, load the SDKs again.
                val loadSdkCallback = LoadSdkOutcomeReceiverImpl()
                mSdkSandboxManager.loadSdk(
                          SDK_NAME, Bundle(), { obj: Runnable -> obj.run() },
                          loadSdkCallback)
            }
        }
    

    জাভা

          private class SdkSandboxLifecycleCallbackImpl
                  implements SdkSandboxProcessDeathCallback {
              @Override
              public void onSdkSandboxDied() {
                  // The SDK runtime process has terminated. To bring back up
                  // the sandbox and continue using SDKs, load the SDKs again.
                  LoadSdkOutcomeReceiverImpl loadSdkCallback =
                          new LoadSdkOutcomeReceiverImpl();
                  mSdkSandboxManager.loadSdk(
                              SDK_NAME, new Bundle(), Runnable::run, loadSdkCallback);
              }
          }
    

    SDK স্যান্ডবক্স কখন বন্ধ হয়ে গেছে সে সম্পর্কে তথ্য পেতে এই কলব্যাকটি নিবন্ধন করতে, যেকোনো সময় নিম্নলিখিত লাইনটি যোগ করুন:

    কোটলিন

        mSdkSandboxManager.addSdkSandboxProcessDeathCallback({ obj: Runnable -> obj.run() },
                SdkSandboxLifecycleCallbackImpl())
    

    জাভা

        mSdkSandboxManager.addSdkSandboxProcessDeathCallback(Runnable::run,
                new SdkSandboxLifecycleCallbackImpl());
    

    যেহেতু স্যান্ডবক্সের প্রক্রিয়াটি শেষ হয়ে গেলে তার অবস্থা হারিয়ে যায়, তাই SDK দ্বারা দূরবর্তীভাবে রেন্ডার করা দৃশ্যগুলি আর সঠিকভাবে কাজ নাও করতে পারে৷ SDK-এর সাথে ইন্টারঅ্যাক্ট করা চালিয়ে যেতে, এই দৃশ্যগুলিকে আবার লোড করতে হবে যাতে একটি নতুন স্যান্ডবক্স প্রক্রিয়া শুরু হয়৷

  7. আপনার ক্লায়েন্ট অ্যাপের build.gradle এ আপনার SDK মডিউলের উপর নির্ভরতা যোগ করুন:

    dependencies {
        ...
        implementation project(':<your-sdk-module>')
        ...
    }

আপনার অ্যাপ্লিকেশন পরীক্ষা করুন

আপনার ক্লায়েন্ট অ্যাপ চালানোর জন্য, Android স্টুডিও বা কমান্ড লাইন ব্যবহার করে আপনার পরীক্ষা ডিভাইসে SDK অ্যাপ এবং ক্লায়েন্ট অ্যাপ ইনস্টল করুন।

অ্যান্ড্রয়েড স্টুডিওর মাধ্যমে স্থাপন করুন

অ্যান্ড্রয়েড স্টুডিওর মাধ্যমে স্থাপন করার সময়, নিম্নলিখিত পদক্ষেপগুলি সম্পূর্ণ করুন:

  1. আপনার ক্লায়েন্ট অ্যাপের জন্য অ্যান্ড্রয়েড স্টুডিও প্রকল্প খুলুন।
  2. Run > Edit Configurations এ যান। রান/ডিবাগ কনফিগারেশন উইন্ডো প্রদর্শিত হবে।
  3. লঞ্চ বিকল্পের অধীনে, নির্দিষ্ট কার্যকলাপে লঞ্চ সেট করুন।
  4. অ্যাক্টিভিটির পাশের তিন ডট মেনুতে ক্লিক করুন এবং আপনার ক্লায়েন্টের জন্য প্রধান অ্যাক্টিভিটি নির্বাচন করুন।
  5. প্রয়োগ করুন এবং তারপর ওকে ক্লিক করুন।
  6. রান ক্লিক করুন আপনার টেস্ট ডিভাইসে ক্লায়েন্ট অ্যাপ এবং SDK ইনস্টল করতে।

কমান্ড লাইনে স্থাপন করুন

কমান্ড লাইন ব্যবহার করে স্থাপন করার সময়, নিম্নলিখিত তালিকার ধাপগুলি সম্পূর্ণ করুন। এই বিভাগটি ধরে নেয় যে আপনার SDK অ্যাপ মডিউলের নাম হল sdk-app এবং আপনার ক্লায়েন্ট অ্যাপ মডিউলের নাম হল client-app

  1. একটি কমান্ড লাইন টার্মিনাল থেকে, গোপনীয়তা স্যান্ডবক্স SDK APK তৈরি করুন:

    ./gradlew :client-app:buildPrivacySandboxSdkApksForDebug
    

    এটি জেনারেট করা APKগুলির জন্য অবস্থান বের করে। এই APKগুলি আপনার স্থানীয় ডিবাগ কী দিয়ে স্বাক্ষরিত। পরবর্তী কমান্ডে আপনার এই পথটি প্রয়োজন।

  2. আপনার ডিভাইসে APK ইনস্টল করুন:

    adb install -t /path/to/your/standalone.apk
    
  3. অ্যান্ড্রয়েড স্টুডিওতে, রান > কনফিগারেশন সম্পাদনা করুন ক্লিক করুন। রান/ডিবাগ কনফিগারেশন উইন্ডো প্রদর্শিত হবে।

  4. ইনস্টলেশন বিকল্পের অধীনে, ডিফল্ট APK-স্থাপন সেট করুন।

  5. প্রয়োগ করুন এবং তারপর ওকে ক্লিক করুন।

  6. আপনার টেস্ট ডিভাইসে APK বান্ডেল ইনস্টল করতে Run এ ক্লিক করুন।

আপনার অ্যাপস ডিবাগ করুন

ক্লায়েন্ট অ্যাপ ডিবাগ করতে, ডিবাগ এ ক্লিক করুন অ্যান্ড্রয়েড স্টুডিওতে বোতাম।

SDK অ্যাপটি ডিবাগ করতে, Run > Attach to Process এ যান, যা আপনাকে একটি পপআপ স্ক্রীন দেখায় (নীচে দেখানো হয়েছে)। সমস্ত প্রক্রিয়া দেখান বাক্সটি চেক করুন। প্রদর্শিত তালিকায়, CLIENT_APP_PROCESS _sdk_sandbox নামক একটি প্রক্রিয়া খুঁজুন। এই বিকল্পটি নির্বাচন করুন এবং আপনার SDK ডিবাগ করা শুরু করতে SDK অ্যাপের কোডে ব্রেকপয়েন্ট যোগ করুন।

SDK অ্যাপ প্রক্রিয়া ডায়ালগের নীচের কাছে একটি তালিকা দৃশ্যে উপস্থিত হয়৷
নির্বাচন প্রক্রিয়া স্ক্রীন, যেখানে আপনি ডিবাগ করতে SDK অ্যাপটি নির্বাচন করতে পারেন।

কমান্ড লাইন থেকে SDK রানটাইম শুরু করুন এবং বন্ধ করুন

আপনার অ্যাপের জন্য SDK রানটাইম প্রক্রিয়া শুরু করতে, নিম্নলিখিত শেল কমান্ডটি ব্যবহার করুন:

adb shell cmd sdk_sandbox start [--user <USER_ID> | current] <CLIENT_APP_PACKAGE>

একইভাবে, SDK রানটাইম প্রক্রিয়া বন্ধ করতে, এই কমান্ডটি চালান:

adb shell cmd sdk_sandbox stop [--user <USER_ID> | current] <CLIENT_APP_PACKAGE>

সীমাবদ্ধতা

SDK রানটাইমের জন্য চলমান ক্ষমতার তালিকার জন্য, রিলিজ নোটগুলি দেখুন।

কোড নমুনা

GitHub-এ SDK রানটাইম এবং গোপনীয়তা সংরক্ষণকারী APIs সংগ্রহস্থলে আপনাকে শুরু করতে সাহায্য করার জন্য পৃথক Android স্টুডিও প্রকল্পের একটি সেট রয়েছে, যার মধ্যে নমুনাগুলি রয়েছে যা প্রদর্শন করে যে কীভাবে SDK রানটাইম শুরু করতে হয় এবং কল করতে হয়।

বাগ এবং সমস্যা রিপোর্ট করুন

আপনার প্রতিক্রিয়া Android এ গোপনীয়তা স্যান্ডবক্সের একটি গুরুত্বপূর্ণ অংশ! Android-এ গোপনীয়তা স্যান্ডবক্সের উন্নতির জন্য আপনার খুঁজে পাওয়া যেকোন সমস্যা বা ধারণা সম্পর্কে আমাদের জানান।

{% শব্দার্থে %} {% endverbatim %} {% শব্দার্থে %} {% endverbatim %}