शिज़ुकु लाइब्रेरी का उपयोग करके ऐप अनुमतियां कैसे बढ़ाएं

रूट करना हर किसी के लिए नहीं है. यहां बताया गया है कि आप शिज़ुकु लाइब्रेरी का उपयोग करके अपने ऐप में उन्नत शेल-स्तरीय अनुमतियां कैसे प्राप्त कर सकते हैं।

ऐसे कई कारण हैं जिनके कारण सामान्य रूप से आपके ऐप को दी गई अनुमतियाँ पर्याप्त नहीं हो सकती हैं। हो सकता है कि आप मेरे जैसे हों और एंड्रॉइड एपीआई का दुरुपयोग करने वाले हैकी ऐप्स बनाने का आनंद लेते हों। मेरे द्वारा उपयोग किए जाने वाले कुछ एपीआई विशेष अनुमतियों के पीछे बंद हैं। कभी-कभी केवल शेल उपयोगकर्ता (एडीबी) या सिस्टम ही उन तक पहुंच सकता है। हालाँकि एक समाधान है - शिज़ुकु।

शिज़ुकु आपको सिस्टम एपीआई को लगभग सीधे और पूरी तरह से जावा या कोटलिन में कॉल करने की अनुमति देता है। यह मार्गदर्शिका आपको दिखाएगी कि शिज़ुकु को कैसे कार्यान्वित और उपयोग करें।

शिज़ुकु क्या है?

इससे पहले कि हम शिज़ुकु का उपयोग करें, यह जानना उपयोगी हो सकता है कि यह वास्तव में क्या है। यदि आप परिचित हैं मैजिक, तो शिज़ुकु समान है। लेकिन रूट एक्सेस को प्रबंधित करने के बजाय, यह शेल एक्सेस को प्रबंधित करता है।

शिज़ुकु शेल-स्तरीय अनुमतियों के साथ अपनी स्वयं की प्रक्रिया चलाता है। उपयोगकर्ता उस प्रक्रिया को कैसे सक्रिय करता है यह उनके डिवाइस, एंड्रॉइड संस्करण और पसंद पर निर्भर करता है। शिज़ुकु को एडीबी के माध्यम से, ऑन-डिवाइस वायरलेस एडीबी के माध्यम से सक्रिय किया जा सकता है (

Android 11 और बाद के संस्करण पर), या रूट एक्सेस के माध्यम से। शिज़ुकु को लागू करने वाले ऐप्स उन्नत संचालन करने के लिए उस प्रक्रिया का उपयोग करने की अनुमति का अनुरोध कर सकते हैं।

शिज़ुकुडेवलपर: ज़िंगचेन और रिक्का

कीमत: मुफ़्त.

4.1.

डाउनलोड करना

शिज़ुकु क्यों?

जबकि सिस्टम तक शेल-स्तरीय पहुंच आपको उतना करने की अनुमति नहीं देती है जड़, यह अभी भी आपको सामान्य ऐप की तुलना में अधिक पहुंच प्रदान करता है। इसके अलावा, शिज़ुकु के काम करने का तरीका आपको एंड्रॉइड एपीआई को लगभग सामान्य की तरह उपयोग करने की सुविधा देता है। आपको शेल कमांड पर निर्भर रहने की ज़रूरत नहीं है (हालाँकि आप चाहें तो ऐसा कर सकते हैं)।

यदि आपके ऐप को विशेष अनुमतियों की आवश्यकता है जो केवल एडीबी (या रूट के साथ) के माध्यम से दी जा सकती है, तो शिज़ुकु और एंड्रॉइड 11 एक बेहतरीन जोड़ी बनाते हैं। आप पूरी तरह से डिवाइस पर विशेष अनुमतियाँ देने के लिए शिज़ुकु का उपयोग कर सकते हैं।

यहां तक ​​कि उन उपकरणों के साथ भी जो एंड्रॉइड 11 पर नहीं हैं, शिज़ुकु उपयोगी हो सकता है। ऐप उपयोगकर्ताओं के लिए निर्देश और स्क्रिप्ट प्रदान करता है ताकि आपको ऐसा न करना पड़े।

एकीकरण

शिज़ुकु को अपने ऐप में जोड़ना सबसे आसान नहीं है, लेकिन कठिन भी नहीं है। दुर्भाग्य से डेवलपर दस्तावेज़ीकरण बिल्कुल पूर्ण नहीं है, लेकिन इस लेख में आपको कवर किया गया है। शिज़ुकु को अपने ऐप में एकीकृत करने का तरीका यहां बताया गया है।

निर्भरताएँ

पहला कदम शिज़ुकु निर्भरता को जोड़ना है। अपने मॉड्यूल-स्तरीय बिल्ड.ग्रेडल में, निर्भरता ब्लॉक में निम्नलिखित जोड़ें।

def shizuku_version = '11.0.3'

implementation "dev.rikka.shizuku: api:$shizuku_version"
implementation "dev.rikka.shizuku: provider:$shizuku_version"

यदि आवश्यक हो तो संस्करण को अद्यतन करना सुनिश्चित करें। 11.0.3 लेखन के समय नवीनतम है।

प्रदाता

शिज़ुकु को काम करने के लिए, आपको अपने ऐप के मेनिफेस्ट में एक प्रदाता ब्लॉक जोड़ना होगा। AndroidManifest.xml खोलें और एप्लिकेशन ब्लॉक के अंदर निम्नलिखित जोड़ें।

 android: name="rikka.shizuku.ShizukuProvider"
android: authorities="${applicationId}.shizuku"
android: multiprocess="false"
android: enabled="true"
android: exported="true"
android: permission="android.permission.INTERACT_ACROSS_USERS_FULL" />

अनुमति

प्राधिकरण के लिए, शिज़ुकु रनटाइम अनुमति का उपयोग करता है। हम थोड़ी देर में वह अनुमति देने पर विचार करेंगे। अभी के लिए, इसे मेनिफेस्ट ब्लॉक के अंदर AndroidManifest.xml में जोड़ें।

अब जब वह सब जुड़ गया है, तो बुनियादी एकीकरण हो गया है। ग्रैडल को प्रोजेक्ट सिंक करने दें, और उपयोग जारी रखें।


प्रयोग

उपलब्धता की जाँच

शिज़ुकु का उपयोग कैसे करें यह जानने से पहले, आइए यह सुनिश्चित करने के बारे में बात करें कि यह वास्तव में उपयोग के लिए उपलब्ध है।

यह जांचने से पहले कि क्या अनुमति दी गई है, और शिज़ुकु के माध्यम से एपीआई कॉल करने से पहले, आप यह सुनिश्चित कर सकते हैं कि वे जांच और कॉल निम्नलिखित विधि से सफल होंगी:

Shizuku.pingBinder()

यदि शिज़ुकु स्थापित है और चल रहा है, तो यह वापस आ जाएगा सत्य. अन्यथा, यह झूठी वापसी करेगा.

अनुमति देना

चूंकि शिज़ुकु रनटाइम अनुमति का उपयोग करता है, इसलिए शेल एक्सेस के साथ कुछ भी करने से पहले इसे आपके ऐप को देना होगा। इसे प्रदान करने के विभिन्न तरीकों के साथ दो एपीआई संस्करण भी प्रचलन में हैं। यह अनुभाग आपको दिखाएगा कि दोनों को कैसे संभालना है।

चेकिंग

अनुमति का अनुरोध करने से पहले, सबसे अच्छी बात यह जांचना है कि क्या आपके पास यह पहले से ही है। यदि आप ऐसा करते हैं, तो आपको जो भी करने की आवश्यकता है उसे जारी रख सकते हैं। अन्यथा, आपको जारी रखने से पहले इसका अनुरोध करना होगा।

यह जांचने के लिए कि क्या आपके पास शिज़ुकु का उपयोग करने की अनुमति है, आप निम्नलिखित का उपयोग कर सकते हैं। यह कोड मान रहा है कि आप इसे किसी गतिविधि के अंदर चला रहे हैं।

Kotlin:

val isGranted = if (Shizuku.isPreV11() || Shizuku.getVersion() < 11) {
checkSelfPermission(ShizukuProvider.PERMISSION) == PackageManager.PERMISSION_GRANTED
} else {
Shizuku.checkSelfPermission() = PackageManager.PERMISSION_GRANTED
}

जावा:

boolean isGranted;
if (Shizuku.isPreV11() || Shizuku.getVersion() < 11) {
isGranted = checkSelfPermission(ShizukuProvider.PERMISSION) == PackageManager.PERMISSION_GRANTED;
} else {
isGranted = Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED;
}

बिनती करना

यदि आपको शिज़ुकु का उपयोग करने के लिए अनुमति का अनुरोध करने की आवश्यकता है, तो यहां बताया गया है।

 शिज़ुकु_कोड नीचे प्रयुक्त चर एक स्थिर मान (स्थैतिक चर) वाला पूर्णांक होना चाहिए।

Kotlin:

if (Shizuku.isPreV11() || Shizuku.getVersion() < 11) {
requestPermissions(arrayOf(ShizukuProvider.PERMISSION), SHIZUKU_CODE)
} else {
Shizuku.requestPermission(SHIZUKU_CODE)
}

जावा:

if (Shizuku.isPreV11() || Shizuku.getVersion() < 11) {
requestPermissions(newString[] { ShizukuProvider.PERMISSION }, SHIZUKU_CODE);
} else {
Shizuku.requestPermissions(SHIZUKU_CODE);
}

परिणाम सुनने के लिए, आपको गतिविधि को ओवरराइड करना होगा onRequestPermissionsResult() तरीका। आपको अमल भी करना होगा शिज़ुकु. OnRequestPermissionResultListener. मैं जो उदाहरण दिखाने जा रहा हूं वह मानता है कि आपकी गतिविधि उस इंटरफ़ेस को लागू करती है, लेकिन यदि आप चाहें तो आप इसे एक वेरिएबल में लागू कर सकते हैं।

Kotlin:

classExampleActivity : AppCompatActivity, Shizuku.OnRequestPermissionResultListener {
...

override void onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
permissions.forEachIndexed { index, permission ->
if (permission == ShizukuProvider.PERMISSION) {
onRequestPermissionResult(requestCode, grantResults[index])
}
}
}

override voidonRequestPermissionResult(requestCode: Int, grantResult: Int){
val isGranted = grantResult == PackageManager.PERMISSION_GRANTED
//Dostuff based on the result.

}
}

जावा:

publicclassExampleActivityextendsAppCompatActivityimplementsShizuku.OnRequestPermissionResultListener{
...

@Override
publicvoidonRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults){
for (int i = 0; i < permissions.length; i++) {
String permission = permissions[i];
int result = grantResults[i];

if (permission.equals(ShizukuProvider.PERMISSION) {
onRequestPermissionResult(requestCode, result);
}
}
}

@Override
publicvoidonRequestPermissionResult(int requestCode, int grantResult){
boolean isGranted = grantResult == PackageManager.PERMISSION_GRANTED;
//Dostuff based on the result.
}
}

एपीआई का उपयोग करना

अब जब शिज़ुकु स्थापित हो गया है और अनुमतियाँ मिल गई हैं, तो आप वास्तव में शिज़ुकु का उपयोग करके एपीआई को कॉल करना शुरू कर सकते हैं। यहां की प्रक्रिया आपकी आदत से थोड़ी अलग है। कॉल करने के बजाय getSystemService() और कुछ इस तरह से कास्टिंग करना WindowManager, आपको इसके बजाय आंतरिक एपीआई का उपयोग करना होगा (उदाहरण के लिए, IWindowManager).

शिज़ुकु में एंड्रॉइड की छिपी हुई एपीआई ब्लैकलिस्ट के लिए एक बाईपास शामिल है, इसलिए इसका उपयोग करते समय आपको इसके बारे में चिंता करने की आवश्यकता नहीं होगी। हालाँकि, यदि आप जानना चाहते हैं कि इसे स्वयं कैसे दरकिनार किया जाए, तो मेरा पिछला ट्यूटोरियल देखें।

यहां एक त्वरित उदाहरण है (प्रतिबिंब का उपयोग करके) जो आपको दिखाता है कि आप इसका उदाहरण कैसे प्राप्त कर सकते हैं IPackageManager और किसी ऐप को रनटाइम अनुमति देने के लिए इसका उपयोग करें।

Kotlin:

val iPmClass = Class.forName("android.content.pm.IPackageManager")
val iPmStub = Class.forName("android.content.pm.IPackageManager\$Stub")
val asInterfaceMethod = iPmStub.getMethod("asInterface", IBinder::class.java)
val grantRuntimePermissionMethod = iPmClass.getMethod("grantRuntimePermission", String:: class.java /* package name */, String:: class.java /* permission name */, Int:: class.java /* user ID */)

val iPmInstance = asInterfaceMethod.invoke(null, ShizukuBinderWrapper(SystemServiceHelper.getSystemService("package")))

grantRuntimePermissionMethod.invoke(iPmInstance, "com.zacharee1.systemuituner", android.Manifest.permission.WRITE_SECURE_SETTINGS, 0)

जावा:

Class< ?>> iPmClass = Class.forName("android.content.pm.IPackageManager");
Class< ?>> iPmStub = Class.forName("android.content.pm.IPackageManager$Stub");
Method asInterfaceMethod = iPmStub.getMethod("asInterface", IBinder.class);
Method grantRuntimePermissionMethod = iPmClass.getMethod("grantRuntimePermission", String.class, String.class, int.class);

val iPmInstance = asInterfaceMethod.invoke(null, new ShizukuBinderWrapper(SystemServiceHelper.getSystemService("package")));

grantRuntimePermissionMethod.invoke(iPmInstance, "com.zacharee1.systemuituner", android.Manifest.permission.WRITE_SECURE_SETTINGS, 0);

अन्य एपीआई के लिए प्रक्रिया समान है। वर्ग और उसके स्टब उप-वर्ग के संदर्भ प्राप्त करें। का संदर्भ प्राप्त करें asInterface स्टब वर्ग के लिए विधि. अपनी इच्छित विधियों का संदर्भ कक्षा से ही प्राप्त करें। फिर, आह्वान करें asInterface आपके पास विधि संदर्भ है, प्रतिस्थापित करना "package" आपको जो भी सेवा चाहिए उसके साथ ऊपर। फिर उस उदाहरण को विधि आमंत्रण के लिए पारित किया जा सकता है।

प्रो टिप: यदि आप एक संशोधित एसडीके स्थापित करते हैं तो आप प्रतिबिंब का उपयोग करने से पूरी तरह बच सकते हैं। Anggrayudi की GitHub रिपॉजिटरी देखें संशोधित एसडीके और इंस्टॉलेशन निर्देशों के लिए। इसे स्थापित करने से, उपरोक्त कोड (कोटलिन में) काफी सरल हो जाता है।

val iPm = IPackageManager.Stub.asInterface(ShizukuBinderWrapper(SystemServiceHelper.getService("package"))))
iPm.grantRuntimePermission("com.zacharee1.systemuituner", android.Manifest.permission.WRITE_SECURE_SETTINGS, 0)

किसी भी एआईडीएल-आधारित एपीआई का उपयोग आपके ऐप में कहीं से भी इस पद्धति के साथ किया जा सकता है, जब तक कि शिज़ुकु चल रहा है और आपके ऐप को अनुमति है।

उपयोगकर्ता सेवा

जबकि बाइंडर विधि अधिकांश उपयोग-मामलों को कवर करती है, ऐसे समय भी हो सकते हैं जहां आपको एक एपीआई की आवश्यकता होती है जिसमें प्रत्यक्ष बाइंडर इंटरफ़ेस नहीं होता है। उस स्थिति में, आप शिज़ुकु में उपयोगकर्ता सेवा सुविधा का उपयोग कर सकते हैं।

यह विधि एंड्रॉइड में सामान्य सेवा के समान ही काम करती है। आप इसे "प्रारंभ" करते हैं, इसे सर्विसकनेक्शन के साथ जोड़कर संचार करते हैं, और सर्विस क्लास में अपना तर्क चलाते हैं। अंतर यह है कि आप एंड्रॉइड की सेवा का उपयोग नहीं कर रहे हैं, और सेवा के अंदर कुछ भी एडीबी अनुमतियों के साथ चलता है।

अब कुछ सीमाएँ हैं। उपयोगकर्ता सेवा पूरी तरह से अलग प्रक्रिया और उपयोगकर्ता में चलती है, इसलिए आप अपने स्वयं के एआईडीएल कॉलबैक और बाइंडर्स को छोड़कर अपने बाकी ऐप के साथ बातचीत नहीं कर सकते हैं। चूँकि यह उचित ऐप प्रक्रिया में भी नहीं चल रहा है, इसलिए Android सेवाओं को बाइंड करने जैसी कुछ चीज़ें ठीक से काम नहीं कर सकती हैं।

इसके लिए शिज़ुकु संस्करण 10 या उसके बाद के संस्करण की भी आवश्यकता है। जबकि ऐप के अधिकांश स्रोतों में वर्तमान में संस्करण 11 है, फिर भी आपको एक संस्करण जांच शामिल करनी चाहिए, जिसे उदाहरण में शामिल किया जाएगा।

एआईडीएल को परिभाषित करना

आरंभ करने के लिए, आपको एक नई AIDL फ़ाइल बनानी होगी। आप इसे एंड्रॉइड स्टूडियो में एंड्रॉइड फ़ाइल-व्यू में किसी भी चीज़ पर राइट-क्लिक करके, "नए" विकल्प पर होवर करके और "एआईडीएल" विकल्प चुनकर कर सकते हैं। फ़ाइल का नाम दर्ज करें (उदाहरण के लिए, "IUserService"), और एंड्रॉइड स्टूडियो आपके लिए एक टेम्पलेट फ़ाइल बनाएगा।

यदि आप इस बात से परिचित नहीं हैं कि एआईडीएल कैसे काम करता है, तो अवश्य देखें Google का दस्तावेज़ीकरण.

एआईडीएल से टेम्प्लेट विधियां हटाएं और फिर जोड़ें destroy() शिज़ुकु के लिए उचित आईडी वाली विधि। इसे तब कॉल किया जाएगा जब शिज़ुकु उपयोगकर्ता सेवा को बंद कर रहा है, और इसका उपयोग आपके पास मौजूद किसी भी संदर्भ या चल रहे तर्क को साफ़ करने के लिए किया जाना चाहिए।

उदाहरण एआईडीएल:

packagetk.zwander.shizukudemo;

interfaceIUserService{
voiddestroy()= 16777114;

void grantPermission(String packageName, String permission, int userId) = 1; //You can specify your own method IDs in the AIDL. Check out the documentation for more details on this.
}

एआईडीएल का कार्यान्वयन

अगली चीज़ जो आपको करनी है वह वास्तव में एआईडीएल को लागू करना है।

जावा:

publicclassUserServiceextendsIUserService.Stub{
//Make sure to include an empty constructor.
publicUserService(){
}

@Override
publicvoiddestroy(){
//Shizuku wants the service to be killed. Clean up and then exit.
System.exit(0);
}

@Override
publicvoidgrantPermission(String packageName, String permission, int userId){
//No need to use ShizukuBinderWrapper.
IPackageManager.Stub.asInterface(SystemServiceHelper.getService("package")).grantRuntimePermission(packageName, permission, userId);
}
}

Kotlin:

classUserService : IUserService.Stub {
//Include an empty constructor.
constructor() {
}

override fun destroy(){
//Shizuku wants the service to be killed. Clean up and exit.
System.exit(0)
}

override fun grantPermission(packageName: String, permission: String, userId: Int) {
//No need for ShizukuBinderWrapper.
IPackageManager.Stub.asInterface(SystemServiceHelper.getService("package")).grantRuntimePermission(packageName, permission, userId)
}
}

उपरोक्त उदाहरण मानते हैं कि आपके पास है एंड्रॉइड हिडन एपीआई एसडीके स्थापित.

सेवा कनेक्शन स्थापित करना

अब जब उपयोगकर्ता सेवा परिभाषित और कार्यान्वित हो गई है, तो इसे उपयोग के लिए स्थापित करने का समय आ गया है। पहली चीज़ जो आपको करनी चाहिए वह एक सर्विसकनेक्शन को परिभाषित करना है जहां आप इसके साथ संचार करना चाहते हैं (उदाहरण के लिए, आपके ऐप में मुख्य गतिविधि से)।

जावा:

private IUserService binder = null;

privatefinal ServiceConnection connection = new ServiceConnection() {
@Override
publicvoidonServiceConnected(ComponentName componentName, IBinder binder){
if (binder != null && binder.pingBinder()) {
binder = IUserService.Stub.asInterface(binder);
}
}

@Override
publicvoidonServiceDisconnected(ComponentName componentName){
binder = null;
}
}

Kotlin:

privatevar binder: IUserService? = null

private val connection = object: ServiceConnection {
override fun onServiceConnected(componentName: ComponentName, binder: IBinder?){
if (binder != null && binder.pingBinder()) {
binder = IUserService.Stub.asInterface(binder)
}
}

override fun onServiceDisconnected(componentName: ComponentName){
binder = null;
}
}

binder वेरिएबल वह है जिसका उपयोग आप अपने ऐप से उपयोगकर्ता सेवा के साथ संचार करने के लिए करेंगे। यह जांचने के लिए कि क्या यह उपयोग के लिए उपलब्ध है, बस यह जांच लें कि यह शून्य तो नहीं है pingBinder() रिटर्न सत्य, बिल्कुल ऊपर दिए गए कोड उदाहरण की तरह।

उपयोगकर्ता सेवा तर्क बनाना

इससे पहले कि आप उपयोगकर्ता सेवा को नियंत्रित कर सकें, आपको शिज़ुकु के लिए इसे शुरू और बंद करते समय उपयोग करने के लिए कुछ तर्कों को परिभाषित करने की आवश्यकता होगी। इनमें वास्तव में शिज़ुकु को सेवा का वर्ग नाम बताना, प्रक्रिया प्रत्यय निर्दिष्ट करना, यह डिबग करने योग्य है या नहीं और यह कौन सा संस्करण है जैसी चीजें शामिल हैं।

जावा:

privatefinal Shizuku.UserServiceArgs serviceArgs = new Shizuku.UserServiceArgs(
newComponentName(BuildConfig.APPLICATION_ID, UserService.class.getName()))
.processNameSuffix("user_service")
.debuggable(BuildConfig.DEBUG)
.version(BuildConfig.VERSION_CODE);

Kotlin:

private val serviceArgs = Shizuku.UserServiceArgs(
ComponentName(BuildConfig.APPLICATION_ID, UserService.class::java.getName()))
.processNameSuffix("user_service")
.debuggable(BuildCOnfig.DEBUG)
.version(BuildConfig.VERSION_CODE)

उपयोगकर्ता सेवा प्रारंभ करना, रोकना और बाध्य करना

शिज़ुकु में प्रारंभ और बाइंड क्रियाएँ और स्टॉप और अनबाइंड क्रियाएँ एकीकृत हैं। अलग-अलग स्टार्ट और बाइंड विधियाँ या स्टॉप और अनबाइंड विधियाँ नहीं हैं।

यहां बताया गया है कि कैसे करें प्रारंभ करें और बांधें उपयोगकर्ता सेवा.

जावा:

if (Shizuku.getVersion >= 10) {
//This only works on Shizuku 10 or later.
Shizuku.bindUserService(serviceArgs, connection);
} else {
//Tell the user to upgrade Shizuku.
}

Kotlin:

if (Shizuku.getVersion() >= 10) {
//This only works on Shizuku 10 or later.
Shizuku.bindUserService(serviceArgs, connection)
} else {
//Tell the user to upgrade Shizuku.
}

यहां बताया गया है कि कैसे करें रुकें और बंधन मुक्त करें उपयोगकर्ता सेवा.

जावा:

if (Shizuku.getVersion >= 10) {
Shizuku.unbindUserService(serviceArgs, connection, true);
}

Kotlin:

if (Shizuku.getVersion >= 10) {
Shizuku.unbindUserService(serviceArgs, connection, true)
}

उपयोगकर्ता सेवा का आह्वान करना

एक बार उपयोगकर्ता सेवा शुरू हो जाने पर, आप इसका उपयोग शुरू कर सकते हैं। बस जांचें कि क्या binder वेरिएबल गैर-शून्य और पिंग योग्य है, और फिर अपना मेथड कॉल करें।

जावा:

if (binder != null && binder.pingBinder()) {
binder.grantPermission("com.zacharee1.systemuituner", android.Manifest.permission.WRITE_SECURE_SETTINGS, 0);
}

Kotlin:

if (binder?.pingBinder() == true) {
binder?.grantPermission("com.zacharee1.systemuituner", android.Manifest.permission.WRITE_SECURE_SETTINGS, 0)
}

निष्कर्ष

यदि आपने उन सभी का पालन किया है, तो अब आपके पास एक कार्यशील शिज़ुकु एकीकरण होना चाहिए। बस अपने उपयोगकर्ताओं को शिज़ुकु इंस्टॉल करने के लिए कहना याद रखें, और इसका उपयोग करने का प्रयास करने से पहले ठीक से जांच लें कि शिज़ुकु उपलब्ध है या नहीं।