কীভাবে ইনকামিং কলগুলি অ্যানড্রয়েড 5.0 (ললিপপ) এ প্রোগ্রামযুক্তভাবে উত্তর দেওয়া যায়?


89

ইনকামিং কলগুলির জন্য আমি যেমন একটি কাস্টম স্ক্রিন তৈরি করার চেষ্টা করছি তখন আমি ইনকামিং কলটির প্রগতিগতভাবে উত্তর দেওয়ার চেষ্টা করছি। আমি নিম্নলিখিত কোডটি ব্যবহার করছি তবে এটি অ্যান্ড্রয়েড 5.0 তে কাজ করছে না।

// Simulate a press of the headset button to pick up the call
Intent buttonDown = new Intent(Intent.ACTION_MEDIA_BUTTON);             
buttonDown.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK));
context.sendOrderedBroadcast(buttonDown, "android.permission.CALL_PRIVILEGED");

// froyo and beyond trigger on buttonUp instead of buttonDown
Intent buttonUp = new Intent(Intent.ACTION_MEDIA_BUTTON);               
buttonUp.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK));
context.sendOrderedBroadcast(buttonUp, "android.permission.CALL_PRIVILEGED");

ওহে ম্যান, এটার মধ্যে দৌড়াতে কেন ম্যান স্লাইড! আমার কাছে সহজ মনে হচ্ছে \ এম /
নোবেলজি

আমি অ্যান্ড্রয়েড ব্যবহারকারীদের জন্য একটি কাস্টম ইনকামিং কল স্ক্রিন তৈরি করছি।
maveroid

4
যে কেউ? আমি এই এক আগ্রহী! প্রচুর জিনিস চেষ্টা করেও সেগুলি কার্যকর হয়নি: /
আর্থার

4
@ নোবালজি তিনি প্রোগ্রামিয়ালি বলছেন
59-

4
@ ম্যাওয়ারয়েড, আপনি কি অ্যান্ড্রয়েড 5.0 এর জন্য একটি কাজের সাথে এসেছিলেন?
আর্থারসফ্রেয়ার

উত্তর:


156

অ্যান্ড্রয়েড 8.0 ওরিও দিয়ে আপডেট করুন

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

কী বদলে গেল?

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

আমরা কীভাবে এই পরিবর্তনটি ব্যবহার করব?

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

অনুমতি প্রাপ্ত থাকার পর, আপনার অ্যাপ্লিকেশন সহজভাবে ডাকতে হয়েছে TelecomManager এর acceptRingingCall পদ্ধতি। একটি বেসিক প্রার্থনা নিম্নলিখিত হিসাবে প্রদর্শিত হচ্ছে:

TelecomManager tm = (TelecomManager) mContext
        .getSystemService(Context.TELECOM_SERVICE);

if (tm == null) {
    // whether you want to handle this is up to you really
    throw new NullPointerException("tm == null");
}

tm.acceptRingingCall();

পদ্ধতি 1: টেলিফোনি ম্যানেজ.আনসেটর রিংকলিং ()

কখন আপনার ডিভাইসে সীমাহীন নিয়ন্ত্রণ থাকবে For

এটা কি?

এখানে টেলিফোনিম্যানেজ.আনসওয়ার রিংকলিং () রয়েছে যা একটি লুকানো, অভ্যন্তরীণ পদ্ধতি। এটি ITelephony.answerRingingCall () এর জন্য একটি সেতু হিসাবে কাজ করে যা আন্তঃবিশ্ব সম্পর্কে আলোচনা করা হয়েছিল এবং শুরুতে আশাব্যঞ্জক বলে মনে হচ্ছে। এটি 4.4.2_r1 এ উপলব্ধ নয় কারণ এটি কেবল অ্যান্ড্রয়েড 4.4 কিটকাট ( 4.4.3_r1-এ লাইন 1537 ) এর জন্য প্রতিশ্রুতি 83da75 ডি- তে এবং পরে ললিপপের ( 5.0.0_r1-তে লাইন 3138 ) কমিট f1e1e77 এ "পুনঃপ্রবর্তন" করা হয়েছিল গিট ট্রি কাঠামোগত ছিল। এর অর্থ হ'ল আপনি যদি ললিপপ সহ কেবলমাত্র ডিভাইসগুলিকে সমর্থন করেন না, যা সম্ভবত এখনই এর ক্ষুদ্র বাজারের অংশীদারের উপর ভিত্তি করে একটি খারাপ সিদ্ধান্ত, আপনি যদি এখনও এই রাস্তায় নেমে যান তবে আপনাকে ফ্যালব্যাক পদ্ধতি সরবরাহ করতে হবে।

আমরা কীভাবে এটি ব্যবহার করব?

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

এবং কোডটি কীভাবে দেখায়?

// set the logging tag constant; you probably want to change this
final String LOG_TAG = "TelephonyAnswer";

TelephonyManager tm = (TelephonyManager) mContext
        .getSystemService(Context.TELEPHONY_SERVICE);

try {
    if (tm == null) {
        // this will be easier for debugging later on
        throw new NullPointerException("tm == null");
    }

    // do reflection magic
    tm.getClass().getMethod("answerRingingCall").invoke(tm);
} catch (Exception e) {
    // we catch it all as the following things could happen:
    // NoSuchMethodException, if the answerRingingCall() is missing
    // SecurityException, if the security manager is not happy
    // IllegalAccessException, if the method is not accessible
    // IllegalArgumentException, if the method expected other arguments
    // InvocationTargetException, if the method threw itself
    // NullPointerException, if something was a null value along the way
    // ExceptionInInitializerError, if initialization failed
    // something more crazy, if anything else breaks

    // TODO decide how to handle this state
    // you probably want to set some failure state/go to fallback
    Log.e(LOG_TAG, "Unable to use the Telephony Manager directly.", e);
}

এটা সত্য হতে খুব ভাল!

আসলে, একটি সামান্য সমস্যা আছে। এই পদ্ধতি সম্পূর্ণ ক্রিয়ামূলক হওয়া উচিত, কিন্তু নিরাপত্তা ম্যানেজার রাখা কলারের চায় android.permission.MODIFY_PHONE_STATE । এই অনুমতিটি কেবলমাত্র সিস্টেমের আংশিক নথিভুক্ত বৈশিষ্ট্যের ক্ষেত্রে রয়েছে কারণ তৃতীয় পক্ষগুলি এটির স্পর্শ করবে না বলে আশা করা যায় (আপনি এটির জন্য ডকুমেন্টেশন থেকে দেখতে পারেন)। আপনি <uses-permission>এটির জন্য একটি যুক্ত করার চেষ্টা করতে পারেন তবে এটি কোনও ভাল করবে না কারণ এই অনুমতিটির সুরক্ষা স্তর হ'ল স্বাক্ষর | সিস্টেম ( 5.0.0_r1 তে মূল / অ্যান্ড্রয়েড ম্যানিফেস্টের 1201 লাইনটি দেখুন )।

আপনি ইস্যু 34785 পড়তে পারেন : অ্যান্ড্রয়েড আপডেট করুন: প্রোটেকশন লেভেল ডকুমেন্টেশন যা 2012 সালে ফিরে তৈরি হয়েছিল তা দেখতে যে আমরা নির্দিষ্ট "পাইপ সিনট্যাক্স" সম্পর্কে বিশদটি অনুপস্থিত রয়েছি, তবে চারপাশের পরীক্ষা-নিরীক্ষার মাধ্যমে মনে হয় এটি অবশ্যই 'ও' হিসাবে কাজ করবে যা সমস্ত অর্থ অনুমতি প্রদানের জন্য নির্দিষ্ট পতাকাগুলি পূরণ করতে হবে। এই অনুমানের অধীনে কাজ করা, এর অর্থ হ'ল আপনার অবশ্যই আবেদন করা উচিত:

  1. সিস্টেম অ্যাপ্লিকেশন হিসাবে ইনস্টল করা হয়েছে।

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

  2. ফ্রেমওয়ার্ক / বেস ওরফে সিস্টেম, আরএফ আরএফ হিসাবে একই স্বাক্ষর সহ স্বাক্ষরিত।

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

অতিরিক্তভাবে, এই আচরণটি ইস্যুটি 34792 ইস্যু সম্পর্কিত বলে মনে হয় : অ্যান্ড্রয়েড জেলি বিন / 4.1: android.permission.READ_LOGS আর কাজ করে না যা একই সুরক্ষা স্তরটিকে একটি অনিবন্ধিত বিকাশের পতাকার পাশাপাশি ব্যবহার করে util

টেলিফোনি ম্যানেজারের সাথে কাজ করা ভাল শোনাচ্ছে তবে আপনি যদি যথাযথ অনুমতি না পান যা অনুশীলনে করা এত সহজ নয় তবে কাজ করবে না।

অন্যান্য উপায়ে টেলিফোনি ম্যানেজার ব্যবহার সম্পর্কে কী?

দুঃখের বিষয়, শীতল সরঞ্জামগুলি ব্যবহার করার জন্য আপনাকে Android.permission.MODIFY_PHONE_STATE ধরে রাখা দরকার বলে মনে হচ্ছে যার ফলস্বরূপ আপনি সেই পদ্ধতিগুলিতে অ্যাক্সেস পেতে খুব কঠিন সময় কাটাচ্ছেন।


পদ্ধতি 2: পরিষেবা কল করুন সার্ভিস কোডে

কখন আপনি পরীক্ষা করতে পারবেন যে ডিভাইসে চলমান বিল্ডটি নির্দিষ্ট কোড দিয়ে কাজ করবে।

টেলিফোনি ম্যানেজারের সাথে ইন্টারঅ্যাক্ট করতে সক্ষম না হয়ে serviceএক্সিকিউটেবলের মাধ্যমে পরিষেবাটির সাথে যোগাযোগের সম্ভাবনাও রয়েছে ।

কিভাবে কাজ করে?

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

  • আমরা যে পরিষেবা নামটি ব্যবহার করতে চাই তা হ'ল ফোন

    এটি দৌড় দিয়ে দেখা যায় service list

  • আমরা যে কোডটি ব্যবহার করতে চাইছি তা 6 টির মতো মনে হলেও এটি এখন 5 এর মতো

    দেখে মনে হচ্ছে এটি আইবিন্ডারের উপর ভিত্তি করে তৈরি হয়েছে many এখন অনেক সংস্করণের জন্য এখনই ( 1.5_r4 থেকে 4.4.4_r1 ) এফআইআরআইএসসিএলএলআলআরআরআআআআআআআআআআআআআআআআআআআআআআআ । ললিপো যেহেতু চারপাশে একটি বিশাল আপডেট, এটি এখানে বোধগম্য অভ্যন্তরীণও বোধগম্য।

এই একটি আদেশের সঙ্গে ফলাফল service call phone 5

আমরা কীভাবে এই প্রোগ্রামটি ব্যবহার করব?

জাভা

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

try {
    Process proc = Runtime.getRuntime().exec("su");
    DataOutputStream os = new DataOutputStream(proc.getOutputStream());

    os.writeBytes("service call phone 5\n");
    os.flush();

    os.writeBytes("exit\n");
    os.flush();

    if (proc.waitFor() == 255) {
        // TODO handle being declined root access
        // 255 is the standard code for being declined root for SU
    }
} catch (IOException e) {
    // TODO handle I/O going wrong
    // this probably means that the device isn't rooted
} catch (InterruptedException e) {
    // don't swallow interruptions
    Thread.currentThread().interrupt();
}

প্রকাশ

<!-- Inform the user we want them root accesses. -->
<uses-permission android:name="android.permission.ACCESS_SUPERUSER"/>

এর জন্য কি সত্যিই রুট অ্যাক্সেসের প্রয়োজন?

দুঃখজনকভাবে, এটা মনে হচ্ছে। আপনি এটিতে রানটাইম.এক্সেক ব্যবহার করার চেষ্টা করতে পারেন তবে আমি সেই রুটের সাথে কোনও ভাগ্য পেতে সক্ষম হইনি।

এটা কতটা স্থিতিশীল?

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


আসল পদ্ধতি: হেডসেট কীকোড উদ্দেশ্যগুলি

আপনি যখন স্থায়ী হতে হবে যখন সময় জন্য।

নিম্নলিখিত বিভাগটি রিলে সি দ্বারা এই উত্তর দ্বারা দৃ strongly়ভাবে প্রভাবিত হয়েছিল ।

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

এখনই কি কিছু করার আছে?

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

কোড?

new Thread(new Runnable() {

    @Override
    public void run() {
        try {
            Runtime.getRuntime().exec("input keyevent " +
                    Integer.toString(KeyEvent.KEYCODE_HEADSETHOOK));
        } catch (IOException e) {
            // Runtime.exec(String) had an I/O problem, try to fall back
            String enforcedPerm = "android.permission.CALL_PRIVILEGED";
            Intent btnDown = new Intent(Intent.ACTION_MEDIA_BUTTON).putExtra(
                    Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN,
                            KeyEvent.KEYCODE_HEADSETHOOK));
            Intent btnUp = new Intent(Intent.ACTION_MEDIA_BUTTON).putExtra(
                    Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP,
                            KeyEvent.KEYCODE_HEADSETHOOK));

            mContext.sendOrderedBroadcast(btnDown, enforcedPerm);
            mContext.sendOrderedBroadcast(btnUp, enforcedPerm);
        }
    }

}).start();

tl; ডা

অ্যান্ড্রয়েড 8.0 ওরিও এবং তার পরে এর জন্য একটি দুর্দান্ত পাবলিক এপিআই রয়েছে।

অ্যান্ড্রয়েড 8.0 ওরিওর আগে কোনও পাবলিক এপিআই নেই। অভ্যন্তরীণ এপিআইগুলি অফ-সীমাবদ্ধ বা কেবল কোনও ডকুমেন্টেশন ছাড়াই। আপনার সাবধানতার সাথে এগিয়ে যাওয়া উচিত।


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

কিছুটা ব্যস্ত ছিল তাই বিলম্ব - এটি বের করার জন্য কিছুটা সময় ব্যয় করার চেষ্টা করবে। তাত্ক্ষণিকভাবে দেখার পরে মনে হচ্ছে কলম্যানেজার হেডসেটমিডিয়া বাটন তৈরি করে। সেখানকার সেশন কলব্যাকটি মিডিয়াসেশনম্যানেজারের কলব্যাকের মাধ্যমে হ্যান্ডেলহাইডসেটহুক (কীভেন্তি) কল করার বিষয়ে যত্ন নেওয়া উচিত। সমস্ত কোড মিলে যাচ্ছে বলে মনে হচ্ছে ... তবে আমি অবাক হই, কেউ কি কীভেন্ট.অ্যাকশন_ডাউন পরীক্ষা করতে চান? (এটি, কেবলমাত্র একবারের আগেই আগুন জ্বালিয়ে দিন A অ্যাকশন_আপ একবারে।)
ভাল্টার জ্যানসন

আসলে, HeadsetMediaButton MediaSession সঙ্গে কাজ করে এবং MediaSessionManager সাথে ইন্টারঅ্যাক্ট না সরাসরি ...
Valter Jansons

4
আপনারা যারা অরিজিনাল পদ্ধতিতে কাজ করে না বলে এমন পরিস্থিতি সন্ধান করতে পেরেছেন (যেমন ললিপপের সমস্যা আছে), আমার কাছে ভাল এবং খারাপ খবর আছে: আমি আমার কোডে ACTION_UP 100% কাজ করতে সক্ষম হয়েছি, একটি সহ সম্পূর্ণ_ডাক। এটি একটি PARTIAL_WAKE_LOCK নিয়ে কাজ করবে না। এটি কেন তা সম্পর্কে কোনও দলিল নেই। আমি যখন আমার পরীক্ষামূলক কোডটি আরও বিস্তৃতভাবে পরীক্ষা করি তখন আমি ভবিষ্যতের উত্তরে এটিকে বিস্তারিত জানাব। খারাপ খবরটি অবশ্যই FULL_WAKE_LOCK অবমূল্যায়ন করা হয়েছে, সুতরাং এটি একটি স্থিরতা যা গুগল এপিআই এ রাখে কেবল ততক্ষণ টিকে থাকবে।
leRobot

4
মূল উত্তর থেকে ধরা অনেক ক্ষেত্রে বলা হয় না। আমি প্রথমে কেবল এক্সিকিউট কল করতে এবং তারপরে ঠিক পরে বোতামটি উপরে কল করা ভাল পেয়েছি।
ওয়ারপজিট

36

সম্পূর্ণ কার্যকর সমাধানটি @ ভ্যালটার স্ট্রডস কোডের উপর ভিত্তি করে।

এটি কাজ করতে, আপনাকে লক স্ক্রিনে একটি (অদৃশ্য) কার্যকলাপ প্রদর্শন করতে হবে যেখানে কোডটি কার্যকর করা হয়।

অ্যান্ড্রয়েড ম্যানিফেস্ট.এক্সএমএল

<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />

<activity android:name="com.mysms.android.lib.activity.AcceptCallActivity"
        android:launchMode="singleTop"
        android:excludeFromRecents="true"
        android:taskAffinity=""
        android:configChanges="orientation|keyboardHidden|screenSize"
        android:theme="@style/Mysms.Invisible">
    </activity>

কল স্বীকার ক্রিয়াকলাপ

package com.mysms.android.lib.activity;

import android.app.Activity;
import android.app.KeyguardManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.os.Build;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.view.KeyEvent;
import android.view.WindowManager;

import org.apache.log4j.Logger;

import java.io.IOException;

public class AcceptCallActivity extends Activity {

     private static Logger logger = Logger.getLogger(AcceptCallActivity.class);

     private static final String MANUFACTURER_HTC = "HTC";

     private KeyguardManager keyguardManager;
     private AudioManager audioManager;
     private CallStateReceiver callStateReceiver;

     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);

         keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
         audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
     }

     @Override
     protected void onResume() {
         super.onResume();

         registerCallStateReceiver();
         updateWindowFlags();
         acceptCall();
     }

     @Override
     protected void onPause() {
         super.onPause();

         if (callStateReceiver != null) {
              unregisterReceiver(callStateReceiver);
              callStateReceiver = null;
         }
     }

     private void registerCallStateReceiver() {
         callStateReceiver = new CallStateReceiver();
         IntentFilter intentFilter = new IntentFilter();
         intentFilter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
         registerReceiver(callStateReceiver, intentFilter);
     }

     private void updateWindowFlags() {
         if (keyguardManager.inKeyguardRestrictedInputMode()) {
              getWindow().addFlags(
                       WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
                                WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON |
                                WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
         } else {
              getWindow().clearFlags(
                       WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
                                WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
                                WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
         }
     }

     private void acceptCall() {

         // for HTC devices we need to broadcast a connected headset
         boolean broadcastConnected = MANUFACTURER_HTC.equalsIgnoreCase(Build.MANUFACTURER)
                  && !audioManager.isWiredHeadsetOn();

         if (broadcastConnected) {
              broadcastHeadsetConnected(false);
         }

         try {
              try {
                  logger.debug("execute input keycode headset hook");
                  Runtime.getRuntime().exec("input keyevent " +
                           Integer.toString(KeyEvent.KEYCODE_HEADSETHOOK));

              } catch (IOException e) {
                  // Runtime.exec(String) had an I/O problem, try to fall back
                  logger.debug("send keycode headset hook intents");
                  String enforcedPerm = "android.permission.CALL_PRIVILEGED";
                  Intent btnDown = new Intent(Intent.ACTION_MEDIA_BUTTON).putExtra(
                           Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN,
                                    KeyEvent.KEYCODE_HEADSETHOOK));
                  Intent btnUp = new Intent(Intent.ACTION_MEDIA_BUTTON).putExtra(
                           Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP,
                                    KeyEvent.KEYCODE_HEADSETHOOK));

                  sendOrderedBroadcast(btnDown, enforcedPerm);
                  sendOrderedBroadcast(btnUp, enforcedPerm);
              }
         } finally {
              if (broadcastConnected) {
                  broadcastHeadsetConnected(false);
              }
         }
     }

     private void broadcastHeadsetConnected(boolean connected) {
         Intent i = new Intent(Intent.ACTION_HEADSET_PLUG);
         i.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
         i.putExtra("state", connected ? 1 : 0);
         i.putExtra("name", "mysms");
         try {
              sendOrderedBroadcast(i, null);
         } catch (Exception e) {
         }
     }

     private class CallStateReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
              finish();
         }
     }
}

স্টাইল

<style name="Mysms.Invisible">
    <item name="android:windowFrame">@null</item>
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:windowNoTitle">true</item>
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowAnimationStyle">@null</item>
</style>

শেষ পর্যন্ত যাদু ডাক!

Intent intent = new Intent(context, AcceptCallActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK
            | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
context.startActivity(intent);

4
যেখানে মাই suppoz "অবশেষে যাদুটিকে কল করুন" এর অধীনে কোড যুক্ত করতে চাই। এটি অ্যান্ড্রয়েড 6.0 এর জন্য কাজ করবে
অক্ষয় শাহ

আমি এখানে এসে বললাম যে ব্রডকাস্টহইডসেট সংযুক্ত (বুলিয়ান সংযুক্ত) স্যামসাং এ 3 2016 ডিভাইসে কোনও সমস্যার সমাধান করেছে। তা ছাড়া, একটি খুব অনুরূপ পদ্ধতি (পৃথক, স্বচ্ছ ক্রিয়াকলাপ এবং ইনভোকস এবং হোয়াট নোটের জন্য থ্রেড ব্যবহার করে) প্রায় 20 টি পরীক্ষিত ডিভাইসের জন্য পুরোপুরি কাজ করছে, তখন এই A3 এসেছিল এবং আমাকে নতুন উত্তরগুলির জন্য এই প্রশ্নটি পুনরায় পরীক্ষা করতে বাধ্য করেছে। আমার কোডের সাথে তুলনা করার পরে, তা ছিল গুরুত্বপূর্ণ পার্থক্য!
leRobot

4
আমি কীভাবে কোনও কল প্রত্যাখ্যান করতে পারি? আপনি কি এটি দেখানোর জন্য উত্তর আপডেট করতে পারেন?
আমননি

@ লেআরবোট এই উত্তরটি দেখুন যে এটি সম্প্রচারের জন্য এইচটিসি ডিভাইস কিনা হাইডসেট সংযুক্ত, আপনি কীভাবে এটি পরীক্ষা করতে পারেন যে এটি স্যামসাং এ 3 2016 ডিভাইস কিনা? যাইহোক, এটি সত্যিই একটি ভাল উত্তর, আমার অ্যাপ্লিকেশনটি ফোন কলটি এমনকি স্ক্রীনটিকে লক করা থাকলেও উত্তর দিতে পারে।
eepty

@ ডিপ্টি আপনি বিল্ড ডেটার জন্য অফিসিয়াল ডিভাইস রেফারেন্স ব্যবহার করতে পারেন। ( সমর্থন . google.com/googleplay/answer/1727131?hl=en )। আমি এ 3, 2016 এর জন্য বিল্ড.মোডেল.স্টার্টস ("এসএম-এ 310") ব্যবহার করি B তবে! আমি নিশ্চিত করতে পারি A3 2016 সংযুক্ত সম্প্রচারকে হেডসেট সমর্থন করে না! আমার সমস্যার সমাধানটি হ'ল অর্ডারটি পরিবর্তন করা হয়েছিল যাতে রানটাইম.জেটআরটাইম ()। এক্সিকিউট (... এই ডিভাইসগুলির জন্য প্রথমে ট্রিগার করে। মনে হয় that ডিভাইসটির জন্য এটি প্রতিবার কাজ করে এবং ব্যতিক্রমে ফিরে আসে না
লেরোবোট

14

নিম্নলিখিতটি আমার জন্য কাজ করেছে এমন একটি বিকল্প পদ্ধতি is এটি সরাসরি মিডিয়া কনট্রোলার এপিআই ব্যবহার করে মূল ইভেন্টটি টেলিকম সার্ভারে প্রেরণ করে। এর জন্য অ্যাপ্লিকেশনটির BIND_NOTIFICATION_LISTENER_SERVICE অনুমতি রয়েছে এবং এটি ব্যবহারকারীর কাছ থেকে বিজ্ঞপ্তি অ্যাক্সেসের স্পষ্ট অনুদান দেওয়া দরকার:

@TargetApi(Build.VERSION_CODES.LOLLIPOP) 
void sendHeadsetHookLollipop() {
    MediaSessionManager mediaSessionManager =  (MediaSessionManager) getApplicationContext().getSystemService(Context.MEDIA_SESSION_SERVICE);

    try {
        List<MediaController> mediaControllerList = mediaSessionManager.getActiveSessions 
                     (new ComponentName(getApplicationContext(), NotificationReceiverService.class));

        for (MediaController m : mediaControllerList) {
             if ("com.android.server.telecom".equals(m.getPackageName())) {
                 m.dispatchMediaButtonEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK));
                 log.info("HEADSETHOOK sent to telecom server");
                 break;
             }
        }
    } catch (SecurityException e) {
        log.error("Permission error. Access to notification not granted to the app.");      
    }  
}

NotificationReceiverService.class উপরের কোডটি কেবল একটি খালি শ্রেণি হতে পারে।

import android.service.notification.NotificationListenerService;

public class NotificationReceiverService extends NotificationListenerService{
     public NotificationReceiverService() {
     }
}

ম্যানিফেস্টে সংশ্লিষ্ট বিভাগের সাথে:

    <service android:name=".NotificationReceiverService" android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
        android:enabled="true" android:exported="true">
    <intent-filter>
         <action android:name="android.service.notification.NotificationListenerService" />
    </intent-filter>

যেহেতু ইভেন্টটির লক্ষ্য স্পষ্ট তাই এটি সম্ভবত মিডিয়া প্লেয়ারকে ট্রিগার করার কোনও পার্শ্ব প্রতিক্রিয়া এড়ানো উচিত।

দ্রষ্টব্য: টেলিকম সার্ভারটি বেজে উঠার পরে তত্ক্ষণাত্ সক্রিয় হবে না। এটি নির্ভরযোগ্যভাবে কাজ করার জন্য , টেলিকম সার্ভারটি সক্রিয় হওয়ার আগে, ইভেন্টটি প্রেরণের আগে পর্যবেক্ষণ করতে মিডিয়াসেশনম্যানেজার.অনএ্যাকটিভসেশনস চেঞ্জডলাইজনার প্রয়োগ করা অ্যাপের পক্ষে কার্যকর হতে পারে ।

হালনাগাদ:

ইন অ্যান্ড্রয়েড হে , অনুকরণ এক প্রয়োজন ACTION_DOWNআগে ACTION_UP, অন্যথায় উপরে কোনো প্রভাব নেই। অর্থাত নীচের প্রয়োজন:

m.dispatchMediaButtonEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK));
m.dispatchMediaButtonEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK));

তবে যেহেতু অ্যান্ড্রয়েড ও (শীর্ষ উত্তর দেখুন) এর পরে কল করার জন্য একটি আনুষ্ঠানিক কল উপলব্ধ রয়েছে, অ্যান্ড্রয়েড ও এর আগে কোনও পুরানো সংকলন API স্তরের সাথে আটকে না থাকলে এই হ্যাকের আর প্রয়োজন হবে না unless


এটা আমার জন্য কাজ করে নি। এটি অনুমতি ত্রুটি ফিরিয়ে দিয়েছে। অ্যাপ্লিকেশনটিতে অনুমোদিত নোটিফিকেশন অ্যাক্সেস। আমি অ্যান্ড্রয়েড এল
জামে

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

এটি রিপোর্ট করা সংকীর্ণ ক্ষেত্রে কাজ করছে বলে মনে হচ্ছে: মার্শমেলো সহ গ্যালাক্সি এ 3 2016। আমি এ টি ডিভাইসের একটি গ্রুপে এটি পরীক্ষা করব যা একটি চূড়ান্ত ব্যতিক্রমের কারণে ইনপুট কীভেন্ট পদ্ধতির সাথে কাজ করে না: জাভা.এল্যাং.সিকিউরিটি এক্সসেপশন: অন্য অ্যাপ্লিকেশনটিতে ইনজেকশনের জন্য INJECT_EVENTS অনুমতি প্রয়োজন। অফার করা ডিভাইসগুলি আমার ব্যবহারকারী-বেসের প্রায় 2% এবং আমি তাদের ব্যতিক্রমগুলি প্রতিলিপি করছি না, তবে তারা কলটি পরিচালনা করতে পরিচালিত করে কিনা তা দেখার জন্য এই পদ্ধতির চেষ্টা করব। ভাগ্যক্রমে আমার অ্যাপ্লিকেশনটি ইতিমধ্যে সুস্পষ্ট নোটিফটির জন্য অনুরোধ করছে। অন্যান্য উদ্দেশ্যে অ্যাক্সেস।
leRobot

বিস্তৃত পরীক্ষার পরে, আমি জানাতে পেরে আনন্দিত যে এ 3 ২০১ devices ডিভাইসগুলি যে এক্সিকিউটিভ "ইনপুট কেয়েভেন্ট" এর সাথে ব্যর্থ হয়েছিল মিডিয়া কনট্রোলার # ডিসপ্যাচমিডিয়াবাটন এভেন্ট (<হুক কেরিভেন্ট>)) পদ্ধতিতে কাজ করতে সক্ষম হয়েছিল। এটি সুস্পষ্টভাবে কেবলমাত্র তখনই কাজ করে যখন ব্যবহারকারী সুস্পষ্ট বিজ্ঞপ্তি অ্যাক্সেসের অনুমতি দেয়, সুতরাং আপনাকে তার জন্য অ্যান্ড্রয়েড সেটিংসে নির্দেশিত একটি স্ক্রিন যুক্ত করতে হবে এবং উত্তরে বর্ণিত হিসাবে আপনাকে মূলত এর জন্য অতিরিক্ত পদক্ষেপ নেওয়া উচিত take আমার অ্যাপ্লিকেশনটিতে আমরা ব্যবহারকারী জিজ্ঞাসা রাখতে অতিরিক্ত পদক্ষেপ নিয়েছি যদি ব্যবহারকারী সেই স্ক্রিনে যায় তবে বিজ্ঞপ্তি যোগ করে না। অ্যাক্সেস
leRobot

এটি অ্যান্ড্রয়েড নওগাটে কাজ করে। @ নটজ এর সমাধানটি অন্যথায় দুর্দান্ত কাজ করে তবে অভিযোগ করে যে "অ্যান্ড্রয়েড on এ" কেবলমাত্র মিডিয়া মূল ইভেন্টটি বিশ্ব অগ্রাধিকার সেশনে প্রেরণ করতে পারে "
পিবি

9

@ মুজিকান্তের উত্তরের উপর একটি ছোট্ট বিটটি বিস্তারিতভাবে বর্ণনা করতে এবং আমার ডিভাইসে কিছুটা পরিষ্কার পরিচ্ছন্ন করার জন্য এটিকে কিছুটা সংশোধন করতে, চেষ্টা করুন KeyEvent.KEYCODE_HEADSETHOOK এরinput keyevent 79 জন্য ধ্রুবক । খুব মোটামুটি:

    new Thread(new Runnable() {

        @Override
        public void run() {

            try {

                Runtime.getRuntime().exec( "input keyevent " + KeyEvent.KEYCODE_HEADSETHOOK );
            }
            catch (Throwable t) {

                // do something proper here.
            }
        }
    }).start();

মোটামুটি খারাপ কোডিং কনভেনশনগুলি ক্ষমা করুন, আমি রানটাইম.এক্সেক () কলগুলিতে খুব বেশি পারদর্শী নই। নোট করুন যে আমার ডিভাইসটি মূল নয়, না আমি রুট সুবিধার জন্য অনুরোধ করছি।

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

সুতরাং আমার নেক্সাস 5 এ এটি ব্যবহারকারী-পরিচালিত উত্তরের জন্য ভাল কাজ করে এবং একটি কাস্টম কল স্ক্রিনের উদ্দেশ্য অনুসারে করা উচিত। এটি কেবল কোনও ধরণের স্বয়ংক্রিয় কল-নিয়ন্ত্রণ-ধরণের অ্যাপ্লিকেশনের জন্য কাজ করবে না।

লক্ষণীয় বিষয় হ'ল সমস্ত সম্ভাব্য সতর্কতা, এটি সহ খুব সম্ভবত একটি বা দুটি আপডেটে কাজ বন্ধ করে দেওয়া হবে।


input keyevent 79সনি এক্স্পেরিয়া 5.0 এ সূক্ষ্মভাবে কাজ করে। কোনও ক্রিয়াকলাপ বা সম্প্রচারিত রিসিভারের কাছ থেকে কল করার সময় কাজ করে।
নিকোলাস

0

অ্যাডবি কমান্ডের মাধ্যমে কীভাবে অ্যাডবি দ্বারা কল তুলবেন

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


0

ধন্যবাদ @ নোটজ এর উত্তর আমার পক্ষে ললিপ্পে কাজ করছে। পুরানো অ্যান্ড্রয়েড এসডিকে নিয়ে এই কোডটি কাজ করার জন্য, আপনি এই কোডটি করতে পারেন:

if (Build.VERSION.SDK_INT >= 21) {  
    Intent answerCalintent = new Intent(context, AcceptCallActivity.class);  
    answerCalintent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | 
                             Intent.FLAG_ACTIVITY_CLEAR_TASK  | 
                             Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
    context.startActivity(answerCalintent);  
}  
else {  
  if (telephonyService != null) {  
    try {  
        telephonyService.answerRingingCall();  
    }  
    catch (Exception e) {  
        answerPhoneHeadsethook();  
    }  
  }  
}  

0

কলগুলির স্বয়ংক্রিয়ভাবে উত্তর দেওয়ার পরে কীভাবে স্পিকার ফোনটি চালু করবেন।

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

এটি রুট ছাড়াই আমার নেক্সাস 4 এ অ্যান্ড্রয়েড 5.1.1 এ কাজ করে। ;)

অনুমতি প্রয়োজন:

<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>

জাভা কোড:

// this means the phone has answered
if(state==TelephonyManager.CALL_STATE_OFFHOOK)
{
    // try and turn on speaker phone
    final Handler mHandler = new Handler();
    mHandler.postDelayed(new Runnable() {
        @Override
        public void run() {
            AudioManager audioManager = (AudioManager) localContext.getSystemService(Context.AUDIO_SERVICE);

            // this doesnt work without android.permission.MODIFY_PHONE_STATE
            // audioManager.setMode(AudioManager.MODE_IN_CALL);

            // weirdly this works
            audioManager.setMode(AudioManager.MODE_NORMAL); // this is important
            audioManager.setSpeakerphoneOn(true);

            // note the phone interface won't show speaker phone is enabled
            // but the phone speaker will be on
            // remember to turn it back off when your done ;)
        }
    }, 500); // half a second delay is important or it might fail
}

4
মজাদার. আমি আসলে কলটির উত্তর দেওয়ার চেষ্টা করছি এবং এক সাথে স্পিকার চালু করার চেষ্টা করছি যাতে এই পদ্ধতির উভয়ই সমাধান হয় :) অন্যান্য উত্তরের মন্তব্যগুলির মতো আমারও একই প্রশ্ন রয়েছে: এই কোডটি কোথায় যায়?
ফ্যাংমোবাইল

-1

নিম্নলিখিত কমান্ডটি রুট হিসাবে চালান:

input keyevent 5

এখানে কীভেন্টস অনুকরণের বিষয়ে আরও বিশদ ।

আপনার অ্যাপ থেকে রুট হিসাবে কমান্ড চালাতে আমি তৈরি করা এই বেস ক্লাসটি ব্যবহার করতে পারেন ।


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

-2

এটি পরীক্ষা করুন: প্রথমে অনুমতিগুলি যুক্ত করুন তারপরে কলটির উত্তর দেওয়ার জন্য হ্যাংআপে হিটআপে কিলক্যাল () ব্যবহার করুন)

<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"></uses-permission>


public void killCall() {
    try {
        TelephonyManager telephonyManager =
                (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);

        Class classTelephony = Class.forName(telephonyManager.getClass().getName());
        Method methodGetITelephony = classTelephony.getDeclaredMethod("getITelephony");

        methodGetITelephony.setAccessible(true);

        Object telephonyInterface = methodGetITelephony.invoke(telephonyManager);

        Class telephonyInterfaceClass =
                Class.forName(telephonyInterface.getClass().getName());
        Method methodEndCall = telephonyInterfaceClass.getDeclaredMethod("endCall");

        methodEndCall.invoke(telephonyInterface);

    } catch (Exception ex) {
        Log.d(TAG, "PhoneStateReceiver **" + ex.toString());
    }
}

public void answerCall() {
    try {
        Runtime.getRuntime().exec("input keyevent " +
                Integer.toString(KeyEvent.KEYCODE_HEADSETHOOK));

    } catch (IOException e) {
        answerRingingCallWithIntent();
    }
}

public void answerRingingCallWithIntent() {
    try {
        Intent localIntent1 = new Intent(Intent.ACTION_HEADSET_PLUG);
        localIntent1.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
        localIntent1.putExtra("state", 1);
        localIntent1.putExtra("microphone", 1);
        localIntent1.putExtra("name", "Headset");
        getContext().sendOrderedBroadcast(localIntent1, "android.permission.CALL_PRIVILEGED");

        Intent localIntent2 = new Intent(Intent.ACTION_MEDIA_BUTTON);
        KeyEvent localKeyEvent1 = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK);
        localIntent2.putExtra(Intent.EXTRA_KEY_EVENT, localKeyEvent1);
        getContext().sendOrderedBroadcast(localIntent2, "android.permission.CALL_PRIVILEGED");

        Intent localIntent3 = new Intent(Intent.ACTION_MEDIA_BUTTON);
        KeyEvent localKeyEvent2 = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK);
        localIntent3.putExtra(Intent.EXTRA_KEY_EVENT, localKeyEvent2);
        getContext().sendOrderedBroadcast(localIntent3, "android.permission.CALL_PRIVILEGED");

        Intent localIntent4 = new Intent(Intent.ACTION_HEADSET_PLUG);
        localIntent4.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
        localIntent4.putExtra("state", 0);
        localIntent4.putExtra("microphone", 1);
        localIntent4.putExtra("name", "Headset");
        getContext().sendOrderedBroadcast(localIntent4, "android.permission.CALL_PRIVILEGED");
    } catch (Exception e2) {
        e2.printStackTrace();
    }
}

-2

এফওয়াইআই যদি আপনি কীভাবে অ্যান্ড্রয়েড ও-তে চলমান কলটি শেষ করতে আগ্রহী, ভল্টারের Method 1: TelephonyManager.answerRingingCall()কাজ আপনি যদি অনুরোধের পদ্ধতিটি পরিবর্তন করেন তবে endCall

এটির জন্য কেবল android.permission.CALL_PHONEঅনুমতি প্রয়োজন ।

কোডটি এখানে:

// set the logging tag constant; you probably want to change this
final String LOG_TAG = "TelephonyAnswer";

public void endCall() {
    TelephonyManager tm = (TelephonyManager) mContext
            .getSystemService(Context.TELEPHONY_SERVICE);

    try {
        if (tm == null) {
            // this will be easier for debugging later on
            throw new NullPointerException("tm == null");
        }

        // do reflection magic
        tm.getClass().getMethod("endCall").invoke(tm);
    } catch (Exception e) {
        // we catch it all as the following things could happen:
        // NoSuchMethodException, if the answerRingingCall() is missing
        // SecurityException, if the security manager is not happy
        // IllegalAccessException, if the method is not accessible
        // IllegalArgumentException, if the method expected other arguments
        // InvocationTargetException, if the method threw itself
        // NullPointerException, if something was a null value along the way
        // ExceptionInInitializerError, if initialization failed
        // something more crazy, if anything else breaks

        // TODO decide how to handle this state
        // you probably want to set some failure state/go to fallback
        Log.e(LOG_TAG, "Unable to use the Telephony Manager directly.", e);
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.