How do I change the phone call user interface? Like I have my own dialer layout and contacts layout but how do I change the calling UI. So, when the call is going on, can I remove the speaker button for example?
Here is my dialer scene that I have created: Dialer Picture
But I don't know how to edit this screen: Calling Picture
EDIT: I have already built the UI, I just can not get it to show during call!
Here is the code for as a simpler version:
public class MainActivity extends Activity {
private Button callBtn;
private Button dialBtn;
private EditText number;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
number = (EditText) findViewById(R.id.phoneNumber);
callBtn = (Button) findViewById(R.id.call);
dialBtn = (Button) findViewById(R.id.dial);
// add PhoneStateListener for monitoring
MyPhoneListener phoneListener = new MyPhoneListener();
TelephonyManager telephonyManager =
(TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
// receive notifications of telephony state changes
telephonyManager.listen(phoneListener,PhoneStateListener.LISTEN_CALL_STATE);
callBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
try {
// set the data
String uri = "tel:"+number.getText().toString();
Intent callIntent = new Intent(Intent.ACTION_CALL, Uri.parse(uri));
startActivity(callIntent);
}catch(Exception e) {
Toast.makeText(getApplicationContext(),"Your call has failed...",
Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
});
dialBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
try {
String uri = "tel:"+number.getText().toString();
Intent dialIntent = new Intent(Intent.ACTION_DIAL, Uri.parse(uri));
startActivity(dialIntent);
}catch(Exception e) {
Toast.makeText(getApplicationContext(),"Your call has failed...",
Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
});
}
private class MyPhoneListener extends PhoneStateListener {
private boolean onCall = false;
#Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
// phone ringing...
Toast.makeText(MainActivity.this, incomingNumber + " calls you",
Toast.LENGTH_LONG).show();
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
// one call exists that is dialing, active, or on hold
Toast.makeText(MainActivity.this, "on call...",
Toast.LENGTH_LONG).show();
//because user answers the incoming call
onCall = true;
break;
case TelephonyManager.CALL_STATE_IDLE:
// in initialization of the class and at the end of phone call
// detect flag from CALL_STATE_OFFHOOK
if (onCall == true) {
Toast.makeText(MainActivity.this, "restart app after call",
Toast.LENGTH_LONG).show();
// restart our application
Intent restart = getBaseContext().getPackageManager().
getLaunchIntentForPackage(getBaseContext().getPackageName());
restart.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(restart);
onCall = false;
}
break;
default:
break;
}
}
}
}
Thanks!
Add calling permission in manifest
<uses-permission android:name="android.permission.CALL_PHONE" />
Then need to check if call button pressed. for that use below intent filter
<intent-filter>
<action android:name="android.intent.action.CALL_BUTTON" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
and when firing the UI
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.DIAL" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="tel" />
</intent-filter>
that means your calling activity in manifest will be something like this
<activity
android:name="com.example.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<!-- open activity when establishing a call -->
<intent-filter>
<action android:name="android.intent.action.CALL_PRIVILEGED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="tel" />
</intent-filter>
</activity>
since API 23 it is possible, see Replacing default Phone app on Android 6 and 7 with InCallService arekolek.
Kotlin version: Simple Phone
Java version: Simple Phone Dialer
EDIT
As recommended, Below is the simplest java version.
Below is shown the Manifest with the intent-filter needed.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.aliton.customphonecall">
<uses-permission android:name="android.permission.CALL_PHONE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".DialerActivity" >
<intent-filter>
<!-- Handle links from other applications -->
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.DIAL" />
<!-- Populate the system chooser -->
<category android:name="android.intent.category.DEFAULT" />
<!-- Handle links in browsers -->
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="tel" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.DIAL" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<service
android:name=".CallService"
android:permission="android.permission.BIND_INCALL_SERVICE">
<meta-data
android:name="android.telecom.IN_CALL_SERVICE_UI"
android:value="true" />
<intent-filter>
<action android:name="android.telecom.InCallService" />
</intent-filter>
</service>
<activity android:name=".CallActivity"></activity>
</application>
</manifest>
The MainActivity just have a Button with an Intent redirecting to the DialerActivity.
Below is the DialerActivity. In this Activity, you will set your app as default in order to make call with your UI.
public class DialerActivity extends AppCompatActivity {
private static final int REQUEST_CALL_PHONE = 10;
EditText phoneNumber;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dialer);
phoneNumber = (EditText) findViewById(R.id.etNumber);
Button bCall = (Button) findViewById(R.id.btnCall);
offerReplacingDefaultDialer();
bCall.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
makeCall();
}
});
}
private void makeCall() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) == PackageManager.PERMISSION_GRANTED) {
Uri uri = Uri.parse("tel:"+phoneNumber.getText().toString().trim());
Intent Call = new Intent(Intent.ACTION_CALL, uri);
//Toast.makeText(this, "Entered makeCall()", Toast.LENGTH_SHORT).show();
Log.i("debinf Dialer", "Entered makeCall()");
startActivity(Call);
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CALL_PHONE}, REQUEST_CALL_PHONE);
}
}
private void offerReplacingDefaultDialer() {
if (getSystemService(TelecomManager.class).getDefaultDialerPackage() != getPackageName()) {
Intent ChangeDialer = new Intent(TelecomManager.ACTION_CHANGE_DEFAULT_DIALER);
ChangeDialer.putExtra(TelecomManager.EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME, getPackageName());
startActivity(ChangeDialer);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_CALL_PHONE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
makeCall();
} else {
Toast.makeText(this, "calling permission denied", Toast.LENGTH_LONG).show();
}
//return;
}
}
}
Here is how InCallService is implemented to manage the calls.
public class CallService extends InCallService {
OngoingCallObject ongoingCallObject;
#Override
public void onCallAdded(Call call) {
super.onCallAdded(call);
new OngoingCallObject().setCall(call);
//Intent CallAct = new Intent(this, CallActivity.class);
//startActivity(CallAct);
CallActivity.start(this, call);
}
#Override
public void onCallRemoved(Call call) {
super.onCallRemoved(call);
new OngoingCallObject().setCall(null);
}
}
Here is how the Object is implemented.
public class OngoingCallObject {
private static Call call;
private Object callback = new Callback() {
#Override
public void onStateChanged(Call call, int state) {
super.onStateChanged(call, state);
Log.i("debinf OngoingObj", "state is "+state);
}
};
public void setCall(Call call) {
if (this.call != null) {
this.call.unregisterCallback((Call.Callback)callback);
}
if (call != null) {
call.registerCallback((Call.Callback)callback);
Log.i("debinf OngoingObj", "call.getState() is "+call.getState());
}
this.call = call;
}
public void answer() {
//assert this.call != null;
if (this.call != null) {
this.call.answer(VideoProfile.STATE_AUDIO_ONLY);
}
}
public void hangup() {
//assert this.call != null;
if (this.call != null) {
this.call.disconnect();
}
}
}
And finally, the CallActivity where you launch your UI.
public class CallActivity extends AppCompatActivity {
TextView callInfo;
Button answer, hangup;
private String number;
private OngoingCallObject ongoingCall;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_call);
ongoingCall = new OngoingCallObject();
answer = (Button) findViewById(R.id.answer);
hangup = (Button) findViewById(R.id.hangup);
callInfo = (TextView) findViewById(R.id.callInfo);
number = Objects.requireNonNull(getIntent().getData().getSchemeSpecificPart());
callInfo.setText("Calling number : "+number);
answer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Toast.makeText(CallActivity.this, "Answer button", Toast.LENGTH_SHORT).show();
ongoingCall.answer();
}
});
hangup.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ongoingCall.hangup();
}
});
}
public static void start(Context context, Call call) {
Intent intent = new Intent(context, CallActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setData(call.getDetails().getHandle());
context.startActivity(intent);
}
}
Here is the xml for DialerActivity: activity_dialer.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DialerActivity">
<EditText
android:id="#+id/etNumber"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Tel number"/>
<Button
android:id="#+id/btnCall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="CallActivity"
android:layout_below="#+id/etNumber" />
</RelativeLayout>
Here is the xml for CallActivity: activity_call.xml
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".CallActivity">
<TextView
android:id="#+id/callInfo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.3"
tools:text="Hello World!" />
<Button
android:id="#+id/answer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Answer"
app:layout_constraintBaseline_toBaselineOf="#+id/hangup"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/hangup" />
<Button
android:id="#+id/hangup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hang up"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/answer"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/callInfo" />
</android.support.constraint.ConstraintLayout>
I hope it helps!
EDIT:
Actually the api 23 was release, check this answer. Keep in mind that some devices may not support this functionality.
PREVIEW:
The actual calling view (what you see during calls) CAN`T be changed.
To be more specific, some parts of android CAN NOT be overridden,
android has his core and as developers we have limited access to this
core. In your case you can override dialer but you can`t
override actual phone call view.
You can't do anything about this, until android team decided to share
this core feature with us (developers).
Build your own Dialer UI. Check this out.
You will need an Activity to handle the intent and then displaying a custom UI is your business.
Related
I can't find my mistakes......
while studying social login(google, facebook), almost don't know what to do...
I tried my best, but couldn't find errors.
When I connect my android devices and run on them, my devices get jammed.
So I should force terminate my app.
here is my code
androidmanifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.acepeter.smartcalendar">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.AppCompat.Light.NoActionBar"
tools:replace="android:supportsRtl">
<activity android:name=".SignupActivity"/>
<activity android:name=".MainActivity"/>
<activity android:name=".SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".BaseActivity" />
<meta-data
android:name="com.facebook.sdk.ApplicationId"
android:value="#string/facebook_app_id"
tools:replace="android:value" />
<activity
android:name="com.facebook.FacebookActivity"
android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
android:label="#string/app_name" />
<activity
android:name="com.facebook.CustomTabActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="#string/fb_login_protocol_scheme" />
</intent-filter>
</activity>
<activity android:name=".LoginActivity"
android:windowSoftInputMode="stateHidden|adjustResize">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="#string/fb_login_protocol_scheme" />
</intent-filter>
</activity>
</application>
</manifest>
splashactivity.java
public class SplashActivity extends AppCompatActivity {
/*
앱이 맨처음 실행하면 띄어지는 로딩 화면
앱에서 필요한 네트워크 연결, 데이터베이스 연결
설정 값 적용 등의 앱에서 처음에 해야할 기능을 수행하기 위한 화면
앱 또는 서버 점검 알림창을 띄우는 화면
Remote Config(원격 구성)
서버에서 앱의 대한 설정을 해줄 수 있습니다.
설정 : 사용자가 사용하는 설정이 아닌 앱 관리자가 모든 앱의 설정을
관리하기 위한 기능
*/
FirebaseRemoteConfig remoteConfig;
LinearLayout container;
// #Override
// protected void onCreate(Bundle savedInstanceState) {
// super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_logo);
// startLoading();
// mAuth = FirebaseAuth.getInstance();
// }
// private void startLoading() {
// Handler handler = new Handler();
// handler.postDelayed(new Runnable() {
// #Override
// public void run() {
// finish();
// }
// }, 2000);
//}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_logo);
container = findViewById(R.id.splash_layout_container);
// 전체 화면
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
startLoading();
remoteConfig = FirebaseRemoteConfig.getInstance();
FirebaseRemoteConfigSettings configSettings = new FirebaseRemoteConfigSettings.Builder()
.setMinimumFetchIntervalInSeconds(100)
.build();
remoteConfig.setConfigSettingsAsync(configSettings);
remoteConfig.setDefaultsAsync(R.xml.remote_config_defaults);
remoteConfig.fetchAndActivate()
.addOnCompleteListener(new OnCompleteListener<Boolean>() {
#Override
public void onComplete(#NonNull Task<Boolean> task) {
if (task.isSuccessful()) {
Log.i("RemoteConfig", "Remote Success");
} else {
Log.i("RemoteConfig", "Remote Failed");
}
displayMessage();
}
});
}
private void displayMessage() {
// 서버에 저장된 설정 값을 가져오도록 함.
String background = remoteConfig.getString(getString(R.string.theme_color));
boolean caps = remoteConfig.getBoolean("splash_message_caps");
String message = remoteConfig.getString("splash_message");
container.setBackgroundColor(Color.parseColor(background));
if(caps) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(message)
.setPositiveButton("확인", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
builder.create().show();
}else {
// 다음 화면으로 넘어감
Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
startActivity(intent);
finish();
}
}
private void startLoading() {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
finish();
}
}, 2000);
}
}
So I am authenticating the user via GitHub account using OAuth from browser. But after I fire the Intent from LoginActivity, the onResume() gets executed before the user opens the browser, thus returning the value of uri equals null.
Here is the LoginActivity:
public class LoginActivity extends AppCompatActivity {
Button loginButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
loginButton = findViewById(R.id.button);
final String url = "oauth url...";
Log.d("called","oncreate");
loginButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("called","onclick");
attemptLogin(url);
}
});
}
private void attemptLogin(String url){
Log.d("called","onattempt");
Intent intent = new Intent(this, BrowserActivity.class);
intent.putExtra("URL", url);
startActivityForResult(intent, 1);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Uri uri = data.getData();
String code = uri.getQueryParameter("code");
Log.d("called",code);
}
}
BrowserActivity:
public class BrowserActivity extends AppCompatActivity {
public static String CALLBACK_URL = "callback url..";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_browser);
Intent intent = getIntent();
if(intent != null){
String url = intent.getStringExtra("URL");
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(i);
}
}
#Override
protected void onResume() {
super.onResume();
Uri uri = getIntent().getData();
if(uri != null && uri.toString().startsWith(CALLBACK_URL)) {
String code = uri.getQueryParameter("code");
Intent intent = new Intent();
intent.putExtra("code",code);
setResult(RESULT_OK, intent);
finish();
}
}
}
LoginActivity in AndroidManifest.xml:
<activity
android:name=".ui.activities.LoginActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ui.activities.BrowserActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data
android:host="callback"
android:scheme="app"
/>
</intent-filter>
</activity>
First, you start the browser with
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivityForResult(intent, 1);
this intent does not return any result. It only request the browser to show the url. So the browser does not returning any result.
However, after authentification, the browser trigger an intent and request for a new instance of LoginActivity. onCreate() is called of course
It is like LoginActivity(#1) -> Browser -> LoginActivity(#2)
you can call this portion of code inside onCreate() it will work:
Uri uri = getIntent().getData();
String code = uri.getQueryParameter("code");
Log.d("called",code);
But two different intents(launcher and action_view) can reach the same activity for two different purposes. You'd better create two different activities. First your usual LoginActivity and a second one (which inherit from the first) BrowserActivity wich redifine onCreate. So far, your Manifest will look like
<activity
android:name=".ui.activities.LoginActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ui.activities.BrowserActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data
android:host="callback"
android:scheme="app"
/>
</intent-filter>
</activity>
The LoginActivity code should look like this:
public class LoginActivity extends AppCompatActivity {
Button loginButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
loginButton = findViewById(R.id.button);
final String url = "oauth url...";
Log.d("called","oncreate");
loginButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("called","onclick");
attemptLogin(url);
}
});
}
private void attemptLogin(String url){
Log.d("called","onattempt");
// open the browser with url
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(i);
}
// no onResult
}
And this is the BrowserActivityCode:
public class BrowserActivity extends LoginActivity {
// this will be triggered after authentification
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
processIntent();
}
protected void processIntent() {
Intent intentFromBrowser = getIntent();
if (intentFromBrowser != null) {
Uri uri = intentFromBrowser.getData();
if(uri != null && uri.toString().startsWith(CALLBACK_URL)) {
String code = uri.getQueryParameter("code");
Log.d("code value", code);
}
}
}
}
I have an earphone, headset. It, vertically, has the buttons, increase volume, middle button, lower volume.
By pressing the middle button, it opens the spotify and plays music, even with the screen off or the phone locked.
I would like to do this for an application of mine, when press this middle button, this application trigger an event, is it possible? Or, press one of the volume buttons and trigger an event.
It is possible? If yes, is there any example, source code, with this application?
EDIT:
The code did not work:
Main:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IntentFilter filtro = new IntentFilter(Intent.ACTION_MEDIA_BUTTON);//"android.intent.action.MEDIA_BUTTON"
MediaButtonIntentReceiver r = new MediaButtonIntentReceiver();
filtro.setPriority(1000); //this line sets receiver priority
registerReceiver(r, filtro);
}
}
Broadcast:
public class MediaButtonIntentReceiver extends BroadcastReceiver {
public MediaButtonIntentReceiver() {
super();
}
#Override
public void onReceive(Context context, Intent intent) {
String intentAction = intent.getAction();
if (!Intent.ACTION_MEDIA_BUTTON.equals(intentAction)) {
return;
}
KeyEvent event = (KeyEvent) intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
if (event == null) {
return;
}
int action = event.getAction();
if (action == KeyEvent.ACTION_DOWN) {
toDo();
Toast.makeText(context, "BUTTON PRESSED!", Toast.LENGTH_SHORT).show();
}
abortBroadcast();
}
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.aula.bob.headset">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".MediaButtonIntentReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
</application>
</manifest>
Create a class extending Broadcast Receiver in your App:
public class MediaButtonIntentReceiver extends BroadcastReceiver {
public MediaButtonIntentReceiver() {
super();
}
#Override
public void onReceive(Context context, Intent intent) {
String intentAction = intent.getAction();
if (!Intent.ACTION_MEDIA_BUTTON.equals(intentAction)) {
return;
}
KeyEvent event = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
if (event == null) {
return;
}
int action = event.getAction();
if (action == KeyEvent.ACTION_DOWN) {
// do something
Toast.makeText(context, "BUTTON PRESSED!", Toast.LENGTH_SHORT).show();
}
abortBroadcast();
}
}
And in your Activity Class:
public class MainActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
IntentFilter filter = new IntentFilter(Intent.ACTION_MEDIA_BUTTON);//"android.intent.action.MEDIA_BUTTON"
MediaButtonIntentReceiver r = new MediaButtonIntentReceiver();
filter.setPriority(10000); //this line sets receiver priority
registerReceiver(r, filter);
}
}
Define your Receiver in Android Manifest like this:
<receiver android:name=".MediaButtonIntentReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
Hope it will work for you!
I am setting two buttons on the screen. Whenever I press the first button it will disable the camera. ( as an admin )
I have set manifest ;
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.firstapplication.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- This is where we register our receiver -->
<receiver
android:name=".DemoDeviceAdminReceiver"
android:permission="android.permission.BIND_DEVICE_ADMIN" >
<intent-filter>
<!-- This action is required -->
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
<!-- This is required this receiver to become device admin component. -->
<meta-data
android:name="android.app.device_admin"
android:resource="#xml/device_admin_sample" />
</receiver>
</application>
I have wrote code as ;
public class MainActivity extends Activity {
static final int ACTIVATION_REQUEST = 47; // identifies our request id
DevicePolicyManager devicePolicyManager;
ComponentName demoDeviceAdmin;
#Override
protected void onCreate(Bundle savedInstanceState) {
// ...
// Initialize Device Policy Manager service and our receiver class
devicePolicyManager = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
demoDeviceAdmin = new ComponentName(this, DemoDeviceAdminReceiver.class);
}
/* begin, camera management block */
static boolean click = false ;
private OnClickListener setCamera = new OnClickListener() {
public void onClick(View v) {
if ( click == false ) {
startCamera();
click = true ;
}
else {
stopCamera();
click = false ;
}
activate () ; // activate device policy manager
}
};
private void startCamera(){
if(getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
camera.unlock();
} else {
;
}
}
#SuppressLint("NewApi") private void stopCamera(){
devicePolicyManager. setCameraDisabled(demoDeviceAdmin, true);
}
/* end, camera management block */
private OnClickListener closeApplication = new OnClickListener() {
public void onClick(View v) {
finish ();
}
};
void initializeDPM ( ) {
if (!devicePolicyManager.isAdminActive(demoDeviceAdmin)) {
Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN,
demoDeviceAdmin);
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,
"Additional text explaining why this needs to be added.");
startActivityForResult(intent, ACTIVATION_REQUEST);
} else {
devicePolicyManager.lockNow();
}
}
public void activate ( ) {
// Activate device administration
Intent intent = new Intent(
DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN,
demoDeviceAdmin);
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,
"told me to do this");
startActivityForResult(intent, ACTIVATION_REQUEST);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case ACTIVATION_REQUEST:
if (resultCode == Activity.RESULT_OK) {
// Has become the device administrator.
} else {
//Canceled or failed.
}
return;
}
super.onActivityResult(requestCode, resultCode, data);
}
}
My admin class
public class DemoDeviceAdminReceiver extends DeviceAdminReceiver{
#Override
public void onEnabled(Context context, Intent intent) {
super.onEnabled(context, intent);
}
#Override
public void onDisabled(Context context, Intent intent) {
super.onDisabled(context, intent);
}
}
my device_admin_sample is;
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
<uses-policies>
<limit-password />
<watch-login />
<reset-password />
<force-lock />
<wipe-data />
<expire-password />
<encrypted-storage />
<disable-camera />
</uses-policies>
</device-admin>
</LinearLayout>
Why I could not close the camera as an admin ?
I am new in android and i would like to lock the phone. So I Read through Device Admin documentation. and have my code looking like this. But it doesnt seem to notice it on my manifest suggests if i have it defined in it which i do
my manifest.xml
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity android:name=".MainLauncher"android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".Controller"android:label="#string/app_name">
</activity>
<activity android:name=".DeviceAdminSample$Controller"android:label="#string/activity_sample_device_admin">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
<receiver android:name=".DeviceAdminSample"android:label="#string/sample_device_admin"android:description="#string/sample_device_admin_description"android:permission="android.permission.BIND_DEVICE_ADMIN">
<meta-data android:name="android.app.device_admin"android:resource="#xml/device_admin_sample" />
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
</receiver>
</application>
<uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
</manifest>
My Code
public class DeviceAdminSample extends DeviceAdminReceiver {
public static class Controller extends Activity {
static final int RESULT_ENABLE = 1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mDPM = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
mAM = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
mDeviceAdminSample = new ComponentName(Controller.this, DeviceAdminSample.class);
mEnableButton = (Button)this.findViewById(R.id.button1);
mEnableButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN,
mDeviceAdminSample);
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,
"Additional text explaining why this needs to be added.");
startActivityForResult(intent, RESULT_ENABLE);
}
});
mDisableButton = (Button)this.findViewById(R.id.button2);
mDisableButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
mDPM.removeActiveAdmin(mDeviceAdminSample);
updateButtonStates();
}
});
mForceLockButton = (Button)this.findViewById(R.id.button3);
mForceLockButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Log.i(" In","In the forc lock button");
if (mAM.isUserAMonkey()) {
AlertDialog.Builder builder = new AlertDialog.Builder(Controller.this);
builder.setMessage("You can't lock my screen because you are a monkey!");
builder.setPositiveButton("I admit defeat", null);
builder.show();
return;
}
boolean active = mDPM.isAdminActive(mDeviceAdminSample);
if (active) {
v mDPM.lockNow();
}
}
});
}
void updateButtonStates() {
boolean active = mDPM.isAdminActive(mDeviceAdminSample);
if (active) {
mForceLockButton.setEnabled(true);
} else {
mForceLockButton.setEnabled(false);
}
}
}
}
My Other Activity
package com.examples;
public class MainLauncher extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mainlauncher);
Button btnLock = (Button)this.findViewById(R.id.button22);
btnLock.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
KeyguardManager keyguardManager = (KeyguardManager)getSystemService(Activity.KEYGUARD_SERVICE);
KeyguardLock lock = keyguardManager.newKeyguardLock(KEYGUARD_SERVICE);
lock.reenableKeyguard();
}
});
Button btnDevice = (Button)this.findViewById(R.id.button11);
btnDevice.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
try{
Intent openScreen = new Intent();
openScreen.setClass(MainLauncher.this, DeviceAdminSample.class);
startActivity(openScreen);
}
catch(Exception e)
{Log.i("DeviceAdmin button",String.valueOf(e));}
}
});
}
}
Have you added a resource under "xml" folder called "device_admin_sample.xml"? It will have permission required for doing a "force lock" for Device administrator to work.